基本的な使い方


目的

このページでは、プロジェクトでReactive Entity Setsをセットアップして使用する手順を説明します。state構造体、entity setアセット、entityコンポーネントを作成します。


ステップ1 state構造体を定義する

エンティティデータを保持する構造体を作成します。[System.Serializable]を付与してください。

using System;

[Serializable]
public struct EnemyState
{
    public int Health;
    public int MaxHealth;
    public bool IsStunned;

    public float HealthPercent => MaxHealth > 0 ? (float)Health / MaxHealth : 0f;
    public bool IsDead => Health <= 0;
}

ステップ2 reactive entity setアセットを作成する

ReactiveEntitySetSO<T>を継承するクラスを作成します。

using Tang3cko.ReactiveSO;
using UnityEngine;

[CreateAssetMenu(
    fileName = "EnemyEntitySet",
    menuName = "Reactive SO/Entity Sets/Enemy"
)]
public class EnemyEntitySetSO : ReactiveEntitySetSO<EnemyState>
{
    // ベースクラスがすべての機能を提供
}

Projectウィンドウで以下のメニューパスを選択してアセットを作成します。

Create > Reactive SO > Entity Sets > Enemy

ステップ3 イベントチャンネルを作成する(オプション)

セットレベルの変更通知が必要な場合、イベントチャンネルを作成します。

Create > Reactive SO > Channels > Int Event

entity setのフィールドに割り当てます。

フィールド 発火タイミング
On Item Added エンティティが登録されたとき
On Item Removed エンティティが登録解除されたとき
On Data Changed いずれかのエンティティのデータが変更されたとき
On Set Changed 任意の変更時

ステップ4 entityコンポーネントを作成する

自動ライフサイクル管理のためにReactiveEntity<T>ベースクラスを使用します。

using Tang3cko.ReactiveSO;
using UnityEngine;

public class Enemy : ReactiveEntity<EnemyState>
{
    [SerializeField] private EnemyEntitySetSO entitySet;
    [SerializeField] private int maxHealth = 100;

    // 必須: 使用するセットを指定
    protected override ReactiveEntitySetSO<EnemyState> Set => entitySet;

    // 必須: 初期状態を指定
    protected override EnemyState InitialState => new EnemyState
    {
        Health = maxHealth,
        MaxHealth = maxHealth,
        IsStunned = false
    };

    public void TakeDamage(int damage)
    {
        var state = State;
        state.Health = Mathf.Max(0, state.Health - damage);
        State = state;  // 自動的にイベントをトリガー

        if (state.IsDead)
        {
            Destroy(gameObject);  // OnDisableで自動的に登録解除
        }
    }
}

ステップ5 エンティティデータをクエリする

任意のスクリプトからエンティティデータにアクセスします。

public class EnemyManager : MonoBehaviour
{
    [SerializeField] private EnemyEntitySetSO entitySet;

    public int GetTotalEnemyHealth()
    {
        int total = 0;
        entitySet.ForEach((id, state) => {
            total += state.Health;
        });
        return total;
    }
}

APIリファレンス

プロパティ

プロパティ 説明
Count int 登録されたエンティティ数
EntityIds NativeSlice<int> すべての登録エンティティID
Data NativeSlice<TData> すべてのエンティティデータ

メソッド

メソッド 説明
Register(owner, data) 初期状態でエンティティを登録
Unregister(owner) セットからエンティティを削除
GetData(owner) エンティティの現在の状態を取得
TryGetData(owner, out data) エンティティの状態を安全に取得
SetData(owner, data) エンティティの状態を更新
UpdateData(owner, func) 関数で状態を更新
NotifyDataChanged(owner) データ変更を手動で通知
Contains(owner) エンティティが存在するか確認
Clear() すべてのエンティティを削除
ForEach(action) すべてのエンティティを反復
SubscribeToEntity(id, callback) エンティティの変更をサブスクライブ
UnsubscribeFromEntity(id, callback) エンティティからサブスクライブ解除

パフォーマンス特性

Reactive Entity SetsはNativeArrayとNativeHashMapに基づくSparse Setデータ構造を使用します。

操作 時間計算量
Register O(1)
Unregister O(1)
GetData O(1)
SetData O(1)
イテレーション O(n)

データはキャッシュ効率とJob System互換性のためにNativeArrayに連続して格納されます。NativeHashMapがIDからインデックスへO(1)で変換します。


次のステップ

  • イベント - エンティティごとおよびセットレベルのサブスクリプションについて学びます
  • パターン - 一般的な使用パターンを確認します

This site uses Just the Docs, a documentation theme for Jekyll.