【Unity】RectTransformの領域を四隅の位置から指定する

こじゃらこじゃら

次のように、UIの矩形領域をスクリプトから指定する方法はないの?

このはこのは

該当する要素のRectTransformのアンカーやオフセットを変更すれば良いわ。

RectTransformの領域を四隅の位置から指定する方法の解説記事です。

本記事では、次の2通りの方法を紹介します。

領域の指定方法
  • Rect構造体で左下位置とサイズで指定する
  • 親要素の各辺からの相対位置で指定する

Rect構造体として指定することで、min、maxプロパティから四隅の位置を指定できるようになります。

このような処理は、次のプロパティをスクリプトから操作することで実現可能です。

編集するプロパティ
  • anchorMin
  • anchorMax
  • offsetMin
  • offsetMax

RectTransformクラスの拡張メソッドとして実装すると、手軽に使いまわせて楽できるでしょう。

本記事では、Rect構造体、各辺からの距離の2種類の指定方法でRectTransformの領域を決定する方法について解説していきます。

動作環境
  • Unity 2023.1.0f1
  • Unity UI 1.0.0

スポンサーリンク

前提条件

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

ヒエラルキー上では、次のように親要素の下に子要素が配置されているものとします。

次のように、親要素が無い状態でも機能させることを目指します。

Rect構造体で指定する

Unity標準のRect構造体で領域指定することで、結果として四隅の位置を指定して子要素の領域を変更できるようになります。

Rect構造体は、下図のように左下の座標サイズを保持することで、矩形領域を表現します。

Rect構造体のデータと領域

四隅の座標として指定したい場合は、左下位置をRect.min右上位置をRect.maxプロパティ経由で指定すれば良いです。

Rect rect;

・・・(中略)・・・

rect.min = new Vector2(100, 200);
rect.max = new Vector2(300, 400);

サンプルスクリプト

以下、Rect構造体のデータからRectTransformの領域を決定する処理の実装例です。

SetRectExtensions.cs
using UnityEngine;

public static class SetRectExtensions
{
    /// <summary>
    /// Rect構造体の情報を元に領域を決定する
    /// </summary>
    public static void SetRect(this RectTransform rt, in Rect rect)
    {
        // アンカー領域を左下に設定する
        rt.anchorMin = Vector2.zero;
        rt.anchorMax = Vector2.zero;

        // 親の左下を原点に、指定された矩形の位置を設定する
        rt.offsetMin = rect.min;
        rt.offsetMax = rect.max;
    }
}

上記をSetRectExtensions.csという名前でUnityプロジェクトに保存すると、拡張メソッドとして使用可能になります。

上記拡張メソッドを用いてRectTransformの領域を実際にするスクリプトは次のようになります。

SetRectExample.cs
using UnityEngine;

[RequireComponent(typeof(RectTransform))]
public class SetRectExample : MonoBehaviour
{
    // RectTransformに指定する矩形領域
    [SerializeField] private Rect _rect;

    private void Start()
    {
        var rt = GetComponent<RectTransform>();

        // 拡張メソッドを呼び出して矩形領域を設定する
        rt.SetRect(_rect);
    }
}

上記をSetRectExample.csという名前でUnityプロジェクトに保存し、領域を変更したいUI要素にアタッチし、インスペクターから領域情報を設定してください。

実行結果

次のように、Rect構造体で指定した通りの領域になることが確認できます。

初回のみ領域が更新されることにご注意ください。

Canvas直下に要素を配置しても機能します。

スクリプトの説明

Rect構造体からRectTransformの領域を指定する処理は以下部分です。

public static void SetRect(this RectTransform rt, in Rect rect)
{
    // アンカー領域は原点に設定する
    rt.anchorMin = Vector2.zero;
    rt.anchorMax = Vector2.zero;

    // 親の左下を原点に、指定された矩形の位置を設定する
    rt.offsetMin = rect.min;
    rt.offsetMax = rect.max;
}

アンカー領域を親要素の左下の一点に設定し、その後offsetMinoffsetMaxにそれぞれ指定領域の左下右上の座標を指定しています。

上下左右の辺の位置を指定する

親要素の領域の各辺からの相対的な距離として指定することも可能です。

次のように上下左右の辺の位置を指定するものとします。

親と子の辺の位置関係

位置が正の場合は内側へ、負の場合は外側へずらすものとします。

サンプルスクリプト

以下、親要素の辺との相対位置でRectTransformの領域を決定する拡張メソッドの実装例です。

SetEdgesExtensions.cs
using UnityEngine;

public static class SetEdgesExtensions
{
    /// <summary>
    /// 親の領域を基準に、指定された四隅の位置を設定する
    /// </summary>
    public static void SetEdges(
        this RectTransform rt,
        float top,
        float bottom,
        float left,
        float right
    )
    {
        // アンカー領域を親要素と同じ(Stretch)にする
        rt.anchorMin = new Vector2(0, 0);
        rt.anchorMax = new Vector2(1, 1);

        // 親要素の各辺からの相対的な位置を設定する
        rt.offsetMin = new Vector2(left, bottom);
        rt.offsetMax = new Vector2(-right, -top);
    }
}

上記をSetEdgesExtensions.csという名前でUnityプロジェクトに保存します。

RectTransformに実際に反映するスクリプトは以下のようになります。

SetRectExample.cs
using UnityEngine;

[RequireComponent(typeof(RectTransform))]
public class SetRectExample : MonoBehaviour
{
    // RectTransformに指定する矩形領域
    [SerializeField] private Rect _rect;

    private void Start()
    {
        var rt = GetComponent<RectTransform>();

        // 拡張メソッドを呼び出して矩形領域を設定する
        rt.SetRect(_rect);
    }
}

これをSetRectExample.csという名前でUnityプロジェクトに保存し、1つ目の例と同様に領域を変更したい要素にアタッチし、インスペクターより領域を設定してください。

実行結果

指定した通りの領域に変更されていることを確認できました。

Canvas直下に配置されていても正しく機能します。

スクリプトの説明

実際の指定処理は以下の通りです。

public static void SetEdges(
    this RectTransform rt,
    float top,
    float bottom,
    float left,
    float right
)
{
    // アンカー領域を親要素と同じ(Stretch)にする
    rt.anchorMin = new Vector2(0, 0);
    rt.anchorMax = new Vector2(1, 1);

    // 親要素の各辺からの相対的な位置を設定する
    rt.offsetMin = new Vector2(left, bottom);
    rt.offsetMax = new Vector2(-right, -top);
}

アンカー領域を親要素と同じ(Stretch)された状態に変更し、その後アンカー領域の左下右上からの相対位置をそれぞれoffsetMinoffsetMaxに指定しています。

さいごに

RectTransformの領域は、anchorMin、anchorMax、offsetMin、offsetMaxプロパティのほか、sizeDeltaプロパティなどからも設定できます。

上記に指定する値をRect構造体や辺の位置から計算して指定する方法を示しました。

拡張メソッドにすると、あらゆる場面で使いまわせるので便利です。

関連記事

参考サイト

スポンサーリンク