Skip to content

简介

使用 UI 组件类(UI Component) 组件(Component)可以将 UI 分配给场景中的 游戏对象(Game Object),这样才能控制 UI 的显示与否以及其显示模式。 UI 组件类(UI Component) 组件 需要引用 UI 资产,后者定义并控制在客户端以哪种界面模式显示哪个 UI。

组件逻辑

一个游戏项目中通常会有多个 UI, 在 SandMod 编辑器中通常会通过控制 游戏对象(Game Object)显隐和挂载逻辑脚本 组件(Component)来控制 UI 的交互事件和显示的内容。

  • 将场景中控制 UI 显示与逻辑的 游戏对象(Game Object)添加 UI 组件类(UI Component) 组件(Component)。
  • 通过 UI 组件类(UI Component) 组件(Component)引用 UI 资产。
  • 通过 UI 资产储存 UI 的结构、功能和显示效果。

【UIComponent001.png】

创建方法

创建 UI 组件类(UI Component) 组件(Component)前,需要在 场景编辑器(Scene Editor)的 层级窗口(Hierarchy)或者 场景预览窗口(Scene)中,选中控制 UI 显示模式的 游戏对象(Game Object)。

方法一:

选中对应的 游戏对象 后,在 检视窗口(Inspector)窗口中用鼠标左键点击 添加组件(Add Component)> 渲染(Rendering) > UI 组件类(UI Component) 进行创建。

【UIComponent002.png】

方法二:

选中对应的 游戏对象 后,在 菜单栏(Menu Bar)中点击 组件(Component)> 渲染(Rendering) > UI 组件类(UI Component) 进行创建。

【UIComponent003.png】

属性

UI 组件类(UI Component) 组件(Component)包含以下属性:

【UIComponent004.png】

名称描述
界面(UI)附加到此 游戏对象(Game Object)的 UI 资产。
界面模式(UI Mode)UI 在屏幕上或作为 3D 空间对象进行渲染的方式。详情请参阅 界面模式 小节。
界面顺序(UI Order)UI 的顺序编号,编号越大,显示越在上层,界面顺序编号小 UI 的会被编号大的 UI 遮挡。此属性值输入框内可以输入 0 到 255 的整数。

当 界面模式(UI Mode)选择 场景模式(Scene)选项,该 组件(Component)会显示以下用于设置 3D UI 的属性:

【UIComponent005.png】

名称描述
界面排序层(UI Sorting Layer)排序层与 2D 系统中的 Sprite 图形结合使用。 排序是指不同 Sprite 的叠加顺序。
界面面向摄像机(UI Face Camera)在场景中 UI 界面是否始终面向摄像机。
True.png 勾选,即 UI 界面始终面向摄像机。
False.png不勾选,即 UI 界面不会刻意面向摄像机,其朝向会根据 游戏对象(Game Object)的变换(Transform)而定。
界面被 3D 遮挡(UI Occluded By 3D)在场景中 UI 界面是否会被其他 3D 游戏对象(Game Object)遮挡。
True.png勾选,即 UI 界面会被其他 3D 游戏对象 遮挡。
False.png不勾选,即 UI 界面不会被其他 3D 游戏对象 遮挡。
界面事件摄像机(UI Event Camera)指引用于处理 UI 事件的摄像机。
X 轴每单位像素值(Pixel Per Unit X)设置在场景中的每 1 个单位长度,显示 UI 的 X 轴上的多少像素。
Y 轴每单位像素值(Pixel Per Unit Y)设置在场景中的每 1 个单位长度,显示 UI 的 Y 轴上的多少像素。

界面模式

传统上,渲染 UI 的效果就好像是直接在屏幕上绘制的简单图形设计。也就是说,没有摄像机观察 3D 空间的概念。SandMod 便支持这种屏幕空间渲染方式,但也允许 UI 在场景中渲染为对象,具体取决于界面模式属性的值。可用的模式包括屏幕界面模式和场景界面模式。

【UIComponent006.png】

屏幕界面模式

在此模式下 UI 会进行缩放来适应屏幕,然后直接渲染而不参考场景或摄像机(即使场景中根本没有摄像机,也会渲染 UI)。如果更改屏幕的大小或分辨率,则 UI 将自动重新缩放进行适应。UI 将绘制在所有其他图形(例如摄像机视图)上。

【UIComponent007.png】

场景界面模式

此模式将 UI 视为场景中的平面对象进行渲染。但是,与屏幕界面模式不同,该平面可以不面对摄像机,可以根据喜好任意定向。画布的大小可以使用 X 轴每单位像素值属性和 Y 轴每单位像素值来设置,但是不建议使用 缩放工具(Scale Tool)和 矩形工具(Rect Tool)进行缩放,特别是在界面面向摄像机属性值为 不勾选(False)时,不同角度查看 UI 会变形,而且 UI 在屏幕上的大小将取决于摄像机的视角和距离。其他 游戏对象(Game Object)可以位于 UI 后面、穿透 UI 或位于 UI 前面。

【UIComponent008.png】

UI 交互逻辑

UI 组件类(UI Component) 组件(Component)除了提供显示 UI 的功能以外,通过编码与 UI 交互的逻辑 SandMod 也是建议通过 UI 组件类(UI Component)实现的。

获取被分配的 UI 资产

如果需要获取 游戏对象(Game Object)中 UI 组件类(UI Component)界面(UI)属性分配的 UI 资产( UI Asset)所对应的 UI 画布(Canvas),您可以通过 UIComponent.canvas 获取。详情请参阅 API 文档关于 UIComponent.canvas 的内容。

如示例中命名为 UIObtain 的游戏对象添加了 UI 组件类(UI Component)和控制 UI 逻辑的脚本(该脚本的类名为:UIScript) 组件(Component)

【UIComponent009.png】

其中获取分配到该游戏对象的 UI 资产所对应的 UI 画布,并保存为 _uiCanvas 私有变量,代码示例如下:

typescript
class UIScript extends Component {

    //定义私有变量保存 UI 组件类(UI Component);
    private _uiComponent: UIComponent;
    //定义私有变量保存 UI 画布;
    private _uiCanvas: Canvas;

    /*
    编辑运行时事件;
    */
    OnStart(): void {
        //获取 UI 组件类(UI Component)并将其保存为 _uiComponent 私有变量;
        this._uiComponent = this.gameObject.GetComponent(UIComponent);
        //获取 UI 画布并将其保存为 _uiCanvas 私有变量;
        this._uiCanvas = this._uiComponent.canvas;

    }

    OnUpdate(): void {
    }

}

获取 UI 对象

如果需要获取 UI 画布(Canvas)中的特定 UI 对象(UI Object),您可以通过 Canvas.FindChild(type,path) 结合 UI 对象的控件类型和层级关系获取。详情请参阅 API 文档关于 Canvas.FindChild(type,path) 的内容。

CAUTION

需要注意布局类型的 UI 对象和 视图(Panel)类型的 UI 对象 type 为 Control,具体请参阅 布局类型 章节和 视图 章节的内容。

值得注意的是,如果 UI 对象的层级关系过于复杂,可以直接在 UI 编辑器(UI Editor)的 层级窗口(Hierarchy)中右键打开对应的 UI 对象上下文菜单,点击 复制路径(Copy Path) 选项,UI 对象的 层级关系路径(path)将会复制到剪切板中。

【UIComponent010.png】

但是如果路径的起点是 UI 画布的名字,请记得粘贴至 Canvas.FindChild(type,path) 的传入参数 path 后将画布名字删除。

【UIComponent011.gif】

如示例中您需要在画布中获取命名为 ExitButton 的 UI 对象

【UIComponent012.png】

其中获取该 UI 对象,并保存为 _exitButton 变量,代码示例如下:

typescript
class UIScript extends Component {

    //定义私有变量保存 UI 组件类(UI Component);
    private _uiComponent: UIComponent;
    //定义私有变量保存 UI 画布;
    private _uiCanvas: Canvas;

    //定义私有变量保存 ExitButton UI 对象;
    private _exitButton:Button;

    /*
    编辑运行时事件;
    */
    OnStart(): void {
        //获取 UI 组件类(UI Component)并将其保存为 _uiComponent 私有变量;
        this._uiComponent = this.gameObject.GetComponent(UIComponent);
        //获取 UI 画布并将其保存为 _uiCanvas 私有变量;
        this._uiCanvas = this._uiComponent.canvas;

        //获取 UI 对象 ExitButton 并保存为 _exitButton 私有变量;
        this._exitButton = this._uiCanvas.FindChild(Button,"BackpackPanel/ExitButton");

    }

    OnUpdate(): void {
    }

}

UI 交互事件

UI 交互事件可以根据输入(即点击、触摸或自定义输入)将事件发送到游戏的 UI 对象(UI Object)中。UI 交互事件系统包含一些共同协作以发送事件的功能。

UI 交互事件的主要功能如下:

  • 管理视为选中状态的 UI 对象 。
  • 管理该 UI 对象 的事件输入类型 。
  • 管理事件状态 。
  • 发送事件。

UI 交互事件的代码格式如下:

typescript
_Control.AddEvent(ControlEvent.ControlEventType, (control: Control) =>
{
	//这里编辑点击按钮后发生的事件
});
  1. _Control 是选中状态的 UI 对象,类型可为 Control,或继承自 Control 的其他控件类型。
  2. ControlEventType 为事件输入类型,您可以参阅 API 文档 ControlEvent 的相关枚举内容。
  3. control 是在交互事件中指代当前选中状态的 UI 对象,命名可以按照您的使用习惯命名,类型可为 Control,或继承自 Control 的其他控件类型。
  4. 如果您需要获取 UI 交互事件的相关参数的返回值(如获取点击按钮时对应的屏幕坐标),请参阅 API 文档关于 GUIEventData 的相关枚举内容。

例如需要代码示例如下:

typescript
class UIScript extends Component {

    //定义私有变量保存 UI 组件类(UI Component);
    private _uiComponent: UIComponent;
    //定义私有变量保存 UI 画布;
    private _uiCanvas: Canvas;

    //定义私有变量保存 ExitButton UI 对象;
    private _exitButton:Button;

    /*
    编辑运行时事件;
    */
    OnStart(): void {
        //获取 UI 组件类(UI Component)并将其保存为 _uiComponent 私有变量;
        this._uiComponent = this.gameObject.GetComponent(UIComponent);
        //获取 UI 画布并将其保存为 _uiCanvas 私有变量;
        this._uiCanvas = this._uiComponent.canvas;

        //获取 UI 对象 ExitButton 并保存为 _exitButton 私有变量;
        this._exitButton = this._uiCanvas.FindChild(Button,"BackpackPanel/ExitButton");

        /*
        编辑点击 ExitButton UI 对象的事件
         */
        this._exitButton.AddEvent(ControlEvent.EventClick, (exitButton: Button) =>
		{
			//这里编辑点击按钮后发生的事件
		});
      
    }

    OnUpdate(): void {
    }

}

值得注意的是,不是所有 UI 对象都能触发交互事件,需要 UI 对象有 射线投射目标(Raycast Target)属性且对应属性处于 勾选状态(True)才能触发交互事件。

【UIComponent013.png】

动态创建 UI 对象

如果需要在 UI 画布(Canvas)中创建特定 UI 对象(UI Object),您可以通过 GUIEngine.NewControl(type,parent) 结合 UI 对象的控件类型和父级关系创建 UI 对象。详情请参阅 API 文档关于 GUIEngine.NewControl(type,parent) 的内容。

如示例中您需要在画布中创建命名为 ItemImage 的图片类型 UI 对象,其父级对象为对应的 UI 画布(Canvas),并保存为 _itemImage 变量,代码示例如下:

typescript
class ControlCreation extends Component {

    //定义私有变量保存 UI 组件类(UI Component);
    private _uiComponent: UIComponent;
    //定义私有变量保存 UI 画布;
    private _uiCanvas: Canvas;

    //定义私有变量保存新创建的图片类型 UI 对象;
    private _itemImage:Image;

    /*
    编辑运行时事件;
    */
    OnStart(): void {
        //获取 UI 组件类(UI Component)并将其保存为 _uiComponent 私有变量;
        this._uiComponent = this.gameObject.GetComponent(UIComponent);
        //获取 UI 画布并将其保存为 _uiCanvas 私有变量;
        this._uiCanvas = this._uiComponent.canvas;
      
        //创建图片类型的 UI 对象,并保存为 _exitButton 私有变量;
        this._itemImage = GUIEngine.NewControl(Image,this._uiCanvas);
        //将新创建的图片类型的 UI 对象命名为 ItemImage;
        this._itemImage.name = "ItemImage";

    }

    OnUpdate(): void {
    }

}