特点:
可自定义设置:相机与被跟随目标的距离,移动到目标位置的速度,与目标位置的偏移角度。切换跟踪目标。
using UnityEngine;
using System.Collections.Generic;
namespace Ceto
{
public class CameraFlowTarget : MonoBehaviour
{
struct Position
{
public Vector3 forwardAmount;
public float turnAmount;
public Vector3 camRotation;
public float camDistance;
}
public List<GameObject> obj = new List<GameObject>();
public bool disableInterpolation;
public GameObject m_ship;
public Vector3 m_forward = new Vector3(0, 0, 1);
public float m_shipMoveSpeed = 20.0f;
[Range(0.01f, 1.0f)]
public float shipSmoothness = 0.5f;
public float m_camRotationSpeed = 10.0f;
public float m_camStartRotationX = 10.0f;
public float m_camStartRotationY = 60.0f;
public float m_camStartRotationZ = 60.0f;
//跟目标点保持的距离
public float m_camStartDistance = 200.0f;
[Range(0.01f, 1.0f)]
public float camSmoothness = 0.5f;
Position m_position, m_target;
const float MAX_ACCELERATION = 1.0f;
const float ACCELERATION_RATE = 1.0f;
const float DECELERATION_RATE = 0.25f;
float m_acceleration = 0.0f;
public GameObject target;
Vector3 m_previousPos, m_velocity;
public GameObject m_dummy;
GameObject Ship
{
get
{
if (m_ship == null)
{
m_dummy = new GameObject();
m_ship = m_dummy;
}
return m_ship;
}
set
{
m_ship = value;
}
}
void Start()
{
TheForward();
}
void TheForward()
{
m_position.camRotation.x = m_camStartRotationX;
m_position.camRotation.y = m_camStartRotationY;
m_position.camRotation.z = m_camStartRotationZ;
m_position.camDistance = m_camStartDistance;
m_position.forwardAmount = Vector3.zero;
m_target = m_position;
}
void LateUpdate()
{
//if (是否可通过拖拽鼠标控制视角变化)
//{
ProcessInput();
//}
InterpolateToTarget();
//if (不是第一人称视角)
//{
MoveShip();
//}
CameraChange();
//**实时测试相机与目标点的距离,角度偏移等**
//TheForward();
}
void MoveShip()
{
Vector3 eulerAngles = Ship.transform.eulerAngles;
eulerAngles.y += m_position.turnAmount;
Ship.transform.eulerAngles = eulerAngles;
float ct = Mathf.Cos(m_position.camRotation.y * Mathf.Deg2Rad);
float st = Mathf.Sin(m_position.camRotation.y * Mathf.Deg2Rad);
float cp = Mathf.Cos(m_position.camRotation.x * Mathf.Deg2Rad);
float sp = Mathf.Sin(m_position.camRotation.x * Mathf.Deg2Rad);
Vector3 lookAt = Ship.transform.position;
Vector3 pos = lookAt + (new Vector3(sp * st, ct, cp * st)) * m_position.camDistance;
transform.position = pos;
transform.LookAt(lookAt);
m_velocity = Ship.transform.position - m_previousPos;
m_previousPos = Ship.transform.position;
}
void InterpolateToTarget()
{
if (disableInterpolation || Time.timeScale == 0.0f)
{
m_position = m_target;
return;
}
float smoothness;
smoothness = 1.0f / Mathf.Clamp(camSmoothness, 0.01f, 1.0f);
float camLerp = Mathf.Clamp01(Time.deltaTime * smoothness);
m_position.camDistance = Mathf.Lerp(m_position.camDistance, m_target.camDistance, camLerp);
m_position.camRotation = Vector2.Lerp(m_position.camRotation, m_target.camRotation, camLerp);
//smoothness = 1.0f / Mathf.Clamp(shipSmoothness, 0.01f, 1.0f);
//float shipLerp = Mathf.Clamp01(Time.deltaTime * smoothness);
//m_position.forwardAmount = Vector3.Lerp(m_position.forwardAmount, m_target.forwardAmount, shipLerp);
//m_position.turnAmount = Mathf.Lerp(m_position.turnAmount, m_target.turnAmount, shipLerp);
}
void ProcessInput()
{
float speed = m_shipMoveSpeed;
float velocity = m_velocity.magnitude;
m_target.forwardAmount = Vector3.zero;
m_target.turnAmount = 0.0f;
m_acceleration = Mathf.Clamp(m_acceleration, 0.0f, MAX_ACCELERATION);
float dt = Time.deltaTime * 2000.0f;
float amount = Mathf.Pow(1.02f, Mathf.Min(dt, 1.0f));
if (Input.GetAxis("Mouse ScrollWheel") < 0.0f)
{
m_target.camDistance *= amount;
}
else if (Input.GetAxis("Mouse ScrollWheel") > 0.0f)
{
m_target.camDistance /= amount;
}
m_target.camDistance = Mathf.Max(1.0f, m_target.camDistance);
//相机旋转角度范围设置
m_target.camRotation.y = Mathf.Clamp(m_target.camRotation.y, 20.0f, 140.0f);
if (Input.GetMouseButton(0))
{
m_target.camRotation.y += Input.GetAxis("Mouse Y") * m_camRotationSpeed;
m_target.camRotation.x += Input.GetAxis("Mouse X") * m_camRotationSpeed;
}
}
public void CameraChange()
{
if (Input.GetKey("1"))
{
m_ship = obj[0];
}
if (Input.GetKey("2"))
{
m_ship = obj[1];
}
}
//视角切换 (镜头缓慢移动)
public void SwitchtoF16(int i, float camDis, float camrot)
{
m_ship = obj[i];
m_target.camDistance = camDis;
m_target.camRotation.x = camrot;
}
/// <summary>
/// 视角切换(镜头快速切换)
/// </summary>
/// <param name="i">被跟随物体的序号</param>
/// <param name="camDis">相机与被跟随物体的距离</param>
/// <param name="camrx">相机与被跟随物体的夹角</param>
/// <param name="camry">相机与被跟随物体高度差</param>
public void SwitchtoMainview(int i, float camDis, float camrx, float camry)
{
m_ship = obj[i];
m_target.camDistance = camDis;
m_target.camRotation.x = camrx;
m_target.camRotation.y = camry;
m_position.camDistance = Mathf.Lerp(m_position.camDistance, m_target.camDistance, 1);
m_position.camRotation = Vector2.Lerp(m_position.camRotation, m_target.camRotation, 1);
}
void OnDestroy()
{
if (m_dummy != null)
DestroyImmediate(m_dummy);
}
}
}