版本:Unity 6 (6000.0)
语言:English
自定义您的 IMGUI 控件
扩展 IMGUI

IMGUI 布局模式

固定布局与自动布局

在使用 IMGUI 系统时,您可以使用两种不同的模式来排列和组织您的UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三种 UI 系统。 更多信息
参见 术语表
:固定和自动。到目前为止,本指南中提供的每个 IMGUI 示例都使用了固定布局。要使用自动布局,请在调用控件函数时编写GUILayout而不是GUI。您不必在一种布局模式与另一种布局模式之间进行选择,并且可以在同一个OnGUI()函数中同时使用这两种模式。

当您有一个预先设计的界面需要从中工作时,使用固定布局是有意义的。当您事先不知道需要多少元素,或者不想担心手动定位每个控件时,使用自动布局是有意义的。例如,如果您根据存档文件创建了许多不同的按钮,则您不知道将绘制多少个按钮。在这种情况下,自动布局可能更有意义。它实际上取决于您游戏的界面设计以及您希望如何呈现界面。

使用自动布局时,有两个主要区别

  • GUILayout用于代替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");
    }

}


排列控件

根据您使用的布局模式,有不同的钩子用于控制控件的位置以及控件如何分组。在固定布局中,您可以将不同的控件放入中。在自动布局中,您可以将不同的控件放入区域水平组垂直组中。

固定布局 - 组

组是固定布局模式中提供的一种约定。它们允许您定义包含多个控件的屏幕区域。您可以使用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 ();
    }

}


The above example centers controls regardless of the screen resolution
以上示例无论屏幕分辨率如何都能使控件居中

您还可以将多个组嵌套在彼此内部。当您这样做时,每个组的内容都会被剪裁到其父级空间。

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

}


You can nest Groups together to create clipping behaviors
您可以将组嵌套在一起以创建剪裁行为

自动布局 - 区域

区域仅在自动布局模式中使用。在功能上,它们类似于固定布局组,因为它们定义了屏幕的有限部分以包含 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 ();
    }

}


请注意,在区域内,具有可见元素(如按钮和框)的控件将将其宽度拉伸到区域的整个长度。

自动布局 - 水平和垂直组

使用自动布局时,控件默认情况下会从上到下依次出现。在很多情况下,您会希望更精细地控制控件的位置以及控件的排列方式。如果您使用的是自动布局模式,则可以选择水平组和垂直组。

与其他布局控件一样,您调用单独的函数来开始或结束这些组。具体函数为GUILayout.BeginHorizontal()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();
    }

}


Three Controls arranged with Horizontal & Vertical Groups
使用水平和垂直组排列的三个控件

使用 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 脚本参考页面

自定义您的 IMGUI 控件
扩展 IMGUI