我想为我的模特/演员添加一些脚本。当加载新模型或更改脚本时,actor会做出反应。
现在,我有一个基础Lua类,例如,它有一个Update()函数,每个模型/ actor都应该重载这个函数。但是如何实现呢?主要问题是每个模型都需要一个唯一的类名,......
我在考虑一个表,其键值是actorID(唯一),值是从基类继承的类,但是当脚本重新加载时有点困难。
Objects[ActorID] = Model(paramater)
Objects[ActorID].Update = function() print("Update: actor 1") end
也许也可以为每个演员创建一个新的lua状态。
我从Leadwerks引擎获得了灵感:http://www.youtube.com/watch?v=z-EuS1EYk8o
如果有人知道一本关于游戏引擎脚本的好书,请告诉我
这是一些伪代码:
OnNewActorCreated:
//Add actor
Objects[param.ID] = createClass(baseclass)
//Check if this actor has a script to run.
if param.hasScript then
//Add the new ID to the script
Scripts[param.filename][param.ID]
Entity = Objects[param.ID]
doFile(param.filename)
Entity = nil
end
OnFileChanged:
foreach id in Scripts[changedfile] do
Entity = Objects[id]
dofile(changedfile)
Entity = nil
end
示例脚本:
//check if Entity is valid
if not Entity then
print("[Error] Entity is invalid")
else
function Entity:Update()
print(self.name)
end
end
可以工作;)
答案 0 :(得分:2)
youtube视频中的引擎工作方式不依赖于重载的Update功能。他们拥有基类的原因是为其对象提供默认行为和通用接口,但与实际更新任何内容无关。
他们使用操作系统提供的功能来监听文件更新(有关详细信息,请参阅this SO question),然后只需在游戏的lua_State中执行脚本。由于脚本只修改了类型定义(表和元表),当你重新加载脚本时(通过简单的luaL_dofile或我认为的等价物),新的定义会覆盖旧的定义,并且lua愉快地使用更新的行为。如果您真的斜视并查看视频在编辑器中显示的代码,您会发现它们只是定义函数,而不是运行Update方法。
作为最后一点 - 如果你为每个actor创建新的lua_States,那么你将无法在Lua中自由传递它们之间的东西,并且必须编写C ++代码以手动在两个(或更多)之间传递数据lua_States。
编辑:关于从公共基础对象继承:修改其元表将改变所有对象的行为,因此我们需要防止这种情况。一种方法是用防护包围实体脚本以防止修改实际的公共元表。在加载脚本之前,我们保存对基本元表的引用,并将其替换为脚本可以使用的副本。
通过这种方式,脚本不需要创建自己的元表,也不需要知道引擎的其余部分将如何引用它。相反,它只使用实体一个。一旦脚本完成定义它的派生行为,我们就可以为其Entity副本提供一个新名称(一个基于脚本文件的名称,一个世界对象的名称等),并将Entity恢复为原始引用。 / p>
除此之外,我们还获得了不通过不同更新持续更改的额外好处。每次我们想要在运行时更改脚本时,我们都会重复该过程,并且可以确信如果在先前的更新中添加了某些内容,则在执行删除它的更新后它将不会保留。如果我们只是让脚本覆盖元数据,那么我们就无法删除函数和成员而不将其明确设置为nil
。