1,镜头跟随源码分析
LookAt模式关键源码;
public override void Update (Transform self, Transform target, Vector3 targetOffset)
{
// Position
if (enableMovement)
{
float stepSize = movementSpeed * Time.deltaTime;
m_position += GetInputForAxis(forwardAxis) * stepSize * new Vector3(self.forward.x, 0.0f, self.forward.z).normalized;
m_position += GetInputForAxis(sidewaysAxis) * stepSize * self.right;
m_position += GetInputForAxis(verticalAxis) * stepSize * self.up;
}
self.position = Vector3.Lerp(self.position, m_position, movementDamping * Time.deltaTime);
// Rotation
if (target != null)
{
Quaternion lookAtRotation = Quaternion.LookRotation(target.position + targetOffset - self.position);
self.rotation = Quaternion.Slerp(self.rotation, lookAtRotation, damping * Time.deltaTime);
}
// Zoom
if (m_camera != null)
{
m_fov -= GetInputForAxis(fovAxis) * fovSpeed;
m_fov = Mathf.Clamp(m_fov, minFov, maxFov);
m_camera.fieldOfView = Mathf.Lerp(m_camera.fieldOfView, m_fov, fovDamping * Time.deltaTime);
}
}
绿色标记代码表示先获取一个代表摄像机位置指向汽车位置的时的旋转,再将其插值计算后赋值给摄像机自身的rotation,
damping参数使摄像机存在缓冲效果,而并不是实时指向汽车。
Quaternion.LookRotation方法有两个Vector3类型的参数,第一个参数表示看向的方向,第二个参数起约束作用
默认为Vector3.up.
蓝色标记代码表示通过鼠标滚轮对摄像机的视野范围进行控制,同时也进行了插值计算。
SmoothFollow模式(平滑跟随);
以下为自定义Update方法内容
public override void Update (Transform self, Transform target, Vector3 targetOffset)
{
if (target == null) return;
//updatedVelocity为当前帧target的移动速度,m_smoothLastPos保存上一帧的target的移动速度;
Vector3 updatedVelocity = (target.position + targetOffset - m_smoothLastPos) / Time.deltaTime;
m_smoothLastPos = target.position + targetOffset;
updatedVelocity.y = 0.0f;//将y轴上的速度设为0,使得摄像机只会在水平面改变方向;
if (updatedVelocity.magnitude > 1.0f)
{
m_smoothVelocity = Vector3.Lerp(m_smoothVelocity, updatedVelocity, velocityDamping * Time.deltaTime);
m_smoothTargetAngle = Mathf.Atan2(m_smoothVelocity.x, m_smoothVelocity.z) * Mathf.Rad2Deg;
}
if (!followVelocity)
m_smoothTargetAngle = target.eulerAngles.y;
float wantedHeight = target.position.y + targetOffset.y + height;
m_selfRotationAngle = Mathf.LerpAngle(m_selfRotationAngle, m_smoothTargetAngle, rotationDamping * Time.deltaTime);
m_selfHeight = Mathf.Lerp(m_selfHeight, wantedHeight, heightDamping * Time.deltaTime);
Quaternion currentRotation = Quaternion.Euler (0, m_selfRotationAngle, 0);//创建一个插值计算后的旋转;
Vector3 selfPos = target.position + targetOffset;
selfPos -= currentRotation * Vector3.forward * distance;
selfPos.y = m_selfHeight;//通过向量运算得到本帧结束时摄像机的位置;
Vector3 lookAtTarget = target.position + targetOffset + Vector3.up * height * viewHeightRatio;//设置摄像机lookat对象的位置
if (m_vehicle != null && controller.cameraCollisions)
{
if (m_camera != null)
{//检测self位置和lookAtTarget位置之间是否存在其他物体
Vector3 origin = lookAtTarget;
Vector3 path = selfPos - lookAtTarget;
Vector3 direction = path.normalized;
float rayDistance = path.magnitude - m_camera.nearClipPlane;
float radius = m_camera.nearClipPlane * Mathf.Tan(m_camera.fieldOfView * Mathf.Deg2Rad * 0.5f) + 0.1f;
selfPos = origin + direction * m_vehicle.SphereRaycastOthers(origin, direction, radius, rayDistance, controller.collisionMask);
}
else
{
selfPos = m_vehicle.RaycastOthers(lookAtTarget, selfPos, controller.collisionMask);
}
}
self.position = selfPos;
self.LookAt(lookAtTarget);
}
}
原理: