3
2

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 5 years have passed since last update.

【Unity】子同士の関係にあるメンバ変数の値をコピーするエディタ拡張

3
Posted at

子同士の関係にあるメンバ変数の値をコピーするエディタ拡張。
ContextMenuにあるPaste Componentでは異なるクラス間の値のコピーができない。
例え同じ親を継承していても...。親クラスのメンバ変数部は同じ値やコンポーネントにしたいことがある。
一々Inspectorで編集するのが面倒なのでエディタ拡張でコピーする機能を作った。

使い方

  1. メニューのWindow/ComponentFieldCopyerを選択
  2. コピー元とコピー先のコンポーネントをドラッグ・アンド・ドロップ
  3. Copyを押す
  4. 実行される

コード

using System;
using System.Reflection;
using UnityEditor;
using UnityEngine;

/// <summary>
/// メンバ変数のコピーを行う
/// EditorWindowでコピー元とコピー先のコンポーネントを指定する
/// </summary>
public class UniCopyField : EditorWindow
{
    private UnityEngine.Object fromObj;
    private UnityEngine.Object toObj;

    [MenuItem("Window/ComponentFieldCopyer")]
    private static void OpenWindow()
    {
        EditorWindow.GetWindow<UniCopyField>("ComponentFieldCopyer");
    }

    void OnGUI()
    {
        fromObj = EditorGUILayout.ObjectField("From", fromObj, typeof(UnityEngine.Object), true);
        toObj = EditorGUILayout.ObjectField("To", toObj, typeof(UnityEngine.Object), true);

        if(GUILayout.Button("Copy")) {
            copy(fromObj.GetType());
        }
    }

    private void copy(Type fromType)
    {
        if(fromType == typeof(MonoBehaviour)) return;
        foreach(var from in fromType.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)) {
            var other = fromType.GetField(from.Name, BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            if((other != null)) {
                try {
                    other.SetValue(toObj, from.GetValue(fromObj));
                } catch(Exception e) {
                    Debug.Log(e);
                }
            }
        }
        // fromの親クラスからコピー
        copy(fromType.BaseType);
    }
}


仕組み

設定Window

UnityのEditorWindowでコピー元とコピー先のコンポーネントを取得する。
UnityEngine.Object型で取得するためほぼ全てのコンポーネントに対応できる。
Inspectorから「コンポーネントを」ドラッグアンドドロップで設定すること。
EditorGUILayout.ObjectFieldで設定されたコンポーネントを取得しておく。

メンバ変数の取得

Reflectionを用いて2つのクラスの共通のメンバ変数を取得する。
GetFieldおよびGetFieldsで指定したTypeのメンバ変数が取得できる。
BindingFlagsで取得するメンバ変数の条件を設定する。
両方に共通して持つフィールドのみSetValueで値を代入。
コピー先がメンバ変数を持っていない場合は例外を吐かせることにした。
GetFieldsでは親クラスのprivateメンバは取得できないため、Type.BaseTypeで今度は親クラスのメンバ変数の取得を行う。

GitHub

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?