次のようなUIのサイズをスクリプトから指定する方法はないの?
RectTransform.SetSizeWithCurrentAnchorsメソッドを使うと良いわ。
Unity UI(uGUI)などのRectTransformの幅(width)や高さ(height)をスクリプトから指定したい場合、RectTransform.SetSizeWithCurrentAnchorsメソッドを使うと実現できます。
参考:RectTransform-SetSizeWithCurrentAnchors – Unity スクリプトリファレンス
RectTransform.sizeDeltaプロパティの変更でも可能ですが、サイズをそのまま代入するだけでは正しい挙動にならないケースがあり、親要素とアンカー領域のサイズを考慮した計算値を指定する必要があります。
不十分な例
正しい例
SetSizeWithCurrentAnchorsメソッドは、正しい例で示したような計算を内部的に行ってくれるので、基本的にこちらを使えば問題ありません。
sizeDeltaプロパティは、アンカー間との距離と比較したRectTransformのサイズとなっており、単純なサイズではありません。誤解されやすい点なので注意する必要があります。
参考:RectTransform-sizeDelta – Unity スクリプトリファレンス
本記事では、SetSizeWithCurrentAnchorsメソッドを用いたUIサイズの指定方法を解説していきます。また、メソッド内部の計算や使い方の工夫例についても紹介します。
- Unity 2022.2.13f1
- Unity UI 1.0.0
目次 非表示
前提条件
次のようにパネル(親要素)の下にUI(子要素)が配置されているものとします。
本記事では、上記画像(子要素)に対してサイズ変更を適用していくことを例にとって解説していきます。
SetSizeWithCurrentAnchorsメソッドの使い方
指定されたUI要素のサイズを指定するメソッドです。
次のような形式で定義されています。
第1引数axisには、サイズ変更対象の軸を指定します。Axis.Horizontalで水平方向、Axis.Verticalで垂直方向が指定できます。
第2引数sizeには、変更後のUIサイズを指定します。水平方向ならx軸方向の幅、垂直方向ならy軸方向の高さとなります。
参考:RectTransform-SetSizeWithCurrentAnchors – Unity スクリプトリファレンス
サンプルスクリプト
以下、自身のRectTransformのサイズを指定するサンプルスクリプトです。
上記スクリプトをSetSizeExample.csという名前で保存し、サイズを変更したいUI(RectTransformが適用されているオブジェクト)に追加すると機能するようになります。
インスペクターより指定したいサイズを反映できるようにしています。
実行結果
インスペクターより指定したサイズがUIに反映されていることを確認できました。
途中でアンカーを変更していますが、ストレッチされた状態でも正しく動作するようになっています。
アンカー領域はシーンビュー上の三角マークとして表示されます。
ストレッチされていない時(centerが指定されている)は4つの三角マークが一点に集中していますが、ストレッチされている時(stretchが指定されている)は三角マークの領域が拡大されます。
スクリプトの説明
以下部分で水平方向と垂直方向それぞれでサイズを反映させています。
水平と垂直同時に指定したい場合は、メソッドを2回呼び出す必要があります。
親要素が変更された場合への対応
親要素のサイズが変更されると、その子要素のサイズが変化することがあります。
これは、子要素のアンカー領域が一点でない場合(stretchに設定されている場合)に起こります。
このような場合でも子要素のサイズを維持したい場合、親要素のサイズを変更した時に子要素のサイズを設定し直す必要があります。
前述のサンプルスクリプトはUpdateイベントで毎フレーム更新しているため、子要素のサイズは維持されます。
メソッドの内部挙動
RectTransform.SetSizeWithCurrentAnchorsメソッドは、内部的には子要素のアンカーサイズに基づいて計算した値をRectTransform.sizeDeltaプロパティに指定しています。
次のような計算式になっています。
sizeDelta = 指定サイズ – 子要素のアンカーサイズ
子要素のアンカーサイズ = 親要素のサイズ × (anchorMax – anchorMin)
指定サイズの単位はピクセルですが、anchorMinとanchorMaxは親サイズを1とした単位です。
そのため、ピクセル単位のアンカーサイズを求めるために、親要素のサイズを掛ける必要があります。
親要素のサイズは次のようなコードで計算できます。
RectTransform.rectプロパティに親要素の領域情報が格納されているため、これのsizeプロパティから矩形のサイズが得られます。
参考:RectTransform-rect – Unity スクリプトリファレンス
子要素のアンカーサイズは次のようなコードで計算されます。
アンカーにcenterが指定されている場合はanchorMaxとanchorMinプロパティの値が一致するため、アンカーサイズは0になります。
stretchが指定されている場合、anchorMinとanchorMaxの差は1となります。これらは、親要素のサイズを基準に正規化された値であるためです。
そのため、アンカーサイズは前者に親要素サイズを掛けることで求めます。
そして、最終的に次のように計算式で計算した結果をsizeDeltaプロパティにセットしています。
幅と高さを一緒に指定できる拡張メソッドを自作する
ここまでx軸とy軸それぞれでSetSizeWithCurrentAnchorsメソッドを呼び出してサイズ指定する方法を紹介しました。
メソッドを2回呼び出すのが不便な場合は、拡張メソッドを自作すれば楽できるでしょう。
以下、SetSizeというRectTransformの拡張メソッドを実装した例です。
内部的にSetSizeWithCurrentAnchorsメソッドを2回呼び出す処理を行うようにすれば良いです。
ただし、この場合はRectTransform.parentやRectTransform.sizeDeltaプロパティに2度余分にアクセスしてしまうため、パフォーマンスを求める場合は次のようなコードにすると良いでしょう。
上記をRectTransformExtensions.csという名前でUnityプロジェクトに保存すると拡張メソッドが使えるようになります。
使う側は以下のようになります。
以下のように指定処理が非常にシンプルになりました。
さいごに
RectTransformのサイズをスクリプトから変更したい場合、RectTransform.SetSizeWithCurrentAnchorsメソッドを使えば実現できます。
ただし、幅と高さを一度に指定できず、各軸ずつメソッドを2回呼ぶ形で指定する必要があります。
一度に指定するメソッドはUnity2022.2現在ではUnityから提供されていないため、拡張メソッドを自作して対応すると良いでしょう。