分享一个相机跟随组件

最近在做相机跟随功能,论坛里面没找到类似的,就基于babylon.js的flowCamera做了一个组件,正好之前也一直从论坛下载资源,就想着分享一下,也算是回报大家了
image
组件直接拖动进去就行,这个之前是3d的组件,我因为需要就把z轴固定了,大家如果做3d可以打开
image
里面还有一些参数,我因为没用到就没提出来,大家按需修改就行
image
下面是所有代码
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
      }
    }
1赞

马克马克克