【发布时间】:2017-01-11 20:20:27
【问题描述】:
我希望能够拥有一段 Lua 代码(“脚本”),可以在游戏中的敌人类型之间共享,但脚本的每个实例都有一个独特的执行环境。为了说明我的问题,这是我第一次尝试脚本的外观:
time_since_last_shoot = 0
tick = function(entity_id, dt)
time_since_last_shoot = time_since_last_shoot + dt
if time_since_last_shoot > 10 then
enemy = find_closest_enemy(entity_id)
shoot(entity_id, enemy)
time_since_last_shoot = 0
end
end
但这失败了,因为我将在所有敌人之间共享全局 time_since_last_shoot 变量。所以我尝试了这个:
spawn = function(entity)
entity.time_since_last_shoot = 0;
end
tick = function(entity, dt)
entity.time_since_last_shoot = entity.time_since_last_shoot + dt
if entity.time_since_last_shoot > 10 then
enemy = find_closest_enemy(entity)
shoot(entity, enemy)
entity.time_since_last_shoot = 0
end
end
然后为每个实体创建一个唯一的表,然后在调用 spawn 和 tick 函数时将其作为第一个参数传递。然后在运行时以某种方式将该表映射回一个 id。这可以工作,但我有几个担忧。
首先,它容易出错。脚本仍可能意外创建全局状态,这可能导致稍后在同一脚本甚至其他脚本中难以调试问题。
其次,由于 update 和 tick 函数本身是全局的,所以当我创建第二种类型的敌人并尝试使用相同的界面时,我仍然会遇到问题。我想我可以通过某种命名约定来解决这个问题,但肯定有更好的方法来处理它。
我确实找到了this 问题,它似乎在问同样的事情,但接受的答案是对细节的轻描淡写,并且指的是 Lua 5.3 中不存在的 lua_setfenv 函数。似乎它已被 _ENV 取代,不幸的是我对 Lua 不够熟悉,无法完全理解和/或翻译这个概念。
[edit] 基于@hugomg 建议的第三次尝试:
-- baddie.lua
baddie.spawn = function(self)
self.time_since_last_shoot = 0
end
baddie.tick = function(self, dt)
entity.time_since_last_shoot = entity.time_since_last_shoot + dt
if entity.time_since_last_shoot > 10 then
enemy = find_closest_enemy(entity)
shoot(entity, enemy)
entity.time_since_last_shoot = 0
end
end
在 C++ 中(使用 sol2):
// In game startup
sol::state lua;
sol::table global_entities = lua.create_named_table("global_entities");
// For each type of entity
sol::table baddie_prototype = lua.create_named_table("baddie_prototype");
lua.script_file("baddie.lua")
std::function<void(table, float)> tick = baddie_prototype.get<sol::function>("tick");
// When spawning a new instance of the enemy type
sol::table baddie_instance = all_entities.create("baddie_instance");
baddie_instance["entity_handle"] = new_unique_handle();
// During update
tick(baddie_instance, 0.1f);`
这符合我的预期,我喜欢这个界面,但我不确定它是否遵循可能比我更熟悉 Lua 的人最不意外的路径。即,我使用隐式 self 参数和我的原型/实例之间的区别。我有正确的想法还是做了一些奇怪的事情?
【问题讨论】:
标签: lua game-engine