Version: 5.3 (switch to 5.4b)
Кастомизация
Расширение UnityGUI

Режимы расположения

Фиксированное расположение vs автоматическое расположение

Существует два разных режима для расположения и организации GUI: Fixed (фиксированный) и Automatic (автоматический). Во всех примера использования UnityGUI, представленных до сих пор, было фиксированное расположение. Для использования автоматического, пишите GUILayout вместо GUI при вызове функций контролов. Вы не обязаны использовать только один режим расположения вместо другого и вы можете использовать оба режима одновременно в одной и той же функции OnGUI().

Фиксированное расположение имеет смысл, когда у вас есть заранее подготовленный дизайн, опираясь на который вы можете работать. Автоматическое расположение имеет смысл, когда вы не знаете как много элементов вам понадобится, или если не хотите заниматься расположением каждого контрола вручную. Например, если вы создаёте разные кнопки, количество которых зависит от количества сохранённых игр, вы не знаете в точности как много кнопок придётся отрисовать. В таком случае автоматическое расположение будет очень к месту. Выбор режима расположения сильно зависит от дизайна игры и от того, как вы желаете представлять ваш интерфейс пользователю

Существует два ключевых различия при использовании автоматического расположения:

  • GUILayout is used instead of GUI
  • Функция Rect() не требуется для контролов с автоматическим расположением
/* Two key differences when using Automatic Layout */


// JavaScript
function OnGUI () {
    // Fixed Layout
    GUI.Button (Rect (25,25,100,30), "I am a Fixed Layout Button");

    // Automatic Layout
    GUILayout.Button ("I am an Automatic Layout Button");
}


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

public class GUITest : MonoBehaviour {
    
    void OnGUI () {
        // Fixed Layout
        GUI.Button (new Rect (25,25,100,30), "I am a Fixed Layout Button");
    
        // Automatic Layout
        GUILayout.Button ("I am an Automatic Layout Button");
    }

}


Выстраивание контролов

В зависимости от используемого режима расположения, существует различные подходы к контролированию позиционирования и группирования контролов. При фиксированном расположении, вы можете поместить разные контролы в группы (Groups). При автоматическом расположении, вы можете разместить различные контролы в областях (Areas), горизонтальных группах (Horizontal Groups) и вертикальных группах (Vertical Groups).

Фиксированное расположение - группы

Группы - это соглашение, доступное в фиксированном режиме расположения. Они позволяют вам определять области на экране, которые содержат несколько контролов. Вы определяете, какие контролы будут внутри группы с помощью функций GUI.BeginGroup() и GUI.EndGroup(). Все контролы внутри группы будет размещены на основе левого верхнего угла группы вместо левого верхнего угла экрана. Таким образом, если вы в реальном времени измените позицию группы, сохранятся относительные позиции всех контролов в группе.

Например, очень просто центрировать несколько контролов на экране.

/* Center multiple Controls on the screen using Groups */


// JavaScript
function OnGUI () {
    // Make a group on the center of the screen
    GUI.BeginGroup (Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100));
    // All rectangles are now adjusted to the group. (0,0) is the topleft corner of the group.
    
    // We'll make a box so you can see where the group is on-screen.
    GUI.Box (Rect (0,0,100,100), "Group is here");
    GUI.Button (Rect (10,40,80,30), "Click me");
    
    // End the group we started above. This is very important to remember!
    GUI.EndGroup ();
}


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

public class GUITest : MonoBehaviour {
    
    void OnGUI () {
        // Make a group on the center of the screen
        GUI.BeginGroup (new Rect (Screen.width / 2 - 50, Screen.height / 2 - 50, 100, 100));
        // All rectangles are now adjusted to the group. (0,0) is the topleft corner of the group.
    
        // We'll make a box so you can see where the group is on-screen.
        GUI.Box (new Rect (0,0,100,100), "Group is here");
        GUI.Button (new Rect (10,40,80,30), "Click me");
    
        // End the group we started above. This is very important to remember!
        GUI.EndGroup ();
    }

}


Пример выше центрирует контролы, независимо от разрешения экрана
Пример выше центрирует контролы, независимо от разрешения экрана

Вы также можете вкладывать несколько групп друг в друга. Когда вы так делаете, содержимое каждой группы обрезается по площади её родителя.

/* Using multiple Groups to clip the displayed Contents */


// JavaScript
var bgImage : Texture2D; // background image that is 256 x 32
var fgImage : Texture2D; // foreground image that is 256 x 32
var playerEnergy = 1.0; // a float between 0.0 and 1.0

function OnGUI () {
    // Create one Group to contain both images
    // Adjust the first 2 coordinates to place it somewhere else on-screen
    GUI.BeginGroup (Rect (0,0,256,32));

    // Draw the background image
    GUI.Box (Rect (0,0,256,32), bgImage);
    
    // Create a second Group which will be clipped
    // We want to clip the image and not scale it, which is why we need the second Group
    GUI.BeginGroup (Rect (0,0,playerEnergy * 256, 32));

    // Draw the foreground image
    GUI.Box (Rect (0,0,256,32), fgImage);

    // End both Groups
    GUI.EndGroup ();
    GUI.EndGroup ();
}


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

