Unityに関連する記事です

 ローグライト系のゲーム(Sly The Spire、ファントムローズなど)に見られる、プレイヤーが1つマスずつ移動してゴール地点へ向かいながら、
各マスごとに分岐(選択肢)があり、任意のイベントを実行しながら進行するタイプのゲームシステムの実装例です。



1.設計

 
 各マスでは色々なイベントが発生するため、イベントについてはインターフェースと抽象クラスを利用して設計します。
そしてサブクラスで「バトル」「探索」「休息」「ショップ」といった各マスでのイベントを作成するようにします。

 この方法により、ソース内では処理を抽象化し、イベントの実行命令を行うだけでイベントの詳細までは関与しない形で実装します。


2.サンプルコード   enum とインターフェースー



 最初にイベントの種類を enum で登録します。

// イベントの種類を表す列挙型
public enum EventType
{
    Battle,
    Exploration,
    Shop
}

 必要に応じて追加してください。



 次にイベント実行のインターフェースを作成します。

using System.Collections;

// イベントのインターフェース
public interface IEvent
{
    IEnumerator ExecuteEvent();
    EventType GetEventType();
}

 インターフェースは具体的な実装を提供しないため、クラスがインターフェースを実装する際に、どのように実装するかは具体的なクラスに委ねられます。
これにより、インターフェースを定義するときには、そのインターフェースを実装するクラスの詳細な実装に依存しない形で設計できます。

 また、インターフェースを使用することで、新しいクラスを追加し、既存のクラスが新しいインターフェースを実装するだけで、コードの拡張が容易に行えます。
これにより、アプリケーションの拡張や変更が簡単に行えるようになります。


3.サンプルコード◆ 蔀蠑櫂ラスー

 
 イベント用の抽象クラスを作成し、親クラスとします。

 抽象クラスは、インターフェースを実装することができます。
そのため、インターフェースを実装する複数のクラスが、共通の抽象クラスのメソッドやプロパティを持つことができます。

 これは、クラス階層での一貫性を保ち、コードの保守性を向上させるのに役立ちます。

using UnityEngine;
using System.Collections;

// イベントの抽象クラス
public abstract class EventBase : MonoBehaviour, IEvent
{
    public abstract IEnumerator ExecuteEvent(); // ExecuteEvent メソッドを抽象メソッドとして実装
    public abstract EventType GetEventType();
}

 抽象クラスにインターフェースを抽象メソッドとして実装することにより、子クラスでの振る舞いの実装を強制することができます。
これが重要な理由は、以下の通りです:


1.一貫性を維持

 インターフェースを抽象クラスに組み込むことで、すべての子クラスが同じメソッド(抽象メソッド)を持つことが保証されます。
これにより、クラス階層内で一貫性が維持され、特定のメソッドの存在が確実に保証されます。


2.実装の強制

 子クラスは抽象クラスを継承し、抽象メソッドを実装しなければなりません。
これにより、子クラスが特定のメソッドを実装しない限り、コンパイルエラーが発生します。

 つまり、望まない振る舞いの抜け漏れを防ぎ、プログラマが正しい実装を強制できます。


3.柔軟性と拡張性

 抽象クラスを使用して、インターフェースの一部のデフォルト実装を提供することもできます。
この場合、子クラスは必要に応じてデフォルトの実装を再定義することができ、より柔軟な設計を実現できます。



 このようにインターフェースと抽象クラスの組み合わせは、クラス階層を設計し、コードの柔軟性、拡張性、保守性を向上させるのに役立つ強力な手法です。
具体的な要件や設計上の要因に応じて、どちらを選択するかはプロジェクトによって異なることがあります。


