最近在做相机跟随功能,论坛里面没找到类似的,就基于babylon.js的flowCamera做了一个组件,正好之前也一直从论坛下载资源,就想着分享一下,也算是回报大家了

组件直接拖动进去就行,这个之前是3d的组件,我因为需要就把z轴固定了,大家如果做3d可以打开

里面还有一些参数,我因为没用到就没提出来,大家按需修改就行

下面是所有代码
import {
_decorator,
Camera,
Component,
Mat4,
misc,
Node,
Quat,
v3,
Vec3,
} from ‘cc’
const { ccclass, property } = _decorator
export const Epsilon = 0.001
@ccclass('FlowCamerra')
export class FlowCamerra extends Component {
@property(Node)
targetNode: Node | null = null
@property(Camera)
camera: Camera | any = null
// 定义相机与其跟随的对象之间的旋转偏移
rotationOffset: number = 0
//跟随相机应跟随物体的距离
radius: number = 15
/**
* 定义相机跟随物体的速度限制。
*/
public maxCameraSpeed: number = 20
/**
* 定义相机与其跟随的对象之间的高度偏移。
* 它可以帮助从顶部跟踪物体(例如汽车追逐飞机)
*/
public heightOffset: number = 4
/**
* 定义相机跟随目标的加速速度。
*/
public cameraAcceleration: number = 0.05
protected _upVector = Vec3.UP.clone()
_currentTarget: Vec3 = Vec3.ZERO
public _initialFocalDistance = 1
public _referencePoint = new Vec3(0, 0, 1)
start() {}
update(deltaTime: number) {
if (!this.targetNode) return
const rotMatrix = new Mat4()
Mat4.fromQuat(rotMatrix, this.targetNode.getWorldRotation())
const yRotation = Math.atan2(rotMatrix.m08, rotMatrix.m10)
const radians = misc.degreesToRadians(this.rotationOffset) + yRotation
const targetPosition = this.targetNode.getWorldPosition()
const targetX: number = targetPosition.x + Math.sin(radians) * this.radius
const targetZ: number = targetPosition.z + Math.cos(radians) * this.radius
const dx: number = targetX - this.camera.node.position.x
const dy: number =
targetPosition.y + this.heightOffset - this.camera.node.position.y
const dz: number = targetZ - this.camera.node.position.z
let vx: number = dx * this.cameraAcceleration * 2 //this is set to .05
let vy: number = dy * this.cameraAcceleration
let vz: number = dz * this.cameraAcceleration * 2
if (vx > this.maxCameraSpeed || vx < -this.maxCameraSpeed) {
vx = vx < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed
}
if (vy > this.maxCameraSpeed || vy < -this.maxCameraSpeed) {
vy = vy < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed
}
if (vz > this.maxCameraSpeed || vz < -this.maxCameraSpeed) {
vz = vz < 1 ? -this.maxCameraSpeed : this.maxCameraSpeed
}
let z = this.targetNode.position.z + vz
z = 1000
this.camera.node.position.set(
this.targetNode.position.x + vx,
this.targetNode.position.y + vy,
z
)
this.setTarget(targetPosition)
}
// Target
/**
* 定义相机应查看的目标。
* @param target 将新目标定义为 Vector
*/
public setTarget(target: Vec3): void {
this._upVector.normalize()
const rotation = this.camera.node.rotation
let rotationX = rotation.x
let rotationY = rotation.y
let rotationZ = rotation.z
this._initialFocalDistance = target
.subtract(this.camera.node.position)
.length()
if (this.camera.node.position.z === target.z) {
const pos = this.camera.node.position
let z = pos.z + Epsilon
this.camera.node.position.set(pos.x, pos.y, z)
}
this._referencePoint.normalize().multiplyScalar(this._initialFocalDistance)
Mat4.lookAt(
this.camera.node.getWorldMatrix(),
this.camera.node.position,
target,
Vec3.UP
)
this.camera.node.getWorldMatrix().invert()
let x = Math.atan(
this.camera.node.getWorldMatrix().m06 /
this.camera.node.getWorldMatrix().m10
)
const vDir = target.subtract(this.camera.node.position)
if (vDir.x >= 0.0) {
rotationY = -Math.atan(vDir.z / vDir.x) + Math.PI / 2.0
} else {
rotationX = -Math.atan(vDir.z / vDir.x) - Math.PI / 2.0
}
rotationZ = 0
if (isNaN(rotationX)) {
rotationX = 0
}
if (isNaN(rotationY)) {
rotationY = 0
}
if (isNaN(rotationZ)) {
rotationZ = 0
}
let quat = Quat.IDENTITY.clone()
this.camera.node.rotation = Quat.fromEuler(
quat,
rotationX,
rotationY,
rotationZ
)
}
/**
* 定义相机的目标点。
* 相机从半径距离看向它。
*/
public get target(): Vec3 {
return this.getTarget()
}
public set target(value: Vec3) {
this.setTarget(value)
}
/**
* 返回相机的当前目标位置。该值以局部空间表示。
* @返回目标位置
*/
public getTarget(): Vec3 {
return this._currentTarget
}
}