如何为多个实体共享/重用 Lua 脚本?

发布于 2024-12-13 14:40:13 字数 605 浏览 3 评论 0原文

我正处于使用 Lua 脚本编写的 C++ 游戏的设计/骨架编码阶段,但遇到了一个设计问题:

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

它很简单而且防弹,但我认为加载、编译和存储创建相同实体类型的每个实例的相同字节代码的附加副本是一种悲剧性的浪费,所以我想找出一个更聪明的解决方案。

这是我想到的两种解决方案。我对编程、C 或 OO 概念并不陌生,但我仍在学习 Lua,尤其是 Lua/C API。我认为我的想法是合理的,但我什至不确定如何实现它们。:

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

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

I'm in the design/skeleton coding phase of my C++ game with Lua scripting, but I have run into a design issue:

The game will have many copies of the same kind of entities, with behavior controlled by the same script. Is there a straightforward way I can share the script between entities of the same type in a single lua_state? I have only been able to find this question asked a couple of times on the Internet; I have read mixed feedback on whether or not it's a good idea to load the same script in different lua_state's, and not in-depth feedback on alternatives.

It's simple and bullet-proof, but I think loading, compiling, and storing addition copies of the same byte code with each instance of the same entity type created is a tragic waste, so I would like to figure out a smarter solution.

These are the two solutions I have thought of. I'm not new to programming or C or OO concepts but I am still learning when it comes to Lua and especially the Lua/C API. I think my ideas are sound but I am not even sure how I would go about implementing them.:

  1. Implement OO in the Lua script and have each entity be represented by a Lua object; all the Lua logic would act on the object. This would also have the benefit (or the "benefit") of allowing the global environment to be changed by anything single entity.

  2. Encapsulate each entity in its own environment using setfenv and copy references of all of the functions from the global space. As I understand it the env is just a different table than the default global, but I've looked into setfenv but I don't know how I would do that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

故人如初 2024-12-20 14:40:13

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

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

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

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

然后,使用 lua_loadstring 或 lua_loadfile 加载脚本。这会在 Lua 堆栈上放置一个代表该 Lua 脚本的函数。然后,您可以使用 lua_setfenv 将此表应用为该脚本函数的环境。然后,您可以运行该脚本,传递您想要的任何变量(实体的名称等)。

1 and 2 are just different sides of the same coin, more or less. It's simply a matter of where the object goes. In type 1, the object is an explicit part of the Lua script. Which means the script decides how it wants to set up its objects.

In type 2, the object is the environment. It is still a Lua table, but one created for it by the external code. The script cannot break free of the confines of this object, except in the ways that the external code allows.

The easiest way for me to implement type 1 would be with Luabind. I'd have an AI object as a C++ class, which Lua would be able to derive from. Running the "main script" for that AI would create an instance of that class. You would pass the script parameters, like the name of the entity it controls, maybe a reference it can use to control it, etc.

Type 2 is fairly simple. First, you create the new environment by creating an empty table and populating it with the global variables that you want the user to be able to have access to. These would be for things like talking to game-state (find other objects in the scene, etc), ways to move the entity in question around, and so forth. There are metatable tricks you can play to effectively make these values immutable and constant, so the user can't modify them later.

Then, you load the script with lua_loadstring or lua_loadfile. This puts a function on the Lua stack that represents that Lua script. Then you apply this table as that script function's environment with lua_setfenv. You can then run that script, passing whatever variables you wish (the name of the entity, etc).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文