在Unity3D中,先调整MainCamera在场景中的位置,然后把脚本挂到MainCamera上,摄像机跟随分为简单的摄像机跟随和高级摄像机跟随。
简单摄像机跟随:
public class CameraFollow:MonoBehaviour() { //设置摄像机跟随速度 private float moveSpeed = 3f;
//设置摄像机旋转速度
private float turnSpeed = 10f; //设置摄像机跟随的物体 private Transform target; //定义方向向量 private Vector3 dir; void Awake(){ //获取物体 target = GameObject.FindWithTag(Tags.Player).transform; } void Start(){ //获取方向向量 dir = transform.position - target.position; } void Update(){ //跟随目标 transform.position = Vector3.Lerp(transform.position, target.position+dir, moveSpeed * Time.deltaTime);
//摄像机旋转
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(dir), turnSpeed * Time.deltaTime); } }
在摄像机的简单跟随中,应用的场景中如果有一些障碍物,target在障碍物的后面会在游戏视图中看不到target,因此在大多数的场景中不适用。
高级摄像机跟随:在跟随的目标移动到障碍物后面的时候,调整摄像机的位置,达到看到目标的目的;原理:当target走到障碍物后面,用RaycastHit射线检测摄像机照到的物体是否是target,如果不是,设置档位,依次慢慢移动摄像机,直到照到target为止,所以可以在设定档位的时候,最后一个档位为target的正上方;当target移动到障碍物外面的时候,还原为以前的视角。
高级摄像机跟随代码如下:
public class Camera : MonoBehaviour{ //设置摄像机的移动速度 private float moveSpeed = 3f; //设置摄像机的旋转速度 private float turnSpeed = 10f; //摄像机跟随目标 private Transform target; //方向向量 private Vector3 dir; //设置档位 private int gears = 5; //射线碰撞检测器 privatr RaycastHit hit; void Awake(){ //照到摄像机跟随目标 target = GameObject.FindWithTag(Tags.Player).transform; } void Start(){ dir = transform.position - target.position; } void Update(){ //起始坐标 Vector3 beginPos = target.position + dir; //摄像机的投影向量 Vector3 projectDir = Vector3 Project(dir, Vector3.up); //计算头顶摄像机与target之间的距离 float distance = projectDir.mignitude; //target头顶坐标 Vector3 endPos = target.position + Vector3.up * distance; //所有档位 Vector3[] allPos = new Vector3[gears]; //起点 allPos[0] = beginPos; //终点 allPos[allPos.Length - 1] = endPos; //填充中间点 for(int i = 1; i < allPos.Length - 1; i++){ allPos[i] = Vector3.Lerp(beginPos, endPos, i/(gears - 1f)); } //默认结果点为起点 Vector3 resultPos = beginPos; //遍历所有点 for(int i=0; i < allPos.Length - 1; i++){ if(CanSeeTarget(allPos[i])){ resultPos = allPos[i]; break; } } //摄像机移动 transform.position = Vector3.Lerp(transform.position, resultPos + dir, moveSpeed * Time.deltaTime); //获取方向向量 Vector3 lookDir = target.position - resultPos; //摄像机旋转
transform.rotation=Quaternion.Lerp(transform.rotation,Quaternion.LookRotation(lookDir), turnSpeed * Time.deltaTime); //将欧拉角Y置零 transform.eulerAngles = new Vector3(transform.eulerAngles.x, 0, transform.eulerAngles.z); } //能否看到玩家 void CanSeeTarget(Vector3 pos){ //发射射线(起点,方向向量,射到的物体) if(Physics.Raycast( pos, target.position - pos ,out hit)){ //能否看到玩家 if(hit.collider.CompareTag(Tags.Player)){ return true; } } return false; } }