布局模式

固定布局与自动布局

可以采用两种不同的模式来安排组织您的 GUI:固定模式和自动模式。目前为止,本指南中所提供 的所有 UnityGUI 示例都采用固定布局 (Fixed Layout)。要使用自动布局 (Automatic Layout) 模式,在调用控制函数时,写入 GUILayout 来代替 GUI。您不必逐个设置布局模式,并且还可以在同一 OnGUI() 函数中同时使用两种模式。

当您已经有了一个预先设计好界面可以用来工作时,就可以使用固定布局 (Fixed Layout)。当您之前不知道需要多少元素,或者不想手动安置每个控件时,则可以使用自动布局 (Automatic Layout)。比如,当您要根据保存游戏文件来创建若干不同按钮时,您可能不知道要绘制按钮的确切数目。在这种情况下使用自动布局 (Automatic Layout) 会更方便。这实际上取决于游戏的设计以及您想要如何呈现界面。

使用自动布局 (Automatic Layout) 时,存在两个关键的不同之处:

/* 使用自动布局 (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");
	}

}

安排控件

随您所使用的布局模式而定,可采用不同的挂钩来控制控件 (Controls) 的位置以及这些控件的集合方式。在固定布局 (Fixed Layout) 中,您可以将不同的控件 (Controls) 放入 群组 (Groups) 。在自动布局 (Fixed Layout) 中,您可以将不同的控件 (Controls) 放入 区域 (Areas)水平群组 (Horizontal Groups)垂直群组 (Vertical Groups)

固定布局 - 群组

群组 (Groups) 是固定布局模式 (Fixed Layout Mode) 下可用的惯例,使您能够定义包含多个控件 (Controls) 的屏幕区域。您通过使用GUI.BeginGroup() 函数和GUI.EndGroup() 函数来定义哪些控件 (Controls) 在一个群组 (Group) 内。一个群组 (Group) 内的所有控件 (Controls) 都将基于群组 (Group) 的左上角来放置而不是按屏幕的左上角。以此方式,当您在运行时重新调整该群组的位置时,群组内所有控件 (Controls) 的相对位置保持不变。

例如,可以很容易地把多个控件 (Controls) 放置在屏幕中心。

/* 使用群组 (Groups) 将多个控件 (Controls) 放置在屏幕中心 */


// 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 () {
		// 在屏幕中心创建群组
		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 ();
	}

}

上面示例将控件居中放置,不考虑屏幕分辨率

您也可以将多个群组 (Group) 嵌套进彼此内部。进行嵌套后,每个群组的内容都被剪切到其父级空间。

/* 使用多个群组 (Group) 剪切显示的内容  */


// JavaScript
var bgImage : Texture2D; // 256 x 32 背景图像
var fgImage : Texture2D; // /256 x 32 前景图像
var playerEnergy = 1.0; // 0.0 和 1.0 之间的一个浮点数

function OnGUI () {
	// 创建群组 (Group) 来容纳两幅图像
	// 调整开始的 2 个坐标以便将其放置在屏幕上的其他某处
	GUI.BeginGroup (Rect (0,0,256,32));

	// 绘制背景图像
	GUI.Box (Rect (0,0,256,32), bgImage);

	// 创建将被剪切的第二群组 (Group)
	// 我们要剪切而不是缩放图像,所以需要第二群组 (Group)
	GUI.BeginGroup (Rect (0,0,playerEnergy * 256, 32));

	// 绘制前景图像
	GUI.Box (Rect (0,0,256,32), fgImage);

	// 结束两个群组 (Groups)
	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 之间的一个浮点数
	public float playerEnergy = 1.0f; 

	void OnGUI () {
		// 创建群组 (Group) 来容纳两幅图像
		// 调整开始的 2 个坐标以便将其放置在屏幕上的其他某处
		GUI.BeginGroup (new Rect (0,0,256,32));

		// 绘制背景图像
		GUI.Box (new Rect (0,0,256,32), bgImage);

			// 创建将被剪切的第二群组 (Group)
			// 我们要剪切而不是缩放图像,所以需要第二群组 (Group)
			GUI.BeginGroup (new Rect (0,0,playerEnergy * 256, 32));

			// 绘制前景图像
			GUI.Box (new Rect (0,0,256,32), fgImage);

			// 结束两个群组 (Groups)
			GUI.EndGroup ();

		GUI.EndGroup ();
	}

}

