先上代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
public float Distance = 20; //摄像机与目标距离
public float RotSpeedInHorizontal = 0.05f; //横向旋转速度
public float RotSpeedInVertical = 0.05f; //纵向旋转速度
public float ZoomSpeed = 0.2f; //距离变化速度
public float rot = 0; //横向角度
private float roll = 30f * 2 * Mathf.PI / 360; //纵向角度
private float minRoll = -10f * 2 * Mathf.PI / 360; //纵向角度范围
private float maxRoll= 70f * 2 * Mathf.PI / 360; //纵向角度范围
private float minDistance = 10f; //距离范围
private float maxDisrance = 50f;
private GameObject targetGO; //目标物体
void Start()
{
SetTarget(GameObject.Find("Tank"));
}
void LateUpdate()
{
if (targetGO != null && Camera.main != null)
{
RotateInHorizontal();
RotateInVertical();
Zoom();
FollowTarget(targetGO.transform);
}
}
private void SetTarget(GameObject target)
{
Transform cameraPoint = target.transform.Find("CameraPoint");
targetGO = cameraPoint != null ? cameraPoint.gameObject : target;
//if (cameraPoint != null)
//{
// targetGO = cameraPoint.gameObject;
//}
//else
//{
// targetGO = target;
//}
}
private void FollowTarget(Transform targetTrans)
{
Vector3 targetPos = targetTrans.position;
Vector3 cameraPos;
float d = Distance * Mathf.Cos(roll);
float height = Distance * Mathf.Sin(roll);
cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
cameraPos.y = targetPos.y + height;
Camera.main.transform.position = cameraPos;
Camera.main.transform.LookAt(targetTrans);
}
/// <summary>
/// 水平旋转。
/// </summary>
private void RotateInHorizontal()
{
float tmp = Input.GetAxis("Mouse X") * RotSpeedInHorizontal;
rot -= tmp;
}
/// <summary>
/// 竖直旋转。
/// </summary>
private void RotateInVertical()
{
float tmp = Input.GetAxis("Mouse Y") * RotSpeedInVertical * 0.5f;
roll -= tmp;
roll = Mathf.Clamp(roll, minRoll, maxRoll);
}
/// <summary>
/// 调节摄像机与目标之间的距离。
/// </summary>
private void Zoom()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
if (Distance > minDistance)
{
Distance -= ZoomSpeed;
}
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
if (Distance < maxDisrance)
{
Distance += ZoomSpeed;
}
}
}
}
设置跟随目标 SetTarget(GameObject target)
private void SetTarget(GameObject target)
{
Transform cameraPoint = target.transform.Find("CameraPoint");
targetGO = cameraPoint != null ? cameraPoint.gameObject : target;
//if (cameraPoint != null)
//{
// targetGO = cameraPoint.gameObject;
//}
//else
//{
// targetGO = target;
//}
}
因为目标物体的大小形状可能不同,有时候我们想让相机对准目标身上某个自定义的点,便可以在目标上添加一个子物体,命名为”CameraPoint”。
这个方法的作用就是查找目标是否存在”CameraPoint”,如果有就将”CameraPoint”设为目标点。如果没有,仍然使用默认目标点。
相机跟随目标 FollowTarget(Transform targetTrans)
private void FollowTarget(Transform targetTrans)
{
Vector3 targetPos = targetTrans.position;
Vector3 cameraPos;
float d = Distance * Mathf.Cos(roll);
float height = Distance * Mathf.Sin(roll);
cameraPos.x = targetPos.x + d * Mathf.Cos(rot);
cameraPos.z = targetPos.z + d * Mathf.Sin(rot);
cameraPos.y = targetPos.y + height;
Camera.main.transform.position = cameraPos;
Camera.main.transform.LookAt(targetTrans);
}
这一部分较为复杂,使用了三角函数的知识。
要想让相机跟随目标移动,就要明白在一定角度下相机与目标的位置关系,如图所示
(灵魂画手。。)
设相机与目标距离为distance,相机与xz平面角度为roll。根据三角函数即可求得distance映射在xz平面上的距离为distance*cos(roll),高度为distance*sin(roll)。
再如下图,设相机与目标在水平面上的距离为d(即distance映射在水平面的长度),相机旋转角度为rot,由图可知相机与目标的连线与x轴角度为rot-180。
根据三角函数,求得x轴位移为d*sin(rot),z轴位移为d*cos(rot)。所以,只要用目标坐标减去相对位移,便能求出相机坐标。
其他
1.相机跟随代码最好放入LateUpdate()中;
2.Mathf.Sin()和Mathf.Cos()使用弧度做单位,使用时将度数乘以[kbd]2*Mathf.Pi/360[/kbd]转化为弧度;
1 comment
😛