イバコの生存記録

いまは競プロ(AtCoder)記事がメインです。

15. decimal型VectorをUnityEditorで制御したかった

Unity(2020.3.6f1) の話です。

計算精度が欲しかったので decimal 型で独自の Vector クラスを作成しました。
これで困ったのは、UnityEditor の Inspector で編集できないということです。

どうも Unity の Inspector は decimal 型をサポートしていないらしく、変数に SerializeField を付けても表示されません。
まぁ通常必要になることはないですし、下手にサポートすると初学者の人が誤りそうということでサポートしない方針も理解できます。
Inspector 拡張など色々やれば出せるようになると思いますが、Vector クラスは純粋な算術クラスとして扱いたいので Unity に依存させたくありませんでした。


そこで、苦肉の策として Unity の Vector3 と自作の Vector3decimal を仲介する Vector3UnityProxy というクラスを作成しました。

using UnityEngine;

[Serializable]
public sealed class Vector3UnityProxy
{
    public Vector3decimal Impl { get; set; }

    [SerializeField]
    private Vector3 value;

    public void Awake()
    {
        this.Impl = new Vector3decimal((decimal)this.value.x, (decimal)this.value.y, (decimal)this.value.z);
    }

    public void Update()
    {
        this.value = this.Impl.ToUnityVector();
    }
}

コード中で操作するのは Impl で、value は初期値を Impl に伝える役割と、Impl の値を UnityEditor へ伝える役割を持ちます。
だいぶ適当に作ったのですが、このクラスは色々と問題があります。

  • Impl への直接アクセスを許容しており、Proxy としての役割を正しく果たせていない
  • 利用者側からの記述が冗長になる(必ず Impl を挟む)
  • UnityEditor へ見せるための変数が private、裏方としてのプロパティが public で直感的に矛盾しているように見える

…と、今こうやって書き出すとかなり微妙だなぁ…と思っています。

ちゃんとやるなら Vector3decimal 用のインターフェースを切るのが良さそうですね。
.NET の Vector と実装を合わせたい気持ちがありましたが、流石にこの設計は嫌なのでインターフェースの追加は許容しようかなぁ、と思います。