// CameraOrbit.ts import { _decorator, Component, Node, Vec3, EventTouch, input, Input, v3 } from 'cc'; const { ccclass, property } = _decorator; @ccclass('CameraOrbit') export class CameraOrbit extends Component { @property(Node) public targetNode: Node | null = null; // 需通过脚本动态设置目标节点 private lastTouchX: number = 0; private readonly rotationSpeed: number = 0.6; private isTouching: boolean = false; private currentAngle: number = 0; // 动态计算参数 private radius: number = 5; // 初始默认值,会自动修正 private heightOffset: number = 2; // 初始默认值,会自动修正 private centerOffset = v3(0, 1, 0);// 中心点Y偏移(角色腰部高度) // 初始化时自动校准参数 private isInitialized: boolean = false; start() { this.tryInitialize(); } // 每帧更新摄像机位置 lateUpdate() { if (!this.isInitialized) return; this.updateCameraPosition(true); // true表示保持当前角度 } // 动态设置目标节点 public setTarget(node: Node) { this.targetNode = node; this.tryInitialize(); } private tryInitialize() { if (!this.targetNode || this.isInitialized) return; // 计算机型参数与目标的相对关系 const targetWorldPos = this.targetNode.worldPosition; const cameraWorldPos = this.node.worldPosition; // 计算水平距离(半径) const dx = cameraWorldPos.x - targetWorldPos.x; const dz = cameraWorldPos.z - targetWorldPos.z; this.radius = Math.sqrt(dx * dx + dz * dz); // 计算起始角度(世界坐标系) this.currentAngle = Math.atan2(dx, dz) * 180 / Math.PI; // 计算高度差 this.heightOffset = cameraWorldPos.y - targetWorldPos.y; this.isInitialized = true; } private updateCameraPosition(keepAngle: boolean = false) { if (!this.isInitialized) return; const targetWorldPos = this.targetNode!.worldPosition.clone() .add(this.centerOffset); // 计算水平坐标 const angleRad = this.currentAngle * Math.PI / 180; const x = targetWorldPos.x + Math.sin(angleRad) * this.radius; const z = targetWorldPos.z + Math.cos(angleRad) * this.radius; // 设置摄像机世界坐标 this.node.worldPosition = new Vec3( x, targetWorldPos.y + this.heightOffset, z ); // 确保准确朝向目标中心点 this.node.lookAt(targetWorldPos); } // 触摸事件处理(保持不变) onEnable() { input.on(Input.EventType.TOUCH_START, this.onTouchStart, this); input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this); input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this); input.on(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this); } onDisable() { input.off(Input.EventType.TOUCH_START, this.onTouchStart, this); input.off(Input.EventType.TOUCH_MOVE, this.onTouchMove, this); input.off(Input.EventType.TOUCH_END, this.onTouchEnd, this); input.off(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this); } private onTouchStart(event: EventTouch) { this.isTouching = true; this.lastTouchX = event.getLocationX(); } private onTouchMove(event: EventTouch) { if (!this.isTouching) return; const currentTouchX = event.getLocationX(); const deltaX = currentTouchX - this.lastTouchX; // 更新角度 this.currentAngle -= deltaX * this.rotationSpeed; this.currentAngle = (this.currentAngle + 360) % 360; // 立即更新摄像机位置 this.updateCameraPosition(); this.lastTouchX = currentTouchX; } private onTouchEnd() { this.isTouching = false; } }