效果图

使用UGUI来实现3DUI 动态跟随效果。
⚠️ 本章节如果遇到动画一类的脚本使用不会讲解,后续有专门的章节进行动画技巧讲解
⚠️ 本文按照大纲的阅读流程进行 如果有错误还请指出 本文会进行修正

概述

脚本结构

主要跟随脚本在 Canvas3D.cs 中实现,UI面板更新事件在 HudEventCatcher.cs 中被实现。

1
2
Canvas3D.cs
HudEventCatcher.cs

prefab结构

Prefab结构图
CamRig 结构下有两台摄像机,上级摄像机只处理3D物体,子节点摄像机负责处理3DUI.

功能实现

useCamDistanceResizer 决定3DUI面板是否动态朝向主摄像机。
followBone 实际是UI相对位置锚定的骨骼。此处使用的是 Head ,当动画运作时候UI会发生相应的位移。
transform 此处为当前整个 3DUI部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
public class Canvas3D : MonoBehaviour
{
//···

public HumanBodyBones bone = HumanBodyBones.Head;

//···

private Vector3 targetPosition;

//···

private void Start()
{
//···

playerCamera = player.GetComponent<SetupAndUserInput>().cameraRig.GetComponent<PlayerCamera>();

//···

followBone = player.GetComponent<Animator>().GetBoneTransform(bone);

//···
}

//···

private void Update()
{
//···

ManageSize();
}

//···

private void ManageSize()
{
//是否面向摄像机
if (!useCamDistanceResizer)
return;
//进行一个相对位移
targetPosition = followBone.position + playerCamera.transform.right * (playerCamera.currentOffset.x >= 0 ? 1 * rightFix : -1 * (leftFix)) + Vector3.up * upFix;
//使用插值平滑移动到新的位置(如果跟随的骨骼发生改变)
transform.position = Vector3.Lerp(transform.position, targetPosition, Time.deltaTime * positionLerpSpeed);
//直接设置角度 这里会造成3DUI屏幕转向有点抖动 源码
//transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, playerCamera.transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z);

//建议修改 此处我修改成如下,添加插值并且减少2/1的 positionLerpSpeed 增加平滑度。
float yAngle = Mathf.LerpAngle(transform.eulerAngles.y, playerCamera.transform.rotation.eulerAngles.y, Time.deltaTime * positionLerpSpeed / 2);
transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, yAngle, transform.rotation.eulerAngles.z);

//3D相机与UI的距离
float fov = Vector3.Distance(playerCamera.transform.position, transform.position);
//最大尺寸与最小尺寸阀值控制(微调选项)
float maxDif = maxScaleAtDist - minScaleAtDist;
float cDif = fov - minScaleAtDist;

//近大远小
float scale = Mathf.Lerp(minScale, maxScale, cDif / maxDif);
transform.localScale = Vector3.one * scale;
}

//···

}