2

我想为我的模型/演员添加一些脚本。当加载新模型或更改脚本时,参与者会做出反应。

现在,我有一个基本 Lua 类,例如,它有一个 Update() 函数,每个模型/演员都应该重载这个函数。但是如何实施呢?主要问题是每个模型都需要一个唯一的类名称,...

  1. 我正在考虑一个表,其键值为 actorID(unique) 并且值将是从基类继承的类,但是当脚本重新加载时有点困难。

    Objects[ActorID] = Model(paramater)

    Objects[ActorID].Update = function() print("Update: actor 1") end

  2. 也许也可以为每个参与者创建一个新的 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

可以工作;)

4

1 回答 1

2

youtube 视频中引擎的工作方式不依赖于重载的更新函数。它们具有基类的原因是为它们的对象提供默认行为和公共接口,但与实际更新任何内容无关。

他们正在使用操作系统提供的功能来侦听文件更新(有关更多信息,请参阅此 SO 问题),然后只需在游戏的 lua_State 中执行脚本。由于脚本仅修改类型定义(表和元表),因此当您重新加载脚本(通过简单的 luaL_dofile 或我认为的等效文件)时,新定义会覆盖旧定义,并且 lua 会愉快地使用更新的行为。如果您真的眯着眼睛看视频在编辑器中显示的代码,您会注意到它们只是定义函数,而不是运行 Update 方法。

最后一点 - 如果您为每个参与者创建新的 lua_States,那么您将失去在 Lua 中在它们之间自由传递事物的能力,并且必须编写 C++ 代码来手动在两个(或更多)lua_States 之间传递数据。

编辑:关于从公共基础对象继承:修改其元表将改变所有对象的行为,因此我们需要防止这种情况发生。一种方法是在实体脚本周围加上防止修改实际通用元表的措施。在加载脚本之前,我们保存对基本元表的引用并将其替换为脚本可以使用的副本。

通过这种方式,脚本不需要创建自己的元表,也不需要知道引擎的其余部分将如何引用它。相反,它只使用实体之一。一旦脚本完成定义它的派生行为,我们可以给它的实体副本一个新名称(一个基于脚本文件的名称、世界对象的名称等)并将实体恢复到原始引用。

除了上述之外,我们还获得了不通过不同更新持久化更改的额外好处。每次我们想在运行时更改脚本时,我们都会重复该过程,并且可以确信,如果在之前的更新中添加了某些内容,那么在我们执行删除它的更新后它不会保留。如果我们只是让脚本覆盖元表,那么如果不将它们显式设置为 ,我们就无法删除函数和成员nil

于 2012-09-04T10:51:25.243 回答