
这次没有使用cocos自己的UICoordinateTracker,而是使用了自己写的逻辑,因为cocos的组件问题真的挺多的,就最开始使用角色控制器的时候,检测碰撞墙壁有时候竟然碰到墙之后不会动了.....这次使用UICoordinateTracker这个组件也是很不灵活,就像上篇文章写的那样,偏差很大,这次索性也自己写了一个,效果如图所示。
添加UI节点
创建一个label的ui节点,用于显示昵称,要显示血条等也是一样的,添加一个Sprite节点

创建跟随脚本
脚本逻辑如下:
获取3D对象的世界坐标(World Position)
将3D坐标转换为屏幕坐标(Screen Position)
将屏幕坐标转换为UI坐标(通常是Canvas下UI节点坐标)
设置UI节点位置,实现UI跟随3D对象移动
javascript
import {
_decorator,
Camera,
Component,
Node,
UITransform,
Vec3,
} from 'cc'
const { ccclass, property } = _decorator
@ccclass('follow')
export class follow extends Component {
@property({ type: Node })
playerNode: Node = null
@property({ type: Node })
uiNode: Node = null // 血条/昵称UI节点
@property({ type: Camera })
mainCamera: Camera = null // 3D摄像机
@property({ type: Node })
canvasNode: Node = null // Canvas节点
// 头顶偏移
private _offset: Vec3 = new Vec3(0, 2, 0)
update(dt: number) {
if (
!this.playerNode ||
!this.uiNode ||
!this.mainCamera ||
!this.canvasNode
)
return
// 1. 计算头顶世界坐标
const headWorldPos = this.playerNode
.getWorldPosition()
.add(this._offset)
// 2. 世界坐标转屏幕坐标
const screenPos = new Vec3()
this.mainCamera.worldToScreen(headWorldPos, screenPos)
console.log('screenPos', screenPos)
// 3. 屏幕坐标转UI坐标
const canvasUITrans = this.canvasNode.getComponent(UITransform)
const widgetPos = canvasUITrans.convertToNodeSpaceAR(
new Vec3(screenPos.x, screenPos.y, 0)
)
console.log('widgetPos', widgetPos)
// 4. 设置UI节点位置
this.uiNode.setPosition(widgetPos)
}
}
关联到节点
将节点关联到脚本上,PlayerNode就是你的角色节点,UINode就是昵称或血条节点,Main Camera就是主摄象机,CancasNode就是Canvas节点

特别注意
还有非常重要的一点就是屏幕分辨率,一定不要设置缩放,不然就会有移动偏差,这个问题困扰了我好久........后面还需要优化适配不同的分辨率
