はじめに
UnityでPrefab化したUIを生成する際に、RectTransformの持つSizeDeltaでは生成位置を上手く計算できなかったので、UIオブジェクトのサイズをワールド座標でも利用できるように変換する処理を作りました。
完成後、インスタンスした後に直接anchoredPositionを指定して移動させれば良いことに気づいたので全く使っていません。悔しいので備忘録として残しておきます。
もしかしたら今後使うかもしれない...多分
ワールド座標空間とSizeDeltaが表す大きさが違うので、
ワールド座標から直接SizeDeltaを引いて位置を出すと大きく異なる位置に生成されてしまう

条件
以下の条件を満たしていない場合は上手く動作しないです。
- 2D空間であること
- 対象となるUIオブジェクトがCanvas直下に置かれている
- アンカー設定のminAnchorとmaxAnchorが一致している(デフォルト)
SizeDeltaを変換する際の比率を計算
画面に入るユニット数と画面の縦幅を利用して比率を計算します。
手順
- メインカメラから画面の縦幅に入るユニット数を取得
(カメラのインスペクタにも項目があるが、アスペクト比によって変わらない) - 表示している画面の縦幅を取得(1920*1080なら1080)
- 対象となるUIオブジェクトのサイズにcanvasのscaleFactorを掛けて拡大率を修正する
- 取得した比率を修正されたUIオブジェクトのサイズに掛ける
public static Vector2 SizeDeltaToWorldSize(Vector2 targetSizeDelta, Canvas canvas)
{
//メインカメラから画面の縦半分に何ユニット入るのかを取得する
float cameraSize = Camera.main.orthographicSize;
//画面の縦幅に入るユニット数
float heightUnit = cameraSize * 2;
//画面の縦のサイズを取得
float heightSize = Screen.height;
//SizeDeltaのサイズを変換する際の比率を求める
float sizeDeltaToWorld = heightUnit / heightSize;
//スクリーンサイズによって変換されたcanvasの拡大率をsizedeltaから修正
Vector2 fixSizeDelta = targetSizeDelta * canvas.scaleFactor;
//与えられたsizeを変換
Vector2 result = fixSizeDelta * sizeDeltaToWorld;
return result;
}
sizeDeltaはRectTransform自体のサイズを表していないため、親要素サイズを考慮する必要がある場合があります
おわりに
これで計算できたワールド座標での縦幅を前のオブジェクトの生成座標に足すことでオブジェクトを隙間なく生成できます。
条件もかなり厳しく、追加の処理が必要になる可能性もあるため始めに述べた方法で行うべきだと思います。ただ、RectTransformとワールド座標空間周りの知識がかなり付いたのでいつか活かせればと思います。
参考サイト
https://nn-hokuson.hatenablog.com/entry/2021/05/12/143613
https://qiita.com/kodai100/items/aeab3cda3dc3feb2bef4
https://nekojara.city/unity-rect-transform-size
https://qiita.com/tetr4lab/items/117142e38d6487b7bef3
https://nekojara.city/unity-rect-transform-size-delta
https://note.com/tsukerat_games/n/n9aa0f9f0f939
