カスタマイズ
IMGUI の拡張

IMGUI レイアウトモード

固定レイアウトと自動レイアウト

IMGUI システムを使用しているときに UI の配置と整理を行うには、固定と自動の 2 つの方法があります。本ガイドでは、すべての例において固定レイアウトを使用してきました。自動レイアウトを使用するには、コントロール関数を呼び出す際に、GUI の代わりに、GUILayout を記述します。固定レイアウトは、1 つのレイアウトモードを使用する必要はありませんが、同じ OnGUI() 関数で一度に両方のモードを使用することができます。

固定レイアウトは、事前に設計されたインターフェースで作業する場合に使用します。自動レイアウトは、前もって必要な要素の数が分からない場合、や各コントロールの配置について気にしたくない場合に使用します。例えば、Save Game ファイルに基づいて、各種ボタンを作成している場合、描画するボタンの数が分からないとします。この場合、自動レイアウトを使用する方が便利です。ゲームの設計とどのようにインターフェースを表示したいかに強く依存しています。

自動レイアウトを使用した場合、2 つの大きな差があります。

  • GUI の代わりに GUILayout を使用します。
  • 自動レイアウトコントロールには、Rect() 関数が不要です。
/* 自動レイアウトを使うときの 2 つの主な違い */


// JavaScript
function OnGUI () {
    // 固定レイアウト
    GUI.Button (Rect (25,25,100,30), "I am a Fixed Layout Button");

    // 自動レイアウト
    GUILayout.Button ("I am an Automatic Layout Button");
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
    
    void OnGUI () {
        // 固定レイアウト
        GUI.Button (new Rect (25,25,100,30), "I am a Fixed Layout Button");
    
        //自動レイアウト
        GUILayout.Button ("I am an Automatic Layout Button");
    }

}


コントロールの配置

使用しているレイアウトモードに応じて、コントロールを配置する場所やグループ化する方法をコントロールするための各種仕掛けがあります。固定レイアウトでは、各種コントロールを Groups に分けることができます。自動レイアウトでは、各種コントロールを AreasHorizontal GroupsVertical Groups に分けることができます。

固定レイアウト - グループ

グループを固定レイアウトモードで利用できる手法です。これにより、複数のコントロールを含む画面のエリアを定義できます。GUI.BeginGroup()GUI.EndGroup() 関数を使用することで、グループ内に置くコントロールを定義できます。グループ内にあるすべてのコントロールは、画面の左上ではなく、グループの左上に基づいて配置されます。このように、ランタイム時にグループを最配置する場合、グループ内のすべてのコントロールの相対位置は維持されます。

例として、画面上で複数のコントロールを中心に置くと非常に簡単です。

/* グループを使って複数のコントロールを画面の中心に置く */


// JavaScript
function OnGUI () {
    // 画面の中心にグループを作ります。
    GUI.BeginGroup (Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100));
    // すべての四角をグループに調整します。 (0,0) はグループの左上の端です。
    
    // ボックスを作ります。すると、画面上でどもにグループがあるかわかります。
    GUI.Box (Rect (0,0,100,100), "Group is here");
    GUI.Button (Rect (10,40,80,30), "Click me");
    
    // 上で開始したグループを終了します。これは、忘れずに行わなければいけません。
    GUI.EndGroup ();
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
    
    void OnGUI () {
        // 画面の中心にグループを作ります。
        GUI.BeginGroup (new Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100));
        // すべての四角をグループに調整します。 (0,0) はグループの左上の端です。
    
        // ボックスを作ります。すると、画面上でどもにグループがあるかわかります。
        GUI.Box (new Rect (0,0,100,100), "Group is here");
        GUI.Button (new Rect (10,40,80,30), "Click me");
    
        // 上で開始したグループを終了します。これは、忘れずに行わなければいけません。
        GUI.EndGroup ();
    }

}


上記の例では、画面解像度に関係なく、コントロールを中心に置きます
上記の例では、画面解像度に関係なく、コントロールを中心に置きます

それぞれの内部で複数のグループをネストすることもできます。これを行うと、各グループは、その内容をその親の空間に対して、切り取らせます。

/* 表示したコンテンツをクリップするために複数のグループを使用します*/


// JavaScript
var bgImage : Texture2D; //背景画像、 256 x 32
var fgImage : Texture2D; //前景画像、 256 x 32
var playerEnergy = 1.0; // 0.0 から 1.0 までの float

function OnGUI () {
    // 両方の画像を含むグループを作成
    // 最初の 2 座標を調整し、画面上のどこかに置きます
    GUI.BeginGroup (Rect (0,0,256,32));

    // 背景画像を描画します。
    GUI.Box (Rect (0,0,256,32), bgImage);
    
    // クリップされる2番目のグループを描画
    // 画像をクリップしますが、スケールはしません。それが、2番目のグループが必要な理由です。
    GUI.BeginGroup (Rect (0,0,playerEnergy * 256, 32));

    // 前景画像を描画します。
    GUI.Box (Rect (0,0,256,32), fgImage);

    //両グループを終了します。
    GUI.EndGroup ();
    GUI.EndGroup ();
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
    
    // 背景画像、256 x 32
    public Texture2D bgImage; 
    
    // 前景画像、256 x 32
    public Texture2D fgImage; 
    
    //0.0 から 1.0 までの float
    public float playerEnergy = 1.0f; 
    
    void OnGUI () {
        // 両方の画像を含むグループを作成
        // 最初の 2 座標を調整し、画面上のどこかに置きます
        GUI.BeginGroup (new Rect (0,0,256,32));
    
        // 背景画像を描画します。
        GUI.Box (new Rect (0,0,256,32), bgImage);
    
            // クリップされる2番目のグループを描画
    // 画像をクリップしますが、スケールはしません。それが、2番目のグループが必要な理由です。
            GUI.BeginGroup (new Rect (0,0,playerEnergy * 256, 32));
        
            // 前景画像を描画します。
            GUI.Box (new Rect (0,0,256,32), fgImage);
        
            // 両グループを終了します。
            GUI.EndGroup ();
        
        GUI.EndGroup ();
    }

}


