Version: 2019.3
Immediate Mode GUI (IMGUI)
Контролы

IMGUI Basics

This section will explain the bare necessities for scripting Controls with Unity’s Immediate Mode GUI system (IMGUI).

Making Controls with IMGUI

Unity’s IMGUI controls make use of a special function called OnGUI(). The OnGUI() function gets called every frame as long as the containing script is enabled - just like the Update() function.

IMGUI controls themselves are very simple in structure. This structure is evident in the following example.

/* Example level loader */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour {
            
    void OnGUI ()
    {
        // Make a background box
        GUI.Box(new Rect(10,10,100,90), "Loader Menu");
    
        // Make the first button. If it is pressed, Application.Loadlevel (1) will be executed
        if(GUI.Button(new Rect(20,40,80,20), "Level 1"))
        {
            Application.LoadLevel(1);
        }
    
        // Make the second button.
        if(GUI.Button(new Rect(20,70,80,20), "Level 2")) 
        {
            Application.LoadLevel(2);
        }
    }
}

Этот пример является полным функциональным загрузчиком уровня. Если вы скопируете скрипт, и прикрепите его к GameObject’у, вы увидите, что появится следующее меню после входа в Play Mode:

The Loader Menu created by the example code
The Loader Menu created by the example code

Давайте посмотрим на детали кода примера:

Первая строка GUI, GUI.Box (Rect (10,10,100,90), “Loader Menu”); отображает контрол Box с заголовком “Loader Menu”. Он следует типичной схеме объявления контролов, которую мы вскоре рассмотрим.

Следующая строка GUI - это объявление контрола Button (кнопка). Заметьте, что оно немного отличается от объявления контрола Box. В частности, всё объявление кнопки помещено в оператор if. Когда при запущенной игре нажимается кнопка, этот оператор if возвращает true и выполняется любой код в блоке if.

Так как код в методе OnGUI() вызывается каждый кадр, вам не требуется явно создавать или удалять GUI контролы. Линия, объявляющая контрол, по сути и создаёт его. Если вам требуется отобразить контролы в определённый момент, вы можете использовать любой вид программной логики для этого.

/* Flashing button example */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour
{
            
    void OnGUI () 
    {
        if (Time.time % 2 < 1) 
        {
            if (GUI.Button (new Rect (10,10,200,20), "Meet the flashing button"))
            {
                print ("You clicked me!");
            }
        }
    }
}

В этом примере GUI.Button() вызывается только каждую вторую секунду, так что кнопка будет появляться и исчезать. Пользователь может кликнуть по кнопке только тогда, когда она видна.

Как вы видите, вы можете использовать любую желаемую логику для управления отображением и функционалом GUI контролов. Теперь детально рассмотрим объявление каждого их контролов.

Анатомия контрола

Для определения GUI контрола требуется три ключевых части информации:

Тип (позиция, содержимое)

Заметьте, что эта структура - функция с двумя аргументами. Сейчас мы подробно рассмотрим эту структуру.

Тип

Тип это тип контрола, и он определяется с помощью вызова функции Unity GUI class или GUILayout class, которая подробно описана в режимах расположения. Например, GUI.Label() создаст неинтерактивный Label. Все остальные типы контролов будут описаны позже, в секции Контролы этого руководства.

Позиция

Позиция - это первый аргументы в любой функции контролов GUI. Сам по себе аргумент предоставляется в виде функции Rect(). Rect() определяет 4 свойства: левая позиция, верхняя позиция, ширина, высота. Все эти значения передаются в целых числах (integers), которые соответствуют пиксельным значениям. Все UnityGUI контролы работают в экранном пространстве (Screen Space), которое по сути разрешение в пикселях опубликованного проигрывателя.

Отсчёт координат производится из левого верхнего угла. Rect(10, 20, 300, 100) определяет Rectangle, который начинается в координатах: 10,20 и заканчивается в 310,120. Стоит повторить, что вторая пара чисел в Rect() это ширина и высота, а не координаты, где должен закончиться контрол. Вот почему в приведённом выше примере контрол заканчивается в 310,120 а не 300,100.

Вы можете использовать свойства Screen.width и Screen.height для получения общих размеров экрана, доступных проигрывателю. Следующий пример может прояснить как это делается:

/* Screen.width & Screen.height example */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour 
{
            
    void OnGUI()
    {
        GUI.Box (new Rect (0,0,100,50), "Top-left");
        GUI.Box (new Rect (Screen.width - 100,0,100,50), "Top-right");
        GUI.Box (new Rect (0,Screen.height - 50,100,50), "Bottom-left");
        GUI.Box (new Rect (Screen.width - 100,Screen.height - 50,100,50), "Bottom-right");
    }

}
The Boxes positioned by the above example
The Boxes positioned by the above example

Содержимое

Второй аргумент для GUI контрола - это содержимое для отображения в контроле. Чаще всего вы захотите отобразить какой-то текст или картинку в вашем контроле. Чтобы показать текст, передайте строку в качестве аргументы, например, так:

using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour 
{
    void OnGUI ()
    {
        GUI.Label (new Rect (0,0,100,50), "This is the text string for a Label Control");
    }
}

Чтобы показать картинку, объявите публичную переменную типа Texture2D и передайте её имя в качестве аргумента, например так:

/* Texture2D Content example */
public Texture2D controlTexture;
  ...

void OnGUI () 
{
    GUI.Label (new Rect (0,0,100,50), controlTexture);
}

Вот приближённый к реальной жизни пример:

/* Button Content examples */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour
{
    public Texture2D icon;
    
    void OnGUI () 
    {
        if (GUI.Button (new Rect (10,10, 100, 50), icon)) 
        {
            print ("you clicked the icon");
        }
    
        if (GUI.Button (new Rect (10,70, 100, 20), "This is text")) 
        {
            print ("you clicked the text button");
        }
    }
}
The Buttons created by the above example
The Buttons created by the above example

В GUI контроле существует и третья опция, позволяющая показывать и текст и картинки вместе. Вы можете передать объект GUIContent в качестве аргумента “содержимое” и определить строку и отображаемую картинку в GUIContent.

/* Using GUIContent to display an image and a string */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour
{
    public Texture2D icon;

    void OnGUI () 
    {
        GUI.Box (new Rect (10,10,100,50), new GUIContent("This is text", icon));
    }
}

Вы также можете определять Tooltip (всплывающую подсказку) в GUIContent и отображать её где-то в GUI при наведении мышки.

/* Using GUIContent to display a tooltip */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour 
{
    void OnGUI () 
    {
        // This line feeds "This is the tooltip" into GUI.tooltip
        GUI.Button (new Rect (10,10,100,20), new GUIContent ("Click me", "This is the tooltip"));
        
        // This line reads and displays the contents of GUI.tooltip
        GUI.Label (new Rect (10,40,100,20), GUI.tooltip);
    }
}

You can also use GUIContent to display a string, an icon, and a tooltip.

/* Using GUIContent to display an image, a string, and a tooltip */
using UnityEngine;
using System.Collections;

public class GUITest : MonoBehaviour 
{
    public Texture2D icon;
    
    void OnGUI () 
    {
        GUI.Button (new Rect (10,10,100,20), new GUIContent ("Click me", icon, "This is the tooltip"));
        GUI.Label (new Rect (10,40,100,20), GUI.tooltip);
    }
}

В справке по конструктору GUIContent есть несколько примеров его использования.

Immediate Mode GUI (IMGUI)
Контролы