[英]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 方法相同,但沒有更新方法和實際代碼。
我有幾個問題我還不明白:
如果您不介意,請像我很愚蠢一樣回答。 :) 非常感謝!
我不知道統一,但我知道 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.