Scripting 如何为多个实体共享/重用Lua脚本? 我在我的C++游戏的设计/骨架编码阶段,使用了Lua脚本,但是我遇到了一个设计问题:

Scripting 如何为多个实体共享/重用Lua脚本? 我在我的C++游戏的设计/骨架编码阶段,使用了Lua脚本,但是我遇到了一个设计问题:,scripting,lua,entity,luac,Scripting,Lua,Entity,Luac,游戏将有许多相同类型实体的副本,行为由同一脚本控制。有没有一种简单的方法可以在一个lua_状态下在相同类型的实体之间共享脚本?我只能在互联网上发现这个问题被问了几次;我读过关于在不同的lua_州加载相同的脚本是否是一个好主意的混合反馈,而不是关于替代方案的深入反馈 它简单且防弹,但我认为在创建相同实体类型的每个实例时加载、编译和存储相同字节码的附加副本是一种悲惨的浪费,因此我想找出一个更智能的解决方案 这是我想到的两个解决方案。我对编程、C或OO概念并不陌生,但对于Lua,尤其是Lua/CAPI

游戏将有许多相同类型实体的副本,行为由同一脚本控制。有没有一种简单的方法可以在一个lua_状态下在相同类型的实体之间共享脚本?我只能在互联网上发现这个问题被问了几次;我读过关于在不同的lua_州加载相同的脚本是否是一个好主意的混合反馈,而不是关于替代方案的深入反馈

它简单且防弹,但我认为在创建相同实体类型的每个实例时加载、编译和存储相同字节码的附加副本是一种悲惨的浪费,因此我想找出一个更智能的解决方案

这是我想到的两个解决方案。我对编程、C或OO概念并不陌生,但对于Lua,尤其是Lua/CAPI,我仍然在学习。我认为我的想法是正确的,但我甚至不确定我将如何实施这些想法

  • 在Lua脚本中实现OO,并让每个实体由Lua对象表示;所有Lua逻辑都会作用于对象。这还将有一个好处(或“好处”),即允许任何单一实体改变全球环境

  • 使用setfenv将每个实体封装在自己的环境中,并从全局空间复制所有函数的引用。据我所知,env只是一个不同于默认全局表的表,但我已经研究了setfenv,但我不知道如何做到这一点


  • 1和2只是同一枚硬币的不同侧面,或多或少。这只是一个物体去哪里的问题。在类型1中,对象是Lua脚本的显式部分。这意味着脚本决定如何设置其对象

    在类型2中,对象是环境。它仍然是一个Lua表,但由外部代码为其创建。脚本无法摆脱此对象的限制,除非以外部代码允许的方式

    对我来说,实现类型1最简单的方法是使用。我将把一个AI对象作为C++类,Lua可以从中派生。运行该AI的“主脚本”将创建该类的实例。您可以传递脚本参数,比如它控制的实体的名称,或者它可以用来控制它的引用,等等

    类型2相当简单。首先,通过创建一个空表并用希望用户能够访问的全局变量填充它来创建新环境。这些将用于诸如与游戏状态对话(在场景中查找其他对象等)、移动相关实体的方法等。您可以使用一些元表技巧来有效地使这些值不可变和不变,因此用户以后不能修改它们


    然后,使用
    lua\u loadstring
    lua\u loadfile
    加载脚本。这将在Lua堆栈上放置一个函数,该函数表示该Lua脚本。然后使用
    lua\u setfenv
    将此表应用为脚本函数的环境。然后,您可以运行该脚本,传递您想要的任何变量(实体名称等)。

    我更喜欢idea 2。我希望脚本避免看到多个对象。您能解释一下为运行的脚本的每个副本设置环境所需的元表魔法吗?我也不明白你为什么要使用lua_loadfile。据我所知,它只是编译脚本而没有运行它,所以函数声明之类的东西不会被计算。@stands2reason:这就是为什么你调用它而不是
    lua\u dofile
    。因为您不能
    lua\u dofile
    并提供一个环境。记住:脚本本身只是一个函数。您希望在环境中执行该函数。您只能将环境附加到堆栈上的函数。因此,您必须使用
    lua_loadfile
    将函数加载到堆栈上,然后将环境附加到该堆栈上,然后执行该函数。因此,为了澄清这一点,setfenv在堆栈上获取一个表,并使其成为即将运行的新表。如果您使用的是元表,那么这不是一个空表吗?你能解释一下我是如何建立一个元表来共享函数的吗?等等,没关系,我想我现在明白了。这是我的样本lua_newtable(L);卢厄·塞芬夫(L,-2);等等,没关系,我想我现在明白了。这是我的示例
    首先创建不变表:
    lua_State*L=lua_open()
    luaL_加载文件(L,“scripts/test.lua”)
    lua_newtable(L)
    lua_setfenv(L,-2)