背景
UI要素のサイズ(RectTransform.sizeDelta)を別UI要素に追従させ、見た目上で一致させたい
- 一致させる対象が直接の親の場合
- Stretch指定でOK
- 一致させる対象が子かつ子の数が1つの場合
- 下記公式ドキュメントの実装で可能
- https://docs.unity3d.com/ja/2018.4/Manual/HOWTO-UIFitContentSize.html
- Horizontal/Vertical Layout Groupを使用する必要があり、自動で整列されるため子1つのみの制約あり
- 構成が複雑でわかりづらい
上記の様なヒエラルキーや要素数に依存しないコンポーネントが欲しかったので自作しました
また、Inspector上でのサイズ変更を不可にしました
UISizeFitter
usingUnityEngine;[ExecuteInEditMode,RequireComponent(typeof(RectTransform))]publicclassUISizeFitter:MonoBehaviour{[SerializeField]RectTransform_target;RectTransform_selfRect;Vector3_cachedTargetLossyScale;Vector2_cachedTargetSizeDelta;bool_isDirty=true;voidUpdateDirty(){if(_cachedTargetSizeDelta==_target.sizeDelta&&_cachedTargetLossyScale==_target.lossyScale){return;}_cachedTargetSizeDelta=_target.sizeDelta;_cachedTargetLossyScale=_target.lossyScale;_isDirty=true;}voidAdjustSize(){if(!_isDirty){return;}_selfRect.sizeDelta=_cachedTargetSizeDelta*_cachedTargetLossyScale;_isDirty=false;}// Layout Groupみたいに「Some values driven by 〜」とInspector上の編集を禁止するvoidLockRectTransformProperty(){DrivenRectTransformTrackerdt=newDrivenRectTransformTracker();dt.Clear();dt.Add(this,_selfRect,DrivenTransformProperties.SizeDelta);}voidAwake(){_selfRect=GetComponent<RectTransform>();LockRectTransformProperty();}voidUpdate(){if(_target==null){return;}UpdateDirty();AdjustSize();}}
補足
常に追従させたかったのでUpdateで実行していますが、負荷的に問題になったり、動的に変更しないのであればStart辺りに移動し一度のみ実行するのが良いと思います
また、 lossyScale
がUnity側でキャッシュしているのか毎回計算しているのかが不明だったため、とりあえずComponent側でキャッシュしていますがUnity側で毎回計算している様だと比較時の負荷が若干気になります
_cached〜でキャッシュしているのは比較の方がコピーより高速だろうという考えの下です