您可以将群组 (Group) 嵌套起来创建剪切行为

自动布局 - 区域

区域 (Areas) 只在自动布局 (Automatic Layout) 模式中使用。区域在功能上与固定布局群组类似,因为它们定义了屏幕中有限的一部分来容纳 GUILayout 控件。由于自动布局 (Automatic Layout) 特性的原因,您几乎会总是用到区域 (Area)。

在自动布局 (Automatic Layout) 模式中,不必在控件层 (Control level) 定义要绘制控件的屏幕区域。控件 (Control) 将被自动放置到容纳区域的最左上角。这有可能是屏幕。您也可以创建手动放置区域 (Areas)。区域内的 GUILayout 控件 (GUILayout Control) 将被放置到该区域的最左上角。

/* 一个按钮未放置在区域中,以及一个按钮放置在横跨半个屏幕的区域中。 */


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

}

注意,在一个区域 (Area) 内,带按钮 (Buttons)、框 (Boxes) 等可见元素的控件都会将其宽度拉伸至区域 (Area) 的全长。

自动布局 - 水平群组和垂直群组

使用自动布局 (Automatic Layout) 时,在默认情况下控件从上到下依次出现。在很多情况下,您想要更精细地控制控件的位置和排布方式。如果您使用自动布局 (Automatic Layout) 模式,就可以选择水平群组和垂直群组。

像其他的布局控件 (Control) 一样,您可以调用不同的函数来开始或结束群组。函数具体为 GUILayout.BeginHoriztontal()GUILayout.EndHorizontal()GUILayout.BeginVertical()GUILayout.EndVertical()

水平群组 (Horizontal Group) 内的所有控件 (Control) 都会水平排列。垂直群组 (Horizontal Group) 内的所有控件 (Control) 都会垂直排列。这听起来很罗嗦,但在您开始进行群组内部的嵌套时才会发现其实不然。这使您能够将任何数量的控件以任何可以想象到的配置来安排。

/* 使用嵌套的水平群组和垂直群组 */


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

function OnGUI()
{
	// 将所有内容纳入指定 GUI 区域
	GUILayout.BeginArea (Rect (0,0,200,60));

	// 开始单个水平群组 (Horizontal Group)
	GUILayout.BeginHorizontal();

	// 按常规放置按钮 (Button)
	if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
	{
		maxSliderValue += 3.0 * Time.deltaTime;
	}

	// 将另外两个控件垂直地放在按钮 (Controls) 旁边
	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 区域
		GUILayout.BeginArea (new Rect (0,0,200,60));

		// 开始单个水平群组 (Horizontal Group)
		GUILayout.BeginHorizontal();

		// 按常规放置按钮 (Button)
		if (GUILayout.RepeatButton ("Increase max\nSlider Value"))
		{
			maxSliderValue += 3.0f * Time.deltaTime;
		}

		// 将另外两个控件垂直地放在按钮 (Controls) 旁边
		GUILayout.BeginVertical();
		GUILayout.Box("Slider Value: " + Mathf.Round(sliderValue));
		sliderValue = GUILayout.HorizontalSlider (sliderValue, 0.0f, maxSliderValue);

		// 结束群组 (Groups) 和 区域 (Area)
		GUILayout.EndVertical();
		GUILayout.EndHorizontal();
		GUILayout.EndArea();
	}

}

三个控件按照水平群组和垂直群组排列

使用 GUILayoutOptions 定义某些控件

您可以使用 GUILayoutOptions 覆盖自动布局 (Automatic Layout) 的某些参数。通过提供 选项作为 GUILayout 控件 (GUILayout Control) 的最终参数可实现此功能。

可否记得在上面的区域 (Areas) 示例中,按钮将其宽度延伸到区域宽度的 100%?若有需要随时可以将其覆盖。

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

}

有关可能的 GUILayoutOptions 的完整列表,请参阅 GUILayoutOption 脚本参考页面

Page last updated: 2013-06-28