【Unity】RectTransform.sizeDeltaの仕様と注意点

こじゃらこじゃら

sizeDeltaはサイズと覚えたけど、期待通りの結果にならない事があるの…😭

このはこのは

RectTransformのsizeDeltaは正確にはサイズではないわ。サイズとアンカーサイズとの差分を意味するものなの。

Unity UI(uGUI)などで使われるRectTransform.sizeDeltaプロパティは、そのRectTransform自体の矩形サイズではなく矩形サイズからアンカーサイズを引いたものです。

アンカーが矩形より小さい場合
アンカーが矩形より大きい場合

sizeDeltaはサイズと説明される場合がありますが、これは不正確な表現です。sizeDeltaが矩形サイズとして振る舞うのは、アンカーサイズが0の場合に限ります。

試しにUIのアンカーをstretch(アンカーサイズが0でない)に設定すると、RectTransform.sizeDeltaプロパティが実サイズとは異なる結果になる事が確認できます。

アンカーにStretchが設定されている場合

本記事では、このRectTransform.sizeDeltaプロパティの仕様を正しく理解するところを目指して解説します。サイズを取得したり指定する方法にも触れます。

注意

本記事では、4点で定義されるアンカーの縦横のサイズを便宜上「アンカーサイズ」と表記することとします。

動作環境
  • Unity 2023.2.0f1
  • Unity UI 2.0.0

スポンサーリンク

前提条件

次のように、親のUI要素の下に子要素が配置されているものとします。

この子要素のアンカーとサイズとsizeDeltaの関係に着目して解説します。

アンカーについて

RectTransform.sizeDeltaプロパティは矩形サイズとアンカーに密接に関わるため、まずアンカーについて軽く触れておきます。

アンカーは、あるUI要素を親要素に対してどのように位置付けるかを決めるためのもので、親要素の左下を(0, 0)、右上を(1, 1)に正規化した4点の位置で構成されます。

データ上では、アンカー領域の左下(Min Anchor)、右上(Max Anchor)の2点で表現されます。

アンカー領域を親要素を基準に正規化した位置で表現することにより、親要素に対して相対的な割合でサイズが変化させることが可能です。

アンカーの4点を同じ位置にまとめると、次のようにサイズを固定しながら左揃えや中央揃えなどが行えるようになります。

アンカーのプリセット

UI要素を配置する場合は、RectTransformのインスペクターからはアンカーのプリセットを選択できます。

プリセットはそれぞれ次のような値になっています。

プリセットのアンカー(上段:Max Anchor、下段:Min Anchor)

RectTransform.sizeDeltaの仕様

要素のサイズからアンカーのサイズを引いたものです。Vector2型であり、xy軸方向それぞれの結果がx,yに格納されたものとなります。

public Vector2 sizeDelta { get; set; }

sizeDeltaは要素のサイズとアンカーを用いると次式のようになります。

sizeDeltaの計算式

sizeDelta = 要素のサイズ – 要素のアンカーサイズ

要素のアンカーサイズ = (anchorMax – anchorMin) × 親要素のサイズ

sizeDeltaは要素のサイズからアンカー領域のサイズを引いた値です。単位はピクセルです。

アンカー領域のサイズアンカーの右上座標(anchorMax)から左下座標(anchorMin)を引いて求められますが、これは親サイズを1(単位)とした値です。

そのため、アンカーサイズの単位をピクセルに変換するために、親要素のサイズを掛ける必要があります。

上記の関係式より、RectTransformの矩形サイズアンカーサイズにsizeDeltaを足した結果となります。

サイズを求める計算

要素のサイズ = 要素のアンカーサイズ + sizeDelta

アンカー設定による挙動の比較

代表的なアンカー設定によるサイズの振舞いについて見ていきます。

ストレッチでない場合

次のプリセットが指定されている場所、アンカーサイズが0になります。

この場合、minAnchorとmaxAnchorは等しくなるため、sizeDeltaは要素のサイズと一致します。

sizeDeltaとサイズの関係式(アンカーサイズが0の場合)

sizeDelta = 要素のサイズ

UIのデフォルトのアンカー設定はminAnchor、maxAnchor共に(0.5, 0,5)であり、上記の挙動をとります。

sizeDelta = 要素サイズという関係は、このようにminAnchorとmaxAnchorが一致している場合に限る点に注意が必要です。

ストレッチされた場合

次のプリセットが設定されている場合、親要素のサイズが変わると子要素のサイズもそれに追従して変わります。

ストレッチされている軸のアンカーはminAnchor = 0、maxAnchor = 1となり、アンカーサイズ(ピクセル)は親要素のサイズ(ピクセル)と一致します。

この時のsizeDeltaの関係式は以下のようになります。

sizeDeltaとサイズとの関係式

sizeDelta = 要素のサイズ – 親要素のサイズ

実際に親要素のサイズを変えた様子です。

子要素の4隅からの相対位置が維持されています。

RectTransformの矩形サイズの取得

特定要素の矩形サイズはRectTransform.rect.sizeプロパティから取得できます。

RectTransform rectTransform;

・・・(中略)・・・

// RectTransformのサイズを取得する
Vector2 size = rectTransform.rect.size;

要素の矩形領域(位置とサイズ)の情報はRectTransform.rectプロパティからRect構造体として得られ、Rect.sizeプロパティからxy軸方向のサイズを取得出来ます。

RectTransform.sizeDeltaプロパティを用いても親要素のサイズやアンカーから計算できますが、rectプロパティを用いた方が手軽です。

RectTransformの矩形サイズの指定

逆に特定要素のサイズを指定したい場合、RectTransform.SetSizeWithCurrentAnchorsメソッドを使うと簡単です。

RectTransform rectTransform;

・・・(中略)・・・

// RectTransformのx軸方向のサイズを変更する
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, 400);

// RectTransformのy軸方向のサイズを変更する
rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 200);

第1引数にはサイズ指定する軸第2引数には変更後のサイズ(ピクセル)を指定します。

このメソッドは、内部的にアンカーの設定値に基づいて計算し、それをsizeDeltaプロパティに反映しています。

もしRectTransform.sizeDeltaプロパティに直接指定したい場合は、指定したいサイズからアンカー領域のサイズを引いた結果を反映すれば良いです。

RectTransform rectTransform;
Vector2 size = new Vector2(400, 200);

・・・(中略)・・・

// 親要素のサイズ取得
RectTransform parent = rectTransform.parent as RectTransform;
Vector2 parentSize = parent != null ? parent.rect.size : Vector2.zero;

// アンカーサイズの計算
Vector2 anchorSize = (rectTransform.anchorMax - rectTransform.anchorMin) * parentSize;

// サイズからアンカーサイズを引いた結果がsizeDelta
rectTransform.sizeDelta = size - anchorSize;

サイズ指定のより詳しい内容は、以下記事で解説しています。

さいごに

RectTransform.sizeDeltaプロパティは、実際のサイズからアンカーサイズを引いたVector2型の値です。

sizeDeltaがサイズと等しくなるのはアンカーサイズが0の場合に限ります。UIのデフォルト設定ではアンカーサイズが0となっているので、サイズと誤解しやすい点に注意する必要があります。

サイズ取得したい場合はRectTransform.rect.sizeプロパティをリードすれば良いです。サイズ指定はRectTransform.SetSizeWithCurrentAnchorsメソッドを使うかサイズからアンカーサイズを引いた計算結果をsizeDeltaに指定するのが正しい方法です。

関連記事

参考サイト

スポンサーリンク