# 使用零件编程
# 内置函数
现在我们已经把零件通过挂接到预设的方式,在场景中实例化了,下面我们可以进行零件的编程了。
当然,你也可以先进行零件的编程,再进行他的挂接和实例化。
我们找到上一步创建的零件的文件夹,然后双击打开ChatPart.py,这里把他的代码粘贴在下方。
你可以发现,在零件的代码中,我们已经为你生成了总计6个内置函数,这些函数就是零件代码的逻辑入口。
# -*- coding: utf-8 -*-
from Preset.Model.PartBase import PartBase
from Preset.Model.GameObject import registerGenericClass
@registerGenericClass("ChatPart")
class ChatPart(PartBase):
def __init__(self):
super(ChatPart, self).__init__()
self.name = "Chat"
def InitClient(self):
pass
def InitServer(self):
pass
def TickClient(self):
pass
def TickServer(self):
pass
def DestroyClient(self):
pass
def DestroyServer(self):
pass
他们分别是这些逻辑的入口:
- _init_:零件初始化时,一般仅在此声明变量
- InitClient:零件实例的客户端初始化时
- InitServer:零件实例的服务端初始化时
- TickClient:零件实例的客户端每帧调用
- TickServer:零件实例的服务端每帧调用
- DestroyClient:零件实例的客户端销毁时
- DestroyServer:零件实例的服务端销毁时
直接在脚本里重写这些函数就可以在这些时机执行对应的逻辑。
# 零件python编程
接下来,我们使用零件来实现一个简单的逻辑,我们在聊天栏输入“摧毁”时,摧毁这个零件的父预设实例。
当一个实例被摧毁时,挂接在他下面的所有实例也会跟着摧毁,所以,在这种情况下展览台预设下的。
代码如下,由于我们只用到服务端的初始化和销毁时,所以我们可以把其他的内置函数删除。
可以看到,我们在InitServer里监听了ServerChatEvent事件,当系统(我的世界)里发生玩家的聊天框输入时,会调用零件的OnServerChat函数。
然后我们在OnServerChat函数中判断,如果玩家输入的是摧毁,就摧毁父预设。
def InitServer(self):
import mod.server.extraServerApi as serverApi
self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerChatEvent", self, self.OnServerChat)
def DestroyServer(self):
import mod.server.extraServerApi as serverApi
self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerChatEvent", self, self.OnServerChat)
def OnServerChat(self, args):
# 生成掉落物品
# 当我们输入的信息等于摧毁时,摧毁父节点
if args["message"] == "摧毁":
self.GetParent().Destroy()
当前我们已经支持在文件头 import 大部分库/文件。
如果产生了报错,可以在使用时 import。
# 使用Mod开发包测试结果
点击编辑器右上角的运行,进行本作品的开发测试。
使用0.16.12(7月15日更新),或者更高版本的MC Studio新建的作品,只能使用1.23或更高版本的开发包进行开发测试
在运行的开发包中可以看到场景中的2个实例。
按回车调出指令窗,输入:摧毁,此时只有一个展览台实例被摧毁了,但两个展览台是都应该被摧毁的。
MC的事件机制是当一个事件的函数执行完毕时,才会发送下一个事件,而我们在执行的过程中进行了事件的反监听,导致了这一问题。
所以我们修改一下代码,让删除父节点的行为在事件触发的下一帧执行。
在资源管理器里找到Chat零件的文件夹,然后右键空白处,选择打开当前文件夹,我们在Windows的资源管理器内创建一个新的python文件,命名为coroutineMgrGas.py,然后将如下代码复制进去(此部分代码涉及的知识点较深,可以先按步骤操作):
# -*- coding: utf-8 -*-
import time
# 这个类的作用是延迟执行给定的函数
# 使用参考每个具体使用的地方,yield 正数为时间,负数为帧数
class CoroutineMgr(object):
coroutines = {}
globalEnd = []
addCoroutines = {}
@classmethod
def StartCoroutine(cls, iter):
cls.addCoroutines[iter] = 0
return iter
@classmethod
def StopCoroutine(cls, iter):
cls.globalEnd.append(iter)
@classmethod
def Tick(cls):
if cls.addCoroutines:
for c,v in cls.addCoroutines.iteritems():
cls.coroutines[c] = v
cls.addCoroutines = {}
if cls.globalEnd:
for c in cls.globalEnd:
if cls.coroutines.get(c):
del cls.coroutines[c]
cls.globalEnd = []
ended = []
for c, v in cls.coroutines.iteritems():
try:
if v < 0:
v += 1
cls.coroutines[c] = v
if v == 0 or (v > 0 and time.time() >= v):
newv = c.next()
if newv > 0:
newv = newv + time.time()
cls.coroutines[c] = newv
except StopIteration:
ended.append(c)
for c in ended:
del cls.coroutines[c]
然后修改ChatPart.py的代码如下:
from coroutineMgrGas import CoroutineMgr
……
def TickServer(self):
CoroutineMgr.Tick()
def OnServerChat(self, args):
# 生成掉落物品
# 当我们输入的信息等于摧毁时,摧毁父节点
if args["message"] == "摧毁":
CoroutineMgr.StartCoroutine(self.DelayDestroy())
def DelayDestroy(self):
yield -1
self.GetParent().Destroy()
现在我们再进行开发测试,可以看到现象正常了!
# 使用属性面板修改零件
我们在资源管理器中点击Chat.part,可以在他的属性面板中发现它的两个配套文件。除了在ChatPart.py里编程之外,我们还可以利用ChatPartMeta.py将ChatPart.py中的变量暴露到编辑器的属性面板中。
点击配套文件右侧的小图标可以直接打开它。
首先,我们先改造一下ChatPart.py,将“摧毁”作为一个变量使用。
def __init__(self):
super(ChatPart, self).__init__()
self.name = "Chat"
self.message = "摧毁"
def OnServerChat(self, args):
if args["message"] == self.message:
......
改造后的零件在使用上与之前没有什么区别,接下来,我们打开ChatPartMeta.py,这里面已经自动帮我们写好了一些必要的代码,我们在这个文件中键入1行代码,整体效果如下:
@sunshine_class_meta
class ChatPartMeta(PartBaseMeta):
CLASS_NAME = "ChatPart"
PROPERTIES = {
"message": PStr(group="默认", text="信息"),
}
然后返回编辑器,我们可以发现,Chat.part的属性面板中增加了我们自己定义的“信息”变量。
接下来,我们在舞台上找到Chat零件,分别把两个展览台预设的Chat零件的信息更改为“左”和“右”,然后保存并重新点击运行进行开发测试。
我们打开聊天窗口,输入:右。
这次,只有右边的展览台实例被删除了!
← 拼装预设和零件 使用预设制作AddOn →