UI组件是UGF最常用的组件之一,UIComponent界面组件中完成了UI辅助器及界面组Group的创建。
3DUI功能扩展
玩VR游戏时,3DUI可能会存在于场景中的某一固定位置,或跟随某一物体。此时UI的坐标不再是Vector3.zero,层级关系也不位于框架组件的UI中。
从UI层级结构可以看到Group组在UI Form Instances下。这时可以改变Group组的父物体以及坐标,来实现想要的功能。
创建UI3DComponent 组件,继承于UIComponent
创建如下字典,Group名与游戏对象对应关系,awake中初始化
private Dictionary<string, Transform> CustomUIGroupHelpers;
重写Addgroup(string uiGroupName, int depth)方法,在其中给字典赋值
CustomUIGroupHelpers.Add(uiGroupName, transform);
随后创建ChangeGroupPos(string uiGroupName, Transform parents)方法,当场景切换完成后,可以调用ChangeGroupPos改变Group组的父物体parents,来完成3DUI的功能,如有需要,传入parents之外,也可以传入Group的坐标。如果界面是浮动的,我们可以给parents添加随动相关的逻辑。
当需要切换场景是,调用ReGroupPos将Group还原到框架中,防止丢失。
using GameFramework;
using System.Collections.Generic;
using UnityEngine;
namespace UnityGameFramework.Runtime
{
/// <summary>
/// 界面组件。
/// </summary>
[DisallowMultipleComponent]
[AddComponentMenu("Game Framework/UI3D")]
public class UI3DComponent : UIComponent
{
private Dictionary<string, Transform> CustomUIGroupHelpers;
private float Scale = 0.001f;
/// <summary>
/// 游戏框架组件初始化。
/// </summary>
protected override void Awake()
{
base.Awake();
CustomUIGroupHelpers = new Dictionary<string, Transform>();
}
/// <summary>
/// 增加界面组。
/// </summary>
/// <param name="uiGroupName">界面组名称。</param>
/// <param name="depth">界面组深度。</param>
/// <returns>是否增加界面组成功。</returns>
public override bool AddUIGroup(string uiGroupName, int depth)
{
if (m_UIManager.HasUIGroup(uiGroupName))
{
return false;
}
UIGroupHelperBase uiGroupHelper = Helper.CreateHelper(m_UIGroupHelperTypeName, m_CustomUIGroupHelper, UIGroupCount);
if (uiGroupHelper == null)
{
Log.Error("Can not create UI group helper.");
return false;
}
uiGroupHelper.name = Utility.Text.Format("UI Group - {0}", uiGroupName);
uiGroupHelper.gameObject.layer = LayerMask.NameToLayer("UI");
Transform transform = uiGroupHelper.transform;
transform.SetParent(m_InstanceRoot);
transform.localPosition = Vector3.zero;
transform.localEulerAngles = Vector3.zero;
transform.localScale = Vector3.one * Scale;
CustomUIGroupHelpers.Add(uiGroupName, transform);
return m_UIManager.AddUIGroup(uiGroupName, depth, uiGroupHelper);
}
/// <summary>
/// 改变界面组坐标
/// </summary>
/// <param name="uiGroupName">界面组名称。</param>
/// <param name="depth">界面组父物体。</param>
public bool ChangeGroupPos(string uiGroupName, Transform parents)
{
if (!m_UIManager.HasUIGroup(uiGroupName))
{
return false;
}
Transform transform = CustomUIGroupHelpers[uiGroupName];
if (transform == null)
{
Log.Error("Can not find UI group helper.");
return false;
}
transform.SetParent(parents);
transform.localPosition = Vector3.zero;
transform.localEulerAngles = Vector3.zero;
transform.localScale = Vector3.one;
return true;
}
/// <summary>
/// 恢复界面组层级
/// </summary>
/// <param name="uiGroupName">界面组名称。</param>
/// <param name="depth">界面组父物体。</param>
public bool ReGroupPos(string uiGroupName)
{
if (!m_UIManager.HasUIGroup(uiGroupName))
{
return false;
}
Transform transform = CustomUIGroupHelpers[uiGroupName];
if (transform == null)
{
Log.Error("Can not find UI group helper.");
return false;
}
transform.SetParent(m_InstanceRoot);
transform.localPosition = Vector3.zero;
transform.localEulerAngles = Vector3.zero;
transform.localScale = Vector3.one;
return true;
}
}
}
代码完成后,替换掉原来的UI组件,代码里的注册逻辑对应也改成UI3D。
GameEntry.Builtin
/// <summary>
/// 获取界面组件。
/// </summary>
public static UI3DComponent UI3D
{
get;
private set;
}
创建上述脚本,并调用后,会发现初始坐标对不上。再打开脚本DefaultUIFormHelper,在CreateUIForm方法里重置局部坐标
transform.localPosition = Vector3.zero;
transform.localEulerAngles = Vector3.zero;
注意:3Dgroup下的UI需要设置为World Space。一般3DUI和2DUI用一个即可,一起用的话还没有试过,有兴趣的小伙伴可以探索下。