4.サンプルコード ーゲームのコントローラークラスー

 
 プレイヤーとマスを制御するスクリプトを作成します。


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class GameController : MonoBehaviour
{
    public Transform player; // プレイヤーのトランスフォーム
    public List<EventBase> events; // マスに関連付けられたイベントのリスト
    private int currentPosition = 0; // 現在の位置
    private bool isEventRunning = false; // イベントが実行中かどうかのフラグ

    private bool isEventRunning = false;
    private Coroutine currentEventCoroutine;

    private void Start()
    {
        MoveToNextPosition();
    }

    private void Update()
    {
        if (isEventRunning)
            return;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // プレイヤーがボタンを押すとイベントを開始
            StartEvent();
        }
    }

    private void StartEvent()
    {
        if (currentPosition >= events.Count)
        {
            // ゲーム終了
            Debug.Log("ゲーム終了");
            return;
        }

        EventBase currentEvent = events[currentPosition];
        currentEventCoroutine = StartCoroutine(RunEvent(currentEvent));
    }

    private IEnumerator RunEvent(EventBase eventObj)
    {
        isEventRunning = true;

        // イベント実行中はゲームの進行を一時停止
        Time.timeScale = 0f;

        yield return StartCoroutine(eventObj.ExecuteEvent());

        // イベント終了まで待機
        while (isEventRunning)
        {
            yield return null;
        }

        // イベントが終了したらゲームの進行を再開
        Time.timeScale = 1f;

        currentPosition++;
        MoveToNextPosition();
    }

    public void EndEvent()
    {
        isEventRunning = false;
        currentPosition++;

        // 次のマスに移動し、ボタンを表示
        MoveToNextPosition();
    }

    private void MoveToNextPosition()
    {
        if (currentPosition < events.Count)
        {
            Vector3 nextPosition = new Vector3(currentPosition, 0, 0); // マスごとにX座標を変える
            player.position = nextPosition;

            // 次のマスにボタンを表示
            events[currentPosition].gameObject.SetActive(true);
        }
    }
}

 このサンプルコードでは、プレイヤーがスペースキーを押すとイベントが実行され、
イベントが終了すると次のマスに移動し、次のイベントのボタンを表示します。ゲームの進行はイベント実行中に停止します。


5.<処理の置き換え>


 コルーチンメソッド内部の処理には、色々なアプローチがあります。


    private IEnumerator RunEvent(EventBase eventObj)
    {
        isEventRunning = true;

        // イベント実行中はゲームの進行が停止
        // UniTaskやyield return StartCoroutineを使ってもよい
        eventObj.ExecuteEvent();

        // イベント終了まで待機
        while (isEventRunning)
        {
            yield return null;
        }
    }



private IEnumerator RunEvent(EventBase eventObj)
{
    isEventRunning = true;

    // イベント実行中はゲームの進行が停止
    yield retrurn StartCoroutine(eventObj.ExecuteEvent());

    // イベント終了まで待機
    yield return new WaitUntil(() => !isEventRunning);
}



private IEnumerator RunEvent(EventBase eventObj)
{
    isEventRunning = true;

    // イベント実行中はゲームの進行が停止
    eventObj.ExecuteEvent();

    // イベント終了まで待機
    yield return new WaitUntil(() => !isEventRunning);
}

 他にも UniTask を活用することでもリファクタリングできます。


5.サンプルコードぁ 璽汽屮ラスー


 イベント用の子クラスです。

using UnityEngine;
using System.Collections;

public class BattleEvent : EventBase
{
    public override IEnumerator ExecuteEvent()
    {
        Debug.Log("バトルイベントが発生しました。敵と戦います!");
        // バトルの実際の処理をここに追加

        // バトルが終了するまで待機
        yield return new WaitForSeconds(2.0f); // 仮の待機時間

        // バトルが終了したらイベント終了を通知
        EndEvent();
    }

    public override EventType GetEventType()
    {
        return EventType.Battle;
    }
}


コメントをかく


「http://」を含む投稿は禁止されています。

利用規約をご確認のうえご記入下さい

Menu



技術/知識(実装例)

2Dおはじきゲーム(発展編)

2D強制横スクロールアクション(発展編)

3Dダイビングアクション(発展編)

2Dタップシューティング(拡張編)

レースゲーム(抜粋)

2D放置ゲーム(発展編)

3Dレールガンシューティング(応用編)

3D脱出ゲーム(抜粋)

2Dリアルタイムストラテジー

2Dトップビューアドベンチャー(宴アセット使用)

3Dタップアクション(NavMeshAgent 使用)

2Dトップビューアクション(カエルの為に〜、ボコスカウォーズ風)

VideoPlayer イベント連動の実装例

VideoPlayer リスト内からムービー再生の実装例(発展)

AR 画像付きオブジェクト生成の実装例

AR リスト内から生成の実装例(発展)

private



このサイト内の作品はユニティちゃんライセンス条項の元に提供されています。

管理人/副管理人のみ編集できます