首先我觉得我的思路应该是正确的。就是把targetNode的世界坐标通过主相机转到屏幕空间,再由屏幕空间转到rectTransform的UI节点下,然后对这个UI坐标进行位置和方向计算。
还有最重要的一点:这个计算在3.6.3版本下是正确的,在3.8.x版本是错误的。
为了比较平滑的移动,你可以把里面的GuideInReectDemo的代码替换成以下代码:
import { Camera, Component, EventTouch, Node, Vec2, Vec3, _decorator } from 'cc';
const { ccclass, property } = _decorator;
const __vec2_temp1 = new Vec2()
const __vec2_temp2 = new Vec2()
const __vec3_temp1 = new Vec3()
@ccclass('GuideInRectDemo')
export class GuideInRectDemo extends Component {
@property(Camera)
readonly camera: Camera;
@property(Node)
readonly dragOperation: Node;
@property(Node)
readonly localPlayer: Node;
private isMoving: boolean = false;
private moveDirection = new Vec3;
onLoad() {
this.dragOperation.on(Node.EventType.TOUCH_START, this.touchStart, this);
this.dragOperation.on(Node.EventType.TOUCH_MOVE, this.touchMove, this);
this.dragOperation.on(Node.EventType.TOUCH_END, this.touchEnd, this);
this.dragOperation.on(Node.EventType.TOUCH_CANCEL, this.touchEnd, this);
}
protected update(dt: number): void {
if (!this.isMoving) return;
const direction = Vec3.multiplyScalar(__vec3_temp1, this.moveDirection, 3 * dt);
this.localPlayer.position = this.localPlayer.position.add(direction);
}
protected touchStart(event: EventTouch): void {
this.isMoving = true;
}
protected touchMove(event: EventTouch): void {
let startLocation = event.getUIStartLocation(__vec2_temp1);
let currentLocation = event.getUILocation(__vec2_temp2);
let dir = Vec2.subtract(__vec2_temp1, currentLocation, startLocation);
let distance = dir.length();
if (distance == 0) return;
const rotation = this.camera.node.worldRotation;
const direction = Vec3.transformQuat(__vec3_temp1, __vec3_temp1.set(dir.x, 0, -dir.y), rotation);
direction.y = 0;
this.moveDirection.set(direction).normalize();
}
protected touchEnd(event: EventTouch): void {
this.isMoving = false;
}
}