うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】続 Unity デフォルト型の Inspector拡張 ~Transform~

【Unity】Unity デフォルト型の Inspector 拡張 - うにてぃブログ

上記記事で CanEditMultipleObjects を設定時に複数の要素の更新ができない問題があったため、いっそ TransformInspector の実装部分をまるっと実装してしまうことにする

実装

Position と Scale に関しては SerializedProperty をそのまま使っているので問題無いが

Rotation に関しては Quaternion 型で保持しているため internal クラスである UnityEditor.TransformRotationGUIを利用している

そのため UnityEditor.TransformRotationGUI を Reflection で操作している

幸いなことに 呼び出し箇所が少なかったため簡単に実装できた

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


[CustomEditor(typeof(Transform))]
[CanEditMultipleObjects]
public class InspectorExtensionTransform : Editor
{
    private Type _transformRotationGUIType;
    private System.Object _transformRotationGUIObject;
    private MethodInfo _rotationFieldMethod;
    private SerializedProperty _positionProperty;
    private SerializedProperty _scaleProperty;
    private Transform _transform;
    
    private void OnEnable()
    {
        _transform = target as Transform;
        _positionProperty = serializedObject.FindProperty("m_LocalPosition");
        _scaleProperty = serializedObject.FindProperty("m_LocalScale");
        
        _transformRotationGUIType = typeof(EditorApplication).Assembly.GetType("UnityEditor.TransformRotationGUI");
        if (_transformRotationGUIObject == null)
            _transformRotationGUIObject = Activator.CreateInstance(_transformRotationGUIType);
        
        var enableMethod = _transformRotationGUIType
            .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)
            .First(m => m.Name == "OnEnable");
        
        // Initialize TransformRotationGUI
        enableMethod.Invoke(_transformRotationGUIObject, new object[]
        {
            serializedObject.FindProperty("m_LocalRotation"),
            EditorGUIUtility.TrTextContent("Rotation")
        });
        
        _rotationFieldMethod = _transformRotationGUIType
            .GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)
            .Where(m => m.Name == "RotationField")
            .FirstOrDefault(m => m.GetParameters().Length == 0);
    }

    public override void OnInspectorGUI()
    {
        EditorGUILayout.PropertyField(_positionProperty);
        
        _rotationFieldMethod.Invoke(_transformRotationGUIObject, null);
        
        EditorGUILayout.PropertyField(_scaleProperty);
        
        using (new EditorGUI.DisabledScope(true))
        {
            EditorGUILayout.LabelField("World (Read Only)");
            EditorGUILayout.Vector3Field("Position", _transform.position);
            EditorGUILayout.Vector3Field("Rotation", _transform.rotation.eulerAngles);
            EditorGUILayout.Vector3Field("Scale", _transform.lossyScale);
        }
    }
}
単体選択時

f:id:hacchi_man:20200115215517p:plain:w400

複数選択時

f:id:hacchi_man:20200115215607p:plain:w400

複数選択時にRotationに関しては、同じ値でも「ー」と表示されている問題はまだ残っているが概ね想定通りに動作してくれた

参考サイト

UnityCsReference/TransformInspector.cs at 9034442437e6b5efe28c51d02e978a96a3ce5439 · Unity-Technologies/UnityCsReference · GitHub

UnityCsReference/TransformRotationGUI.cs at 9034442437e6b5efe28c51d02e978a96a3ce5439 · Unity-Technologies/UnityCsReference · GitHub