Unity インスペクターは、エディターのリフレクション コルーチン エディターでオブジェクトを生成および破棄するためのボタンとメソッドを描画します。

アートの要件に応えて、実行せずに編集環境でプレハブをインスタンス化できるスクリプトを実装します。
ここに画像の説明を挿入します
効果は上の図のとおりです。
1 .単純な行と列のインスタンス化オブジェクト スクリプトを実装するには
2. インスペクターの下にボタンを提供します
3. メソッドを公開します (カスタム タグを通じて実装されます)。
)

需求一
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FX_init : MonoBehaviour
{
    
    
    // Start is called before the first frame update
    public GameObject PreGameObject;
    public int numCol = 4;

    public float spaceCol = 2.0f;
    
    public int numRow = 4;

    public float spaceRow = 2.0f;

    private List<GameObject> cubeTemp;
    void Start()
    {
    
    
        SetInit();
    }
    public void SetInit()
    {
    
    
        for (int i = 0; i < numCol; i++)
        {
    
    
            for (int j = 0; j< numRow; j++)
            {
    
    
                float xPos = i * spaceRow;
                float yPos = j * spaceCol;
                GameObject newObject = Instantiate(PreGameObject, new Vector3(xPos, yPos, 0), Quaternion.identity);
                cubeTemp.Add(newObject);
            }
        }

    }
    public void Clear()
    {
    
    
        for (int i = 0; i < cubeTemp.Count; i++)
        {
    
    
            DestroyImmediate(cubeTemp[i]);
        }
    }
}

上記は単純な for ループのインスタンス化スクリプトで、配列を使用して後続の破棄のためにそれらを保存します。

using UnityEngine;

[System.AttributeUsage(System.AttributeTargets.Method)]
public class InspectorButtonAttribute : PropertyAttribute
{
    
    
    public readonly string Name;

    public InspectorButtonAttribute()
    {
    
    
    }

    public InspectorButtonAttribute(string name)
    {
    
    
        Name = name;
    }
}

InspectorButtonAttribute は PropertyAttribute を継承します。 Unity では、PropertyAttribute を使用してビューアの表示プロパティをカスタマイズします。
[名前] フィールド。ビューアに表示されるボタンの名前を指定するために使用されます。
コンストラクター: 2 つのコンストラクターが提供されており、1 つはパラメーターなしで、もう 1 つは文字列パラメーター付きです。これら 2 つのコンストラクターを使用すると、オプションでボタンに名前を付けることができます。名前を指定しない場合、メソッドの名前がボタンの表示名として使用されます。
この属性の主な目的は、メソッドにマークアップを提供して、これらのメソッドを Unity インスペクタでボタンとして表示できるようにすることです。 InspectorButton カスタム エディターで、メソッドに InspectorButtonAttribute があるかどうかを確認して、ボタンとして表示するメソッドとボタンの表示名を決定します。

カスタム プロパティ属性の派生元となる基本クラス。これを使用して、スクリプト変数のカスタム属性を作成します。

カスタム属性をカスタム PropertyDrawer クラスに接続すると、その属性を持つスクリプト変数がインスペクターでどのように表示されるかを制御できます。
PropertyAttribute

using System;
using System.Collections;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(MonoBehaviour), true)]
[CanEditMultipleObjects]
public class InspectorButton : Editor
{
    
    
    public override void OnInspectorGUI()
    {
    
    
        base.OnInspectorGUI();

        var mono = target as MonoBehaviour;
        if (mono == null)
            return;

        var methods = mono.GetType()
            .GetMethods(
                BindingFlags.Public | BindingFlags.NonPublic |
                BindingFlags.Instance | BindingFlags.Static
            ).Where(method =>
                Attribute.IsDefined(method, typeof(InspectorButtonAttribute))
            ).ToArray();

        foreach (var method in methods)
        {
    
    
            var attr = method.GetCustomAttribute<InspectorButtonAttribute>();
            DrawButton(method, attr.Name);
        }
    }

