4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

横国ゲーム制作部Advent Calendar 2022

Day 12

ちょっとだけ便利になるかもしれない拡張メソッド集 [Unity]

Last updated at Posted at 2022-12-12

はじめに

自分が個人的なゲーム開発をする際に使い回している拡張メソッド集を紹介します。
拡張メソッドを定義する動機ですが、例えば、Instantiateは複製したいオブジェクトを引数で渡す静的メソッドですが、拡張メソッドの形で定義しておくことでコードを書く流れに沿って記述できるようになります(書きやすくなったと感じるかは人によると思います)。

// 通常
Instantiate(gameObject);
// 拡張メソッド
gameObject.Instantiate();

なお下記メソッド群は何らかの静的クラス内に定義することを想定しています。

GetOrAddComponent

対象のGameObjectが指定したT型のコンポーネントを持つ場合はそれを取得し、なければ追加して返す拡張メソッドです。

public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component
{
    var component = gameObject.GetComponent<T>();
    return component != null ? component : gameObject.AddComponent<T>();
}

public static T GetOrAddComponent<T>(this Component component) where T : Component
{
    return GetOrAddComponent<T>(component.gameObject);
}

使い方

// GameObjectから取得するか作成して返す
var sampleMonoBehaviour = gameObject.GetOrAddComponent<SampleMonoBehaviour>();
// Componentに対しても生えている
this.GetOrAddComponent<SampleMonoBehaviour>();

Instantiate

プレハブやシーン上に既にあるインスタンスを複製(生成)して返します。

/// <summary>
/// 拡張対象のGameObjectを複製(生成)して返す
/// </summary>
public static GameObject Instantiate(this GameObject gameObject)
{
    return Object.Instantiate(gameObject);
}

/// <summary>
/// 生成後に親となるTransformを指定して、拡張対象のGameObjectを複製(生成)して返す
/// </summary>
public static GameObject Instantiate(this GameObject gameObject, Transform parent)
{
    return Object.Instantiate(gameObject, parent);
}

/// <summary>
/// 生成後の座標及び姿勢を指定して、拡張対象のGameObjectを複製(生成)して返す
/// </summary>
public static GameObject Instantiate(this GameObject gameObject, Vector3 pos, Quaternion rot)
{
    return Object.Instantiate(gameObject, pos, rot);
}

/// <summary>
/// 生成後に親となるTransform、また生成後の座標及び姿勢を指定して、拡張対象のGameObjectを複製(生成)して返す
/// </summary>
public static GameObject Instantiate(this GameObject gameObject, Vector3 pos, Quaternion rot, Transform parent)
{
    return Object.Instantiate(gameObject, pos, rot, parent);
}

/// <summary>
/// 生成後に親となるTransform、また生成後のローカル座標を指定して、拡張対象のGameObjectを複製(生成)して返す
/// </summary>
public static GameObject InstantiateWithLocalPosition(this GameObject gameObject, Transform parent,
    Vector3 localPos)
{
    var instance = Object.Instantiate(gameObject, parent);
    instance.transform.localPosition = localPos;
    return instance;
}

public static T Instantiate<T>(this T component) where T : Component
{
    return Object.Instantiate(component);
}

public static T Instantiate<T>(this T component, Transform parent) where T : Component
{
    return Object.Instantiate(component, parent);
}

public static T Instantiate<T>(this T component, Vector3 pos, Quaternion rot) where T : Component
{
    return Object.Instantiate(component, pos, rot);
}

public static T Instantiate<T>(this T component, Vector3 pos, Quaternion rot, Transform parent)
    where T : Component
{
    return Object.Instantiate(component, pos, rot, parent);
}

public static T InstantiateWithLocalPosition<T>(this T component, Transform parent,
    Vector3 localPos) where T : Component
{
    var instance = Object.Instantiate(component, parent);
    instance.transform.localPosition = localPos;
    return instance;
}

使い方

using UnityEngine;

public class InstantiateUser : MonoBehaviour
{
    [SerializeField] private SampleMonoBehaviour samplePrefab;

    private void Start()
    {
        // samplePrefabを複製して、生成したインスタンスを返却
        var createdInstance = samplePrefab.Instantiate();
        // 生成後の座標を指定
        samplePrefab.Instantiate(transform);
        // 生成後の座標・姿勢を指定
        samplePrefab.Instantiate(Vector3.zero, Quaternion.identity);
        // 生成後の座標・姿勢・親を指定
        samplePrefab.Instantiate(Vector3.zero, Quaternion.identity, transform);
        // 生成後の親・ローカル座標を指定
        samplePrefab.InstantiateWithLocalPosition(transform, Vector3.zero);
    }
}

IsInLayerMask

渡されたLayerMaskGameObjectのレイヤーを比較し、LayerMask内にGameObjectのレイヤーが含まれているかを返します。

public static bool IsInLayerMask(this GameObject gameObject, LayerMask layerMask)
{
    int objLayerMask = (1 << gameObject.layer);
    return (layerMask.value & objLayerMask) > 0;
}

public static bool IsInLayerMask(this Component component, LayerMask layerMask)
{
    return IsInLayerMask(component.gameObject, layerMask);
}

使い方

using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private LayerMask attackTarget;

    public void Attack(Enemy enemy)
    {
        // ターゲットレイヤーに含まれている場合のみ攻撃
        if (enemy.IsInLayerMask(attackTarget))
        {
        }
    }
}

Destroy

拡張対象のオブジェクトを破棄します。

public static void Destroy(this GameObject gameObject)
{
    Object.Destroy(gameObject);
}

public static void Destroy(this Component component)
{
    Object.Destroy(component);
}

/// <summary>
/// ComponentがアタッチされているGameObjectを破棄する
/// </summary>
public static void DestroyGameObject(this Component component)
{
    Object.Destroy(component.gameObject);
}

使い方

SampleMonoBehaviour sampleMonoBehaviour1 = this.AddComponent<SampleMonoBehaviour>();
SampleMonoBehaviour sampleMonoBehaviour2 = this.AddComponent<SampleMonoBehaviour>();

sampleMonoBehaviour1.Destroy();
sampleMonoBehaviour2.Destroy();
sampleMonoBehaviour2.gameObject.Destroy();
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?