有多种方式来支持游戏脚本,这是一个滑动的比例尺。
一方面,你可以几乎使用所有的脚本语言运行,因此你可以使用脚本定义所有的数据、逻辑等,只需在 C/C++ 中具有一些核心引擎功能。在这种方案中,几乎所有的 C/C++* 都只是为了使其足够高效或者因为它已经用那种语言编写了并且重新实现会很昂贵。
另一方面,你可以将大部分游戏代码和数据定义在 C/C++ 中,并实现绑定和/或回调以允许通过脚本进行一些自定义。绑定(例如
LuaBind)允许你的脚本获取和设置值/调用在脚本代码中未定义但在 C/C++ 侧定义的函数。回调允许脚本监听触发的游戏事件;例如你可能有一个脚本在实体即将受到伤害时被调用。然后你可以通过脚本自定义/扩展你的游戏逻辑。
这本书《游戏引擎架构》做了很好的解释,但没有包含示例代码或其他类似内容。
脚本编写的实现方式在很大程度上取决于您选择哪些核心和脚本语言。如果您想要更具体的内容,请尝试关注某些语言选择(例如C ++和Lua),然后找到一些教程,例如这个。
为什么要使用脚本取决于所采取的方法,但通常是为了将游戏功能/行为/数据与游戏引擎的本质分离。这样可以更容易地进行更改,因为您可以在运行时重新加载脚本而无需重建项目的其余部分。一个良好实现的脚本系统也可以使人们更轻松地参与,或者在不打扰程序员的情况下对游戏进行修改和扩展。
具体实例:
您可能希望构建一个功能,告诉玩家他们在一轮中造成了多少伤害。
如果您在C++/核心方面执行此操作,则意味着需要让程序员放入大量非常具体的代码来服务于非常特定的功能,重新构建整个项目并部署新版本。 然后他们与设计人员检查所有内容是否完美。 如果不是,则必须重新编码和重建,耗费大量时间。
通过良好设计的脚本系统,只需将round_damage.lua脚本放入脚本文件夹即可。 游戏启动时自动捕获并激活脚本,每次玩家受到伤害时触发"OnDamageReceived"处理程序。 当回合结束时,触发OnRoundEnded回调,脚本将显示一条消息。
如果公开提供了丰富的钩子,脚本编写者可以在没有程序员帮助的情况下完成所有这些工作。 如果他们犯了错误或想尝试其他东西,则可以立即重新加载脚本而无需关闭游戏。
*注意,我说C/C++用于核心引擎部分,因为这是常见的选择,但它可以是任何足够快的语言来满足您的需求。