public class GUITest : MonoBehaviour {
    
    // background image that is 256 x 32
    public Texture2D bgImage; 
    
    // foreground image that is 256 x 32
    public Texture2D fgImage; 
    
    // a float between 0.0 and 1.0
    public float playerEnergy = 1.0f; 
    
    void OnGUI () {
        // Create one Group to contain both images
        // Adjust the first 2 coordinates to place it somewhere else on-screen
        GUI.BeginGroup (new Rect (0,0,256,32));
    
        // Draw the background image
        GUI.Box (new Rect (0,0,256,32), bgImage);
    
            // Create a second Group which will be clipped
            // We want to clip the image and not scale it, which is why we need the second Group
            GUI.BeginGroup (new Rect (0,0,playerEnergy * 256, 32));
        
            // Draw the foreground image
            GUI.Box (new Rect (0,0,256,32), fgImage);
        
            // End both Groups
            GUI.EndGroup ();
        
        GUI.EndGroup ();
    }

}


Вы можете вкладывать группы друг в друга для создания эффектов обрезания содержимого
Вы можете вкладывать группы друг в друга для создания эффектов обрезания содержимого

Автоматическое расположение - области

Области используются только в автоматическом режиме расположения. Они работают аналогично группам фиксированного расположения, т.к. определяют конечную часть экрана для содержания GUILayout контролов. Из-за природы автоматического расположения, вы почти всегда будете использовать области.

В режиме автоматического расположения, вы не определяется область экрана на уровне контролов, в которой будут отрисовываться контролы. Контрол будет автоматически расположен в самой верхней левой точке своей области. Ею может быть и экран. Вы также можете создавать области для размещения вручную. GUILayout контролы в какой-либо области будут расположены в левой верхней точке этой области.

/* A button placed in no area, and a button placed in an area halfway across the screen. */


// 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 ();
    }

}


Учтите, что ширина контролов с видимыми элементами (такими как кнопки и Box’ы), расположенных внутри области, будет растягиваться до полного заполнения длины области.

Автоматическое расположение - горизонтальные и вертикальные группы

При использовании автоматического расположения, контролы будут по умолчанию появляться один за другим, сверху вниз. Существует ряд случаев, в которых вам может потребоваться более точный уровень контроля над тем, где расположены контролы и как они выстроены. Если вы используете автоматическое расположение, у вас есть выбор между горизонтальной и вертикальной группами.

Как и при работе с другими контролами расположения, вы можете вызывать отдельные функции для старта и окончания этих групп. Для этого можно использовать функции GUILayout.BeginHoriztontal(), GUILayout.EndHorizontal(), GUILayout.BeginVertical(), и GUILayout.EndVertical().

Любые контролы внутри горизонтальной группы всегда будут размещаться горизонтально. Любые контролы в вертикальной группе всегда будут размещаться вертикально. Это звучит просто до тех пор, пока вы не начнёте вкладывать группы друг в друга. Это позволяет вам выстраивать любое количество контролов в любой конфигурации, которую только можно себе представить.

/* Using nested Horizontal and Vertical Groups */


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

function OnGUI()
{
    // Wrap everything in the designated GUI Area
    GUILayout.BeginArea (Rect (0,0,200,60));

    // Begin the singular Horizontal Group
    GUILayout.BeginHorizontal();

    // Place a Button normally
    if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
    {
        maxSliderValue += 3.0 * Time.deltaTime;
    }

    // Arrange two more Controls vertically beside the Button
    GUILayout.BeginVertical();
    GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
    sliderValue = GUILayout.HorizontalSlider (sliderValue, 0.0, maxSliderValue);

    // End the Groups and 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()
    {
        // Wrap everything in the designated GUI Area
        GUILayout.BeginArea (new Rect (0,0,200,60));
    
        // Begin the singular Horizontal Group
        GUILayout.BeginHorizontal();
    
        // Place a Button normally
        if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
        {
            maxSliderValue += 3.0f * Time.deltaTime;
        }
    
        // Arrange two more Controls vertically beside the Button
        GUILayout.BeginVertical();
        GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
        sliderValue = GUILayout.HorizontalSlider (sliderValue, 0.0f, maxSliderValue);
    
        // End the Groups and Area
        GUILayout.EndVertical();
        GUILayout.EndHorizontal();
        GUILayout.EndArea();
    }

}


Три контрола, выстроенные в горизонтальных и вертикальных группах
Три контрола, выстроенные в горизонтальных и вертикальных группах

Использование GUILayoutOptions для определения некоторых контролов

Вы можете использовать GUILayoutOptions для переназначения некоторых параметров автоматического расположения. Для этого вам нужно передать опции в качестве последних аргументов GUILayout контролов.

Помните пример с областями, где кнопка растягивается на 100% ширины области? Мы можем это переназначить, если захотим.

/* Using GUILayoutOptions to override Automatic Layout Control properties */


//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 ();
    }

}


Для полного списка возможных опций GUILayoutOptions, пожалуйста, простите страницу справки по классу GUILayoutOption.

Кастомизация
Расширение UnityGUI