切り取り動作を作成するため、グループを一緒にネストします。
切り取り動作を作成するため、グループを一緒にネストします。

自動レイアウト - エリア

エリアは、自動レイアウトでのみ使用されます。GUILayout コントロールを含ませるための画面の制限された部分を定義するため、機能は固定レイアウトに似ています。自動レイアウトの性質上、ほとんど常にエリアを使用することになります。

自動レイアウトモードでは、コントロールがコントロールレベルで描画される画面のエリアを定義しません。コントロールは自動的に含んでいるエリアの左上に配置されます。これは画面の場合があります。自身で手動配置されたエリアを作成することもできます。エリア内の GUILayout コントロールは、エリアの左上に配置されます。

/* エリア内のどこにも位置しないボタンと、画面の半分の位置に位置するボタン */


// JavaScript
function OnGUI () {
    GUILayout.Button ("I am not inside an Area");
    GUILayout.BeginArea (Rect (Screen.width/2, Screen.height/2, 300, 300));
    GUILayout.Button ("I am completely inside an Area");
    GUILayout.EndArea ();
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
    
    void OnGUI () {
        GUILayout.Button ("I am not inside an Area");
        GUILayout.BeginArea (new Rect (Screen.width/2, Screen.height/2, 300, 300));
        GUILayout.Button ("I am completely inside an Area");
        GUILayout.EndArea ();
    }

}


エリア内で、ボタンやボックスのような表示要素は、その幅をエリアの全体の長さにまで延長します。

自動レイアウト - 水平と垂直グループ

自動レイアウトを使用すると、コントロールはデフォルトで次々と上から下に表示されます。コントロールを配置する場所や配置方法をより繊細にコントロールする必要がある場合が多くあります。自動レイアウトモードを使用している場合、水平や垂直グループのオプションがあります。

その他のレイアウトコントロール同様、個々の関数を呼び出して、これらのグループを開始や終了できます。この関数は、GUILayout.BeginHoriztontal()GUILayout.EndHorizontal()GUILayout.BeginVertical()GUILayout.EndVertical() です。

水平グループ内のコントロールは常に水平に配置されます。垂直グループ内のコントロールは常に垂直に配置されます。これは、グループをそれぞれの内部でネスト化するまでは簡単に聞こえます。これにより、想像できる構成で、任意の数のコントロールを配置できます。

/* ネストになった水平と垂直のグループ を使用 */


// JavaScript
var sliderValue = 1.0;
var maxSliderValue = 10.0;

function OnGUI()
{
    //指定した GUI Area のすべてをラップ
    GUILayout.BeginArea (Rect (0,0,200,60));

    // 1 つの水平グループを開始 
    GUILayout.BeginHorizontal();

    // ボタンを通常通り配置
    if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
    {
        maxSliderValue += 3.0 * Time.deltaTime;
    }

    // ボタンの横に、垂直方向にコントロールをもう2 つ設定
    GUILayout.BeginVertical();
    GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
    sliderValue = GUILayout.HorizontalSlider (sliderValue, 0.0, maxSliderValue);

    // Groups と Area を終了
    GUILayout.EndVertical();
    GUILayout.EndHorizontal();
    GUILayout.EndArea();
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
    
    private float sliderValue = 1.0f;
    private float maxSliderValue = 10.0f;
    
    void OnGUI()
    {
        // 指定した GUI Area のすべてをラップ
        GUILayout.BeginArea (new Rect (0,0,200,60));
    
        //1 つの水平グループを開始 
        GUILayout.BeginHorizontal();
    
        //ボタンを通常通り配置
        if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
        {
            maxSliderValue += 3.0f * Time.deltaTime;
        }
    
        // ボタンの横に、垂直方向にコントロールをもう2 つ設定
        GUILayout.BeginVertical();
        GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
        sliderValue = GUILayout.HorizontalSlider (sliderValue, 0.0f, maxSliderValue);
    
        // Groups と Area を終了
        GUILayout.EndVertical();
        GUILayout.EndHorizontal();
        GUILayout.EndArea();
    }

}


水平と垂直グループで配置された 3 つのコントロール
水平と垂直グループで配置された 3 つのコントロール

一部のコントロールを制御するための GUILayoutOption の使用

GUILayoutOptions を使用して、自動レイアウトパラメーターの一部を無効にできます。これは、GUILayout コントロールの最終パラメーターを渡すことで行います。

上記の例のエリアでは、ボタンはその幅をエリアの最大幅に延長します。必要な場合はこれを無効にできます。

/* GUILayoutOptions を使って自動レイアウトコントロールプロパティーをオーバーライド */


//JavaScript
function OnGUI () {
    GUILayout.BeginArea (Rect (100, 50, Screen.width-200, Screen.height-100));
    GUILayout.Button ("I am a regular Automatic Layout Button");
    GUILayout.Button ("My width has been overridden", GUILayout.Width (95));
    GUILayout.EndArea ();
}


// C#
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
        
    void OnGUI () {
        GUILayout.BeginArea (new Rect (100, 50, Screen.width-200, Screen.height-100));
        GUILayout.Button ("I am a regular Automatic Layout Button");
        GUILayout.Button ("My width has been overridden", GUILayout.Width (95));
        GUILayout.EndArea ();
    }

}


考えられる GUILayoutOption の完全なリストに関しては、GUILayoutOption を参照してください。

カスタマイズ
IMGUI の拡張