Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
学ぶ State Transition | 敵の行動
Unityでの格闘ゲーム

bookState Transition

メニューを表示するにはスワイプしてください

public class Transition
{
    Func<bool> condition;
    List<StatePourcentage> availableStates;

    public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage)
    {
        this.condition = condition;
        availableStates = new List<StatePourcentage>();
        for (int i = 0; i < statePourcentage.Length; i++)
        {
            availableStates.Add(statePourcentage[i]);
        }
    }

    public State GetState()
    {
        float percentage = UnityEngine.Random.Range(0, 100);
        float currentPercentage = 0;
        foreach (var statePer in availableStates)
        {
            currentPercentage += statePer.percentage;
            if (percentage <= currentPercentage)
            {
                return statePer.state;
            }
        }
        return null;
    }

    public bool IsConditionMet()
    {
        return condition();
    }
}
public class StatePourcentage
{
    public State state;
    public float percentage;

    public StatePourcentage(State state, float percentage)
    {
        this.state = state;
        this.percentage = percentage;
    }
}

これらの図では、Transition クラスと StatePourcentage クラスが示されています。これらのクラスは、特定の条件と確率に基づいて異なる状態間の遷移を管理するために連携します。このコードが何をしているのかを簡単に説明します。

解説

StatePourcentage クラス

クラス定義: public class StatePourcentage の行は、StatePourcentage という名前のクラスを定義します。このクラスは、状態とその状態に遷移する確率情報を保持します。

メンバ変数:

public State state; は状態への参照を保持します。 public float percentage; はこの状態に遷移する確率を保持します。

コンストラクタ:

public StatePourcentage(State state, float percentage) はコンストラクタメソッドです。Statefloat をパラメータとして受け取り、それぞれメンバ変数に代入します。

Transition クラス

クラス定義: public class Transition の行は、Transition という名前のクラスを定義します。このクラスは、条件と確率に基づいて状態間の遷移ロジックを管理します。

メンバ変数: Func<bool> condition; は条件関数を保持するデリゲートです。この関数は遷移条件が満たされているかどうかを示すブール値を返します。

List<StatePourcentage> availableStates; は複数の StatePourcentage オブジェクトを保持するリストで、遷移先となる可能性のある状態とその確率を表します。public Transition(Func<bool> condition, params StatePourcentage[] statePourcentage) はこのリストを指します。

コンストラクタ: StatePourcentage はコンストラクタメソッドです。条件関数と condition オブジェクトの配列をパラメータとして受け取ります。受け取った条件関数で availableStates メンバ変数を初期化し、配列内の各 StatePourcentage オブジェクトを新しいリストに追加します。

GetState メソッド: public State GetState() は、ランダムな選択と指定された確率に基づいて遷移先の状態を決定するメソッドです。0から100までの乱数を生成し、利用可能な状態の確率を累積しながら、乱数に該当する状態を見つけます。

IsConditionMet メソッド: public bool IsConditionMet() は、条件関数を呼び出して遷移条件が満たされているかどうかを確認するメソッドです。条件関数の結果を返します。

敵キャラクターにおける動作

遷移の設定: 状態間の遷移を定義し、それぞれの遷移が発生する条件や、各状態への遷移確率を指定します。

次の状態の決定: 遷移が発動すると、GetState() メソッドが定義された確率に基づいて次の状態をランダムに選択します。これにより、敵の行動に予測不可能性が加わり、よりダイナミックで挑戦的な動きになります。

条件の確認: IsConditionMet() メソッドは、遷移条件が満たされているかどうかを確認するために使用されます。条件が真の場合、遷移が発生し、GetState() メソッドが次の状態を決定します。

ステートマネージャー

public class StateManager
{
    State currentState;
    Dictionary<State, List<Transition>> stateTransitions;

    public StateManager(State startingState)
    {
        currentState = startingState;
        currentState.StartState();
        stateTransitions = new Dictionary<State, List<Transition>>();
    }

    public void AddStateTransition(State state, Transition transition)
    {
        if (!stateTransitions.ContainsKey(state))
        {
            stateTransitions.Add(state, new List<Transition>());
        }
        stateTransitions[state].Add(transition);
    }

    public void ChangeState(State newState)
    {
        currentState.EndState();
        currentState = newState;
        currentState.StartState();
    }

    public void UpdateStates(float deltaTime)
    {
        currentState.UpdateState(deltaTime);
        List<Transition> stateTransitionsList = stateTransitions[currentState];
        if (stateTransitionsList == null || stateTransitionsList.Count == 0) return;
        foreach (var transition in stateTransitionsList)
        {
            if (transition.IsConditionMet())
            {
                ChangeState(transition.GetState());
                break;
            }
        }
    }
}

変更点と追加点

ステート遷移ディクショナリ: Dictionary<State, List<Transition>> stateTransitions; は、各ステートごとに遷移のリストを保持するディクショナリ。各ステートに対して、更新時にチェックされる可能性のある遷移リストが関連付けられる。

コンストラクタ: stateTransitions = new Dictionary<State, List<Transition>>(); は、コンストラクタ内で stateTransitions ディクショナリを初期化し、異なるステートの遷移を格納できるようにする。

AddStateTransition メソッド: public void AddStateTransition(State state, Transition transition) は、指定したステートの遷移リストに遷移を追加するメソッド。ディクショナリにそのステートのエントリが存在しない場合は、新たに空の遷移リストを作成して追加する。その後、指定したステートの遷移リストに遷移を追加する。

UpdateStates メソッド: UpdateStates メソッドは、まず currentState.UpdateState(deltaTime); で現在のステートを更新した後、現在のステートに関連付けられた遷移リストを取得して遷移をチェックするように変更されている。各遷移について transition.IsConditionMet() で条件を判定し、条件が満たされた場合は ChangeState(transition.GetState()); でステートを変更し、ループを抜けて一度の更新で複数のステート遷移が発生しないようにしている。

これらの変更が行われた理由

stateTransitions ディクショナリと AddStateTransition メソッドの追加により、StateManager は各ステートごとに複数の遷移を管理できるようになり、ステートマシンの柔軟性と複雑性が向上する。UpdateStates メソッド内で動的に遷移をチェックすることで、StateManager は敵キャラクターがリアルタイムでさまざまなイベントや条件に応答できるようになる。更新されたメソッドは、まず現在のステートのロジックを実行し、その後に遷移をチェックすることで、ステートロジックの正しい実行と遷移判断の順序を保証している。

これらの変更を実装することで、StateManager はより複雑で多様な挙動に対応できるようになり、敵キャラクターの行動がゲーム環境に対してより動的かつ柔軟に反応するようになります。

すべて明確でしたか?

どのように改善できますか?

フィードバックありがとうございます!

セクション 3.  4

AIに質問する

expand

AIに質問する

ChatGPT

何でも質問するか、提案された質問の1つを試してチャットを始めてください

セクション 3.  4
some-alt