Unityにおける親オブジェクトでの子オブジェクトの当たり判定を Func と event で管理し、動的に子オブジェクトを追加する方法

この技術資料では、Unityで親オブジェクトに属する子オブジェクトの当たり判定を親オブジェクトのスクリプトで管理し、ゲーム中に動的に追加される子オブジェクトにも同様の仕組みを適用する方法について説明します。Func と event を活用し、親オブジェクトで効率的に当たり判定を管理する手法を紹介します。


1. 前提条件

  • 親オブジェクトは複数の子オブジェクトを持っています。
  • 子オブジェクトが他のオブジェクトと衝突した際、親オブジェクトがその衝突を管理します。
  • ゲーム中に新たに子オブジェクトが追加されるケースを想定し、動的にその子オブジェクトにも当たり判定を設定します。

2. 子オブジェクトのCollider設定

各子オブジェクトには、以下の設定を行い、当たり判定ができる状態にします。

  1. 子オブジェクトにCollider(例: BoxColliderSphereCollider)を追加。
  2. 子オブジェクトにRigidbodyを追加します。静的なオブジェクトとして動かさない場合は、isKinematicを有効にします。

3. 親オブジェクトで子オブジェクトの当たり判定を管理するためのスクリプト実装

ここでは、親オブジェクトで子オブジェクトの当たり判定を管理するスクリプトを、Func と event を使用して実装します。さらに、動的に子オブジェクトが追加された際に、自動的に親の管理下に組み込む仕組みも説明します。

3.1 親オブジェクトのスクリプト (ParentCollisionHandler)

親オブジェクトがすべての子オブジェクトの衝突イベントを管理するスクリプトです。ゲーム中に新しく子オブジェクトを追加する場合にも、自動的にその衝突判定を管理できるように設計します。

using UnityEngine;

public class ParentCollisionHandler : MonoBehaviour
{
    void Start()
    {
        // シーン開始時にすでに存在する子オブジェクトに対して、当たり判定を設定
        foreach (Transform child in transform)
        {
            AddCollisionHandler(child.gameObject);
        }
    }

    // 子オブジェクトを追加した際に呼ばれるメソッド
    public void AddChild(GameObject childObject)
    {
        childObject.transform.SetParent(this.transform); // 親オブジェクトに追加
        AddCollisionHandler(childObject); // 衝突判定のハンドラを設定
    }

    // 子オブジェクトに当たり判定のハンドラを追加する
    private void AddCollisionHandler(GameObject childObject)
    {
        CollisionNotifier notifier = childObject.GetComponent<CollisionNotifier>();

        // CollisionNotifier がアタッチされていない場合は追加
        if (notifier == null)
        {
            notifier = childObject.AddComponent<CollisionNotifier>();
        }

        // 衝突イベントを登録
        notifier.OnCollisionDetected += HandleCollision;
    }

    // 衝突判定の処理
    private bool HandleCollision(GameObject collidedObject, GameObject sourceObject)
    {
        Debug.Log(sourceObject.name + " に " + collidedObject.name + " が衝突しました");
        return true;
    }
}

3.2 子オブジェクトの当たり判定を通知するスクリプト (CollisionNotifier)

子オブジェクトに対する当たり判定を管理し、親オブジェクトにそのイベントを通知するスクリプトです。

using UnityEngine;
using System;

public class CollisionNotifier : MonoBehaviour
{
    // Funcを使った当たり判定のデリゲート
    public event Func<GameObject, GameObject, bool> OnCollisionDetected;

    // OnCollisionEnterでの衝突検知
    private void OnCollisionEnter(Collision collision)
    {
        if (OnCollisionDetected != null)
        {
            OnCollisionDetected.Invoke(collision.gameObject, this.gameObject);
        }
    }

    // OnTriggerEnterでのトリガー検知
    private void OnTriggerEnter(Collider other)
    {
        if (OnCollisionDetected != null)
        {
            OnCollisionDetected.Invoke(other.gameObject, this.gameObject);
        }
    }
}

4. ゲーム中に動的に子オブジェクトを追加する例 (GameController)

ゲーム中に新しい子オブジェクトを追加する場合、この例ではスペースキーを押したときに新しい子オブジェクトを生成し、親オブジェクトに追加しています。

using UnityEngine;

public class GameController : MonoBehaviour
{
    public ParentCollisionHandler parentCollisionHandler;
    public GameObject prefab; // 追加する子オブジェクトのプレハブ

    void Update()
    {
        // スペースキーが押された時に新しい子オブジェクトを追加
        if (Input.GetKeyDown(KeyCode.Space))
        {
            GameObject newChild = Instantiate(prefab); // 子オブジェクトを生成
            parentCollisionHandler.AddChild(newChild); // 親オブジェクトに追加
        }
    }
}

5. スクリプトの説明

  1. ParentCollisionHandler:
    • シーン開始時に既存の子オブジェクトに対して当たり判定を設定します。
    • AddChildメソッドを使って、ゲーム中に動的に追加された子オブジェクトにも当たり判定の管理を追加します。
  2. CollisionNotifier:
    • 子オブジェクトにアタッチされ、OnCollisionEnterOnTriggerEnterでの当たり判定が発生したときに、親オブジェクトに通知します。
    • Func<GameObject, GameObject, bool>型のイベントを使用して、衝突したオブジェクトと元のオブジェクトを引数にとり、処理を行います。
  3. GameController:
    • ゲーム中に新しい子オブジェクトを追加するための処理を実装します。スペースキーを押すことで、新しい子オブジェクトが生成され、親オブジェクトの当たり判定管理に自動的に組み込まれます。

6. 動的に子オブジェクトを管理する利点

  • 柔軟なオブジェクト管理: ゲーム中に新しい子オブジェクトが追加される際、そのオブジェクトも親オブジェクトの管理下に自動的に組み込むことができ、開発が効率化されます。
  • イベント駆動設計Func と event を使うことで、オブジェクト間のイベント通知を簡潔にし、複雑なロジックをシンプルに実装できます。
  • パフォーマンスの向上: 親オブジェクトが全体の当たり判定を一括管理するため、オブジェクト間の通信や処理が効率的に行われます。

7. 追加機能の考慮

  • 子オブジェクトが削除される場合の対処:
    子オブジェクトが削除された際に、そのオブジェクトのイベントリスナーを解除することが必要です。これを行うには、OnDestroyメソッドでイベントを解除する仕組みを導入できます。

まとめ

この技術資料では、Unityにおける親オブジェクトでの子オブジェクトの当たり判定を管理し、動的に追加された子オブジェクトにも自動的にその管理を適用する方法を紹介しました。Func と event を使用することで、衝突判定を効率的に処理し、ゲーム中の柔軟なオブジェクト管理が可能になります。

Unity

Posted by hidepon