簡體   English   中英

需要幫助了解 State 機器(C#/Unity)

[英]Need help understanding State Machines (C#/Unity)

我為此苦苦掙扎了幾個星期,需要幫助來理解和為我的游戲構建 state 機器。

我需要的是這樣的:

狀態機圖

基本上,FSM class 僅用於更改狀態:

public class FSM: MonoBehaviour

public StateHandler currentState { get; private set; }

private void Start()
{
    currentState.OnEnterState();
}

public void ChangeState(StateHandler newState)
{
    currentState.OnExitState();
    currentState = newState;
    currentState.OnEnterState();
}

State class 是這樣的:

public class StateHandler : FSM
public virtual void OnEnterState()
{

}

public virtual void OnExitState()
{

}

public virtual void StateLogicUpdate()
{

}

public virtual void StatePhysicsUpdate()
{

}

void Update()
{
    StateLogicUpdate();
}

void FixedUpdate()
{
    StatePhysicsUpdate();
}

State 攻擊 class 或任何其他狀態與 State ZA2F2ED4F8EBC 和 2CBB4C21A29DC 方法相同,但沒有更新方法和實際代碼。

我有幾個問題我還不明白:

  1. 如何存儲狀態? 要更改它們,我需要從某個地方獲取它們並將它們全部放在我的游戲對象上將使它們同時工作。
  2. 這件事甚至會這樣工作嗎?)
  3. 在運行敵人行為狀態時存儲我需要訪問的敵人數據的最佳方式是什么? 只是敵人游戲對象上的另一個單一行為腳本?

如果您不介意,請像我很愚蠢一樣回答。 :) 非常感謝!

我不知道統一,但我知道 state 機器。

首先,您的 state 機器圖看起來不對勁。 “狀態”可以被視為對象,但您的矩形之一表示“抽象類”。 您永遠不能擁有抽象 class 的 object。

無論如何。 正如這個詞所說,“狀態”存儲 object 或系統的 state。 它是 memory 的一種形式。 基於 state 和外部變量,事情可能會發生

state 機器的最簡單形式在代碼中使用類似枚舉的東西

using System;

State currentState = State.Idle;

while (true)
{
    switch (currentState)
    {
        case State.Idle:
            Console.WriteLine("Doing Nothing");
            if (/* some external trigger is */true) currentState = State.Loading;
            break;
        case State.Loading:
            Console.WriteLine("Loading");
            if (/* loading issue is true, but now*/false)
            {
                Console.Error.WriteLine("Loading failed.");
                currentState = State.Idle;
            }
            if (/*loading finished is */true) currentState = State.Saving;
            break;
        case State.Saving:
            Console.WriteLine("Saving");
            // etc
            if (/*saving finished is */true) currentState = State.Idle;
            break;
    }
}

enum State
{
    Idle,
    Loading,
    Saving,
}

但是,您似乎想要一個更復雜的系統,在進入或退出特定 state 時可能會發生一些事情。 那需要更復雜的 state 類型,可以定義為抽象的 class

注意:這可能不是最好的解決方案,只是為了說明

(它甚至可能容易出錯)

internal abstract class State
{
    public virtual void OnEnter() { } //optional
    public abstract void LogicUpdate(); // required.
    public abstract void PhysicsUpdate(); // required.
    public virtual void OnExit() { } // optional
}

然后,您的每個狀態都可以是這種類型的實現。 例如:

internal sealed class IdleState : State
{
    public override void OnEnter()
    {
        Console.WriteLine("IdleEnter");
    }
    public override void LogicUpdate()
    {
        Console.WriteLine("IdleLogic");
    }
    public override void PhysicsUpdate()
    {
        Console.WriteLine("IdlePhysics");
    }
    // public override void OnExit() <-- not used in his example, as its optional
}

internal sealed class SaveState : State
{
    public override void LogicUpdate()
    {
        Console.WriteLine("SaveLogic");
    }
    public override void PhysicsUpdate()
    {
        Console.WriteLine("SavePhysics");
    }
    public override void OnExit()
    {
        Console.WriteLine("SaveExit");
    }
}

在這種情況下,你的 FSM 幾乎是正確的

internal class FSM {

    private State _currentState = new IdleState();

    public void Handler() // called from main loop
    {
        _currentState.LogicUpdate();
        _currentState.PhysicsUpdate();
        if (_currentState is IdleState)
        {
            if (/*a certain condition is*/ true) ChangeState(new SaveState());
            // remember to call ChangeState.. dont set _currentState directly
            // (might be solved with better encapsulation...)
        }
        else if (_currentState is SaveState)
        {
            if (/*a certain condition is*/ true) ChangeState(new IdleState());
        }
    }

    public void ChangeState(State newState)
    {
        _currentState.OnExit();
        _currentState = newState;
        _currentState.OnEnter();
    }
}

然后你只需要添加一個主循環:

var fsm = new FSM();

while (true)
{
    fsm.Handler();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM