这是在Lua中为我的FSM图实现基本FSM的正确方法吗?

时间:2019-04-24 19:20:56

标签: lua state-machine

Hello Stack Overflow社区!所以,我试图根据我制作的FSM图在我的Roblox游戏中实现AI的基本FSM。我将在图后显示模块,并举例说明如何在NPC模块中使用它。我看过许多其他语言的FSM实现,​​它们看起来更容易,因为我对Lua相当陌生。这看起来像是FSM实施的良好起点吗?如果不能,我可以改进什么,FSM中最常使用哪些功能?我正在努力掌握FSM模型的知识,因为我将从事AI游戏的开发,并且不希望出现大量的if,else,booleans等问题。谢谢任何能给我带来更多见解的人可以学习更多这个学科!


图表

AI FSM Diagram

状态模块:

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

StateMachine模块:

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

0 个答案:

没有答案