lua - 这是在 Lua 中为我的 FSM 图实现基本 FSM 的正确方法吗?
问题描述
你好 Stack Overflow 社区!Sooo 我正在尝试根据我制作的这个 FSM 图在我的 Roblox 游戏中为 AI 实现一个基本的 FSM。我将在图表之后展示模块,并举例说明我如何在我的 NPC 模块中使用它。我查看了很多其他语言的 FSM 实现,它们看起来更容易,因为我对 Lua 还很陌生。这看起来像是 FSM 实施的一个不错的开始吗?如果不是,我可以改进什么以及 FSM 中最常用的功能是什么?我正在尝试了解 FSM 模型,因为我将使用 AI 开发游戏,并且不想要大量的 if、else、booleans 等...感谢任何可以让我更深入地了解我的人可以多学这门课!
图表
状态模块:
local State = {}
State.__index = State
function State:New()
local newState = {
Init = function() print("Init ran") end,
Update = function() print("Updating") end,
Enter = function() print("Entering") end,
Exit = function() print("Exiting") end,
}
setmetatable(newState, self)
print("Created new state")
return newState
end
return State
状态机模块:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local State = require(ReplicatedStorage:WaitForChild("State"))
local StateMachine = {}
StateMachine.__index = StateMachine
function StateMachine:Create()
local machine = {}
machine.initState = State:New()
machine.currentState = machine.initState
machine.currentState.Init()
setmetatable(machine, self)
return machine
end
function StateMachine:Update()
if self.currentState ~= nil then
self.currentState:Update()
end
end
function StateMachine:SetState(state)
assert(state ~= nil, "Cannot set a nil state.")
self.currentState:Exit()
self.currentState = state
self.currentState.Init()
self.currentState.Enter()
end
return StateMachine
这是我使用我的 FSM 版本的方式。
例子:
newZombie.stateMachine = StateMachine:Create()
newZombie.idleState = State:New()
newZombie.idleState.Init = function()
print("idle state init")
end
newZombie.idleState.Enter = function()
print("idle state enter!")
end
newZombie.idleState.Update = function()
print("idle state updating!")
if not newZombie.target then
print("Getting target")
newZombie.target = newZombie:GetNearestTarget()
end
if newZombie.zombieTarget then
print("Found target")
newZombie.stateMachine:SetState(newZombie.chaseState)
end
end
newZombie.chaseState = State:New()
newZombie.chaseState.Init = function()
print("chaseState init")
end
newZombie.chaseState.Enter = function()
print("chaseState enter")
end
newZombie.chaseState.Update = function()
print("chaseState updating!")
if newZombie.target then
local direction = (newZombie.target.Position - newZombie.rootPart.Position).Unit * 0.5
local distanceToTarget = (newZombie.target.Position - newZombie.rootPart.Position).magnitude
local MAX_ATTACK_RADIUS = 4
local ray = Ray.new(newZombie.rootPart.Position, (newZombie.target.Position - newZombie.rootPart.Position).Unit * 500)
local ignoreList = {}
for i, v in pairs(ZombiesServerFolder:GetChildren()) do
table.insert(ignoreList, v)
end
local hit, position, normal = Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
if not hit.Parent:FindFirstChild("Humanoid") then
print("Walk Path")
end
if distanceToTarget >= MAX_ATTACK_RADIUS then
newZombie.rootPart.CFrame = newZombie.rootPart.CFrame + direction
else
newZombie.stateMachine:SetState(newZombie.attackState)
end
else
newZombie.stateMachine:SetState(newZombie.idleState)
end
end
newZombie.attackState = State:New()
newZombie.attackState.Init = function()
print("attackState init")
end
newZombie.attackState.Enter = function()
print("attackState enter")
end
newZombie.attackState.Update = function()
print("attackState updating!")
if newZombie.target then
local distanceToTarget = (newZombie.target.Position - newZombie.rootPart.Position).magnitude
local MAX_ATTACK_RADIUS = 4
if distanceToTarget >= MAX_ATTACK_RADIUS then
newZombie.stateMachine:SetState(newZombie.chaseState)
end
end
end
----------------------------------------------------
---- STARTING STATE ----
----------------------------------------------------
newZombie.stateMachine:SetState(newZombie.idleState)
----------------------------------------------------
同样在 NPC 更新功能中,我正在更新状态机当前状态更新功能。
if self.stateMachine then
self.stateMachine:Update()
end
解决方案
推荐阅读
- c - 通过 execve 从子级调用的排序不会自然终止
- java - 如何将 CSV 中的数据存储到 Java 中的数组中?
- python - 用户输入预期的浮点数,但变成了字符串 Python
- android - 如何使用 Room Db 返回 Rx Single 交易?
- webserver - 如何将我的文件上传到网络服务器?
- ibm-cloud - IBP 2.0 - 如何下载加密配置装置和实例化 Fabric SDK?
- swift - 无法将类型“(SwipeableTabBarController).Type”的值转换为预期的参数类型“UIView”
- jestjs - 为什么 Jest 需要 Babel 来测试异步代码?
- python - 即使在 pip install pydotplus 之后它说 No module named 'pydotplus' 应该怎么做?
- laravel - 需要用 VUEJS 同时遍历 2 个对象