基础组件相关
新建UI对象
通过Hierarchy窗口右键或菜单栏/GameObject创建一份新的UI对象:
选中UI下的复选框,大体分为两块,顶部带有 (VRC) 的四组,均为WorldSDK中VRC官方创建的示例,通过这个创建出来的UI能够直接兼容VRC;其余则是Unity中自带的组件。
如果你需要快速创建一个兼容VRC的UI来测试你的功能,则直接使用带有 (VRC) 的创建示例,否则正常情况下仍建议通过常规顺序来一步步创建你的UI对象,当然,你可以从VRC的创建示例魔改。
如果你在你的场景中首次创建UI对象,那么它不仅会有一个Canvas,还会有一个Event System对象,当然如果只是在vrc,Event System并不重要。
注意事项:
如果你的Scene场景中并没有UI对象,那么你创建的所有UI复选框下的对象,他的层级都是Canvas/xxx ;
如果你的Scene场景中有UI对象,那么你创建的UI复选框下的对象,它会直接在你的UI对象的子层级中的最底层/最下层新建:
一般情况下我们的世界场景中肯定存在多个UI对象,所有我们肯定要避免第二种情况,所以在我们要新建一个UI对象前,请让我们创建一个空对象作为这个新的UI对象的父层级 。
Canvas中的组件
Canvas:画布组件,主要用于渲染这个UI
一个Canvas组件就负责渲染自己的所有UI子对象,如果你的UI对象(控件)的父对象不是一个Canvas,那它大概率是出现问题的;Canvas组件提供几个参数可以调整与修改我们的UI渲染方式:
- RanderMode:控制着这个UI的渲染模式
- Screen Space - Overlay:屏幕空间覆盖,UI始终在前
- Screen Space - Camera:屏幕空间摄像机,场景中的3D物体是可以被渲染在UI前的
- World Space:世界空间,完全遵循3D世界,可以把这个UI堪称这个3D世界的一个3D物品(VRC中最常用的渲染模式)
- Pixel Perfect:无锯齿精准渲染(屏幕空间模式下可被启用)
- Sort Order:场景中存在多个Canvas,可以通过此项指定Canvas的排序层,数字越低越先被渲染(屏幕空间覆盖模式下选项)
- Target Display:渲染到目标设备(屏幕空间覆盖模式下选项,不重要)
- Render Camera:指定渲染UI的摄像机(屏幕空间摄像机模式下选项,如果默认不填则效果依旧遵循覆盖模式)
- Plane Distance:UI在摄像机前方的z轴距离(指定摄像机后开启此选项,如果物体在这个数值前,那么就会出现物体渲染在UI前的效果)
- Sorting Layer:排序层,新加的排序层默认都会比Default层高,遵循层级越低越先被渲染,(屏幕空间摄像机与世界空间下选项)
- Order in Layer:如果在同一排序层的渲染排序,数字越低越先被渲染(屏幕空间摄像机与世界空间下选项)
- Event Camera:指定用于处理UI事件的摄像机(世界空间下选项,VRC中可以默认不填并不会影响效果,独立开发如果不填则无法正常注册UI事件)
Canvas Scaler:画布分辨率自适应组件
RectTransform:UI位置锚点控制相关组件
Graphic Raycaster:射线事件交互组件,(不重要)
EventSystem中的组件(不重要)
玩家输入事件响应系统相关,VRC中会用UI shape脚本代替其作用在ClientSim,所以无需管它。
虽然不重要,只要不管它就行;不要删除!不要删除!不要删除!
SDK相关
VRC UI Shape:可以让玩家可以与UI对象交互的脚本。
此脚本必须添加在Canvas对象(UI对象)中才能起作用;
所有UI对象的Layer必须是非 “UI” 层,不然不起作用;(在UI层除非玩家打开VRChat菜单,否则UI层将阻止玩家交互,除非有特殊需求否则这种效果是不合时宜的:SDK中关于Layer相关使用)
Canvas中的RanderMode属性在大多数情况下应该是“World Space” 而并非“Screen Space” ,如果是VR状态下,是不能显示Screen Space下的内容的,如果想实现UI对象一直出现在屏幕中,可以通过GetTrackingData
方法获取本地玩家头部位置与旋转信息实时更新位置,示例代码:
using //
public class TestCanvas : UdonSharpBehaviour
{
private GameObject currentCanvas;
[SerializeField] private Vector3 pcOffset = new Vector3(0, 0.1f, 1.5f); // PC玩家的偏移量
[SerializeField] private Vector3 vrOffset = new Vector3(0, 0.3f, 1.0f); // VR玩家的偏移量
private void UpdateCanvasPosition() //实时更新函数
{
if (currentCanvas != null)
{
VRCPlayerApi localPlayer = Networking.LocalPlayer;
if (localPlayer != null)
{
// 获取玩家头部位置和朝向
Vector3 headPosition = localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).position;
Quaternion headRotation = localPlayer.GetTrackingData(VRCPlayerApi.TrackingDataType.Head).rotation;
// 偏移量选择
Vector3 offset = localPlayer.IsUserInVR() ? vrOffset : pcOffset;
// 计算Canvas的位置和旋转
Vector3 canvasPosition = headPosition + headRotation * offset;
// 设置Canvas的位置和旋转
currentCanvas.transform.position = canvasPosition;
currentCanvas.transform.rotation = headRotation;
}
}
}
void Update() //运行
{
//逻辑
UpdateCanvasPosition();
}
}