数值程序化 lua中的load运用
[TOC]
数值条件
以下是游戏中常见条件达到逻辑
- 收集X个Y道具
- 角色达到Y级开启
- 任意一个装备升级到Y品质 …
如何在策划配置表中,定义以上规则?常见的办法就是预先定义事件类型X和事件值Y,代码中监听事件X,根据事件的具体逻辑计算相关当前值与事件Y比较,以得出是否满足配置项的条件。
目标类型 | 说明 |
---|---|
1 | 获得道具 |
2 | 角色当前等级 |
3 | 升级装备 |
配置数值 | 说明 |
---|---|
{1, X, Y} | 收集X个Y道具 |
{2, Y} | 角色达到Y级开启 |
{3, Y} | 任意一个装备升级到Y品质 |
对于多条件与/或运算,需要新增字段表达与/或的语义
假设 1
表示与逻辑, 0
表示或逻辑
所集X个Y道具,并且角色达到Y级开启的配置则为
{{1, X, Y}, 1, {2, Y}}
数值条件 程序化
按我的工作了解,几乎所有的项目都是按类似的格式来配置条件数值,且工作得很好。但在程序猿的角度,”不爽点”就是条件的表现形式不直观,又或者说当数值策有稍微的代码逻辑能力时,是否可以将数值表达式,更”程序化”呢!
配置数值 | 说明 |
---|---|
“item_count(X) >= Y” | 收集X个Y道具 |
“role_lvl >= Y” | 角色达到Y级开启 |
“equip_quality_count >= Y” | 任意一个装备升级到Y品质 |
在lua中可以利用load
来实现数值程序化
- 支持逻辑运算
- 支持自定义条件变量
- 支持自定义条件方法
--- require above lua 5.3
-- file: keyworlds.lua
local keyworlds = {
func_map = {
item_count = function (role, item_id)
local item_map = role.item_map
local item = item_map[item_id]
if item == nil then
return 0
end
return item.count or 0
end,
equip_quality_count = function(role, quality)
local equip_map = role.equip_map
local count = 0
for _, data in pairs(equip_map) do
if data.quality == quality then
count = count + 1
end
end
return count
end,
},
var_map = {
role_lvl = function (role)
return role.level
end
}
}
-- file: exp.lua
local exp = {}
function exp.new(s)
local obj = setmetatable({}, {__index = exp})
obj:init(s)
return obj
end
function exp:init(s)
self._role = nil
self._env = {
func_map = keyworlds.func_map,
var_map = keyworlds.var_map,
}
setmetatable(self._env, {
__index = function (_, k)
local var = self._env.var_map[k]
local func = self._env.func_map[k]
if var ~= nil then
local ok, v = pcall(var, self._role)
if not ok then error(v) end
return v
elseif func ~= nil then
return function (...)
local ok, v = pcall(func, self._role, ...)
if not ok then error(v) end
return v
end
end
return nil
end
})
self.str = s
local func, err = load("return " .. self.str, "exp", "t", self._env)
if not func then
error(string.format("%s %s", self.str, err))
end
self.func = func
end
function exp:run(role)
self._role = role
local func, result = pcall(self.func)
if not func then
error(string.format("%s %s", self.str, result))
end
return result
end
测试代码如下:
local role = {
level = 1,
item_map = {[1] = {count=100}},
equip_map = {[11001] = {quality=1}}
}
print(exp.new("item_count(1) >= 0"):run(role)) -- false
print(exp.new("role_lvl >= 1"):run(role)) -- true
print(exp.new("equip_quality_count(1) >= 0"):run(role)) -- true
print(exp.new("role_lvl > 0 and item_count(1) < 0"):run(role)) -- false
总结
- 程序化使条件表达式更强大了。但正如上文提到,如果数值策划人员不懂代码,将增大数值配置难度且更易出错。
- 从过往的经验来说,大于等于和与这两个语义逻辑就够用了。基本上满足所有的任务、成就和活动条件判断,做成程序化显然大材小用。
load
的代码其它是一段lua代码,前端要考虑会被注入代码的风险。
并不是数值配置程序化,就没意义。是否真的需要将数值程序化,要视具体业务需求而定。如果运用在AI行为树的配置上就会十分高效(各种复杂条件下的逻辑变换),而且能担负起这项工作的策划必需具备代码逻辑运算的思维能力。
原文:
https://lizijie.github.io/2022/06/11/%E6%95%B0%E5%80%BC%E7%A8%8B%E5%BA%8F%E5%8C%96-lua%E4%B8%AD%E7%9A%84load%E8%BF%90%E7%94%A8.html
作者github:
https://github.com/lizijie
PREVIOUS整理常用linux命令
NEXTlua代码规范