    private void DrawButton(MethodInfo methodInfo, string methodName)
    {
    
    
        if (string.IsNullOrEmpty(methodName))
            methodName = methodInfo.Name;

        EditorGUILayout.BeginHorizontal();

        if (GUILayout.Button(
                methodName,
                GUILayout.ExpandWidth(true)
            ))
        {
    
    
            foreach (var targetObj in targets)
            {
    
    
                var mono = targetObj as MonoBehaviour;
                if (mono == null)
                    continue;

                var val = methodInfo.Invoke(mono, new object[] {
    
     });
                if (val is IEnumerator coroutine)
                    mono.StartCoroutine(coroutine);
                else if (val != null)
                    Debug.Log($"{
      
      methodName}调用结果: {
      
      val}");
            }
        }

        EditorGUILayout.EndHorizontal();
    }
}

1. OnInspectorGUI メソッドをオーバーライドして、デフォルト インスペクターの下にカスタム GUI 要素 (ボタン) を追加します。
// ターゲットの MonoBehaviour の型を取得します
varmethods = mono.GetType()
// すべてのメソッドを取得しますthis type
.GetMethods(
// パブリック、非パブリック、インスタンス、および静的メソッドを取得するための検索フラグを指定します
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance | BindingFlags.Static
)
// LINQ を使用してフィルタリングします。 InspectorButtonAttribute でマークされたもの Method
.Where(method =>
Attribute.IsDefined(method, typeof(InspectorButtonAttribute))
) .ToArray();
// 結果を配列に変換

mono.GetType(): ターゲット (つまり、MonoBehaviour オブジェクト) の型情報を取得します。

.GetMethods(…): このタイプのすべてのメソッドを取得します。 BindingFlags パラメーターは、パブリック メソッド、非パブリック メソッド、インスタンス メソッド、静的メソッドなどの検索フラグを指定します。
2. リフレクションを使用して、InspectorButtonAttribute を持つメソッドを取得します。このプロパティは、提供されたコードでは定義されていないと想定されますが、ボタンとして表示されるメソッドをマークするために使用されるカスタム プロパティであると想定されます。

.Where(method => Attribute.IsDefined(method, typeof(InspectorButtonAttribute))): LINQ を使用して、InspectorButtonAttribute でマークされたメソッドを除外します。 Attribute.IsDefined メソッドは、メソッドが指定された属性を適用するかどうかを確認するために使用されます。

.ToArray(): フィルタリングされたメソッドの結果を、後で使用できるように配列に変換します。

  1. メソッド呼び出し
    var val = methodInfo.Invoke(mono, new object[] { });
    if (val は IEnumerator コルーチン)< /span> リフレクション (methodInfo.Invoke) を使用してメソッドを呼び出します。メソッドが IEnumerator を返す場合、それはコルーチンであるとみなされ、StartCoroutine を使用して開始されます。 null 以外の戻り値は Unity コンソールに記録されます。 Debug.Log($”{methodName}呼び出し結果: {val}”); else if (val != null)
    mono.StartCoroutine(coroutine);


発生したエラー
ここに画像の説明を挿入します

エディターで GammeObject の destroy メソッドを直接呼び出すと、次のエラーが報告されます。
編集モードから Destroy を呼び出すことはできません。代わりに DestroyImmediate を使用してください。
編集モードでオブジェクトを破棄すると、そのオブジェクトは永久に破棄されます。
UnityEngine.Object:Destroy (UnityEngine.Object)
主な考え方は次のとおりです。破棄は次から呼び出すことはできません。編集モード!代わりに DestroyImmediate を使用してください。
編集モードでオブジェクトを破棄すると、そのオブジェクトは永久に破棄されます。
問題の解決策
そのため、代わりに DestroyImmediate を使用してください。
ここに画像の説明を挿入します

以上です (ラベルについては上の図を参照してください)

おすすめ

転載: blog.csdn.net/qq_45498613/article/details/135027144