138 lines
3.8 KiB
TypeScript
138 lines
3.8 KiB
TypeScript
import { Camera, Component, Node, Vec3, _decorator } from 'cc';
|
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
/**
|
|
* CameraController 摄像机控制器
|
|
* 负责让摄像机跟随指定的目标物体
|
|
*/
|
|
@ccclass('CameraController')
|
|
export class CameraController extends Component {
|
|
/** 跟随目标 */
|
|
private target: Node = null;
|
|
|
|
/** 摄像机节点 */
|
|
private cameraNode: Node = null;
|
|
|
|
/** 摄像机组件 */
|
|
private camera: Camera = null;
|
|
|
|
/** 相对偏移量 */
|
|
private offset: Vec3 = new Vec3(0, 10, 8);
|
|
|
|
/** 跟随速度 */
|
|
@property({ displayName: '跟随速度' })
|
|
public followSpeed: number = 5;
|
|
|
|
/** 是否平滑跟随 */
|
|
@property({ displayName: '平滑跟随' })
|
|
public smoothFollow: boolean = true;
|
|
|
|
onLoad() {
|
|
this.findMainCamera();
|
|
}
|
|
|
|
/**
|
|
* 查找主摄像机
|
|
*/
|
|
private findMainCamera(): void {
|
|
// 查找名为 "Main Camera" 的摄像机
|
|
const mainCameraNode = this.node.scene.getChildByName('Main Camera');
|
|
if (mainCameraNode) {
|
|
this.cameraNode = mainCameraNode;
|
|
this.camera = mainCameraNode.getComponent(Camera);
|
|
console.log('[CameraController] 找到主摄像机:', mainCameraNode.name);
|
|
} else {
|
|
console.error('[CameraController] 未找到主摄像机(Main Camera)');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 设置跟随目标
|
|
* @param target 跟随的目标节点
|
|
*/
|
|
public setTarget(target: Node): void {
|
|
this.target = target;
|
|
|
|
if (this.target && this.cameraNode) {
|
|
// 立即设置初始位置
|
|
this.updateCameraPosition(false);
|
|
console.log('[CameraController] 设置跟随目标:', target.name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 设置摄像机偏移量
|
|
* @param offset 相对于目标的偏移量
|
|
*/
|
|
public setOffset(offset: Vec3): void {
|
|
this.offset.set(offset);
|
|
}
|
|
|
|
/**
|
|
* 获取当前跟随目标
|
|
*/
|
|
public getTarget(): Node {
|
|
return this.target;
|
|
}
|
|
|
|
/**
|
|
* 获取摄像机节点
|
|
*/
|
|
public getCameraNode(): Node {
|
|
return this.cameraNode;
|
|
}
|
|
|
|
update(deltaTime: number) {
|
|
if (this.target && this.cameraNode) {
|
|
this.updateCameraPosition(this.smoothFollow, deltaTime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新摄像机位置
|
|
* @param smooth 是否使用平滑跟随
|
|
* @param deltaTime 帧时间(smooth为true时需要)
|
|
*/
|
|
private updateCameraPosition(smooth: boolean = true, deltaTime: number = 0): void {
|
|
if (!this.target || !this.cameraNode) {
|
|
return;
|
|
}
|
|
|
|
// 计算目标位置
|
|
const targetPosition = new Vec3();
|
|
Vec3.add(targetPosition, this.target.worldPosition, this.offset);
|
|
|
|
if (smooth && deltaTime > 0) {
|
|
// 平滑跟随
|
|
const currentPosition = this.cameraNode.worldPosition;
|
|
const newPosition = new Vec3();
|
|
Vec3.lerp(newPosition, currentPosition, targetPosition, this.followSpeed * deltaTime);
|
|
this.cameraNode.setWorldPosition(newPosition);
|
|
} else {
|
|
// 立即跟随
|
|
this.cameraNode.setWorldPosition(targetPosition);
|
|
}
|
|
|
|
// 让摄像机看向目标
|
|
this.cameraNode.lookAt(this.target.worldPosition);
|
|
}
|
|
|
|
/**
|
|
* 停止跟随
|
|
*/
|
|
public stopFollow(): void {
|
|
this.target = null;
|
|
console.log('[CameraController] 停止跟随');
|
|
}
|
|
|
|
/**
|
|
* 销毁控制器
|
|
*/
|
|
onDestroy(): void {
|
|
this.target = null;
|
|
this.cameraNode = null;
|
|
this.camera = null;
|
|
console.log('[CameraController] 摄像机控制器已销毁');
|
|
}
|
|
} |