游戏演员的剧本

Scripts for game actor

本文关键字:游戏      更新时间:2023-10-16

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

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

  1. 我想的是一个表,它的键值是actorID(唯一),值是从基类继承的类,但当重新加载脚本时,这有点困难。

    Objects[ActorID] = Model(paramater)

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

  2. 也许也可以为每个演员创建一个新的lua状态。

我的灵感来自Leadwerks引擎:http://www.youtube.com/watch?v=z-EuS1EYk8o

如果有人知道一本在游戏引擎中编写脚本的好书,请告诉我

我想我明白了:

这里有一些伪代码:

新建ActorCreated:

//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

可以工作;)

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

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

最后要注意的是,如果你为每个参与者创建新的lua_State,那么你将失去在lua中在他们之间自由传递东西的能力,并且必须编写C++代码来手动在两个(或多个)lua_Sates之间传递数据。

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

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

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