C#のGUI表現技術ののXAMLには上下左右を表す Thickness 型というものがありますが Unity にはありません(ないですよね?
なので今回はこの Thickness 型を作成して特定の操作を簡単にしたいと思います。GUIの上下端を表したり
確認環境
今回実装・確認を行う環境は以下の通りです。
- Unity 2020.3.14f1
- VisualStudio 2019
Editor上のみで確認しています。
実装コード
ではさっそく実装の紹介です。
Thicknessクラス
まずは上下左右を表す Thickness クラスの実装です。以前も紹介している ValueObject のテンプレートを改造して immutable になるように作成します。この方は JsonUtility などでシリアライズできるように readobly フィールドを使用しないようにしています。
using System; using UnityEngine; [Serializable] public /*readonly*/ struct Thickness : IEquatable<Thickness> { // JsonUtility でシリアライズする事を考慮 // Fields //public readonly float Left; //public readonly float Top; //public readonly float Right; //public readonly float Bottom; #pragma warning disable IDE0044 [SerializeField] private float left; [SerializeField] private float top; [SerializeField] private float right; [SerializeField] private float bottom; #pragma warning restore IDE0044 // Props public float Left => left; public float Top => top; public float Right => right; public float Bottom => bottom; public Thickness(float l, float t, float r, float b) { this.left = l; this.top = t; this.right = r; this.bottom = b; } // 演算子のオーバーライド public static bool operator ==(in Thickness a, in Thickness b) => Equals(a, b); public static bool operator !=(in Thickness a, in Thickness b) => !Equals(a, b); // 4つの組み合わせからHSVオブジェクトを作成する public static implicit operator Thickness((float l, float t, float r, float b) thickness) { return new Thickness(thickness.l, thickness.t, thickness.r, thickness.b); } // 等値比較演算子の実装 public readonly override bool Equals(object obj) => (obj is Thickness _obj) && this.Equals(_obj); // IEquatable<T> の implement public readonly bool Equals(Thickness other) { // 個別に記述する return ReferenceEquals(this, other) || this.left == other.left && this.top == other.top && this.right == other.right && this.bottom == other.bottom; } public readonly override int GetHashCode() { unchecked { var hashCode = this.left.GetHashCode(); hashCode = (hashCode * 397) ^ this.top.GetHashCode(); hashCode = (hashCode * 397) ^ this.right.GetHashCode(); hashCode = (hashCode * 397) ^ this.bottom.GetHashCode(); return hashCode; } } }
RectTransformExtensionクラス
上記の型をGUIと連携させるために以下のような拡張メソッドを定義します。
using System; using UnityEngine; public static class RectTransformExtension { /// <summary> /// このオブジェクトを <see cref="RectTransform"/> を仮定して /// <see cref="GetLocalSize(RectTransform)"/> に処理を転送します。 /// </summary> public static Thickness GetLocalSize(this Transform t) { if (t is RectTransform rt) { return GetLocalSize(rt); } throw new InvalidOperationException($"t is not RectTransform."); } /// <summary> /// このオブジェクトの中央を(アンカーなどの設定に関わらず固定で)ゼロとしてローカルサイズを取得します。 /// </summary> /// <remarks> /// RectTransform.localPostion と対応関係がある数値になる。 /// </remarks> public static Thickness GetLocalSize(this RectTransform rt) { UnityEngine.Rect rect = rt.rect; float hw = rect.x / 2f; float hh = rect.y / 2f; return new Thickness(-hw, hh, hw, -hh); } }
使い方
使用方法は以下の通りです。
public void Foo(Image img) { Thickness th = img.transform.GetLocalSize(); // 上下左右の境界の位置を取得する float top = th.Top; float bottom = th.Bottom; float left = th.Left; float right = th.Right; }
こうすれば少しはコードの記述が簡単になるかと思います。