前文:https://blog.csdn.net/Jaihk662/article/details/87632727(摄像机跟随)
前面已经提到了摄像机跟随角色的多种方法以及优化,但是很多时候摄像机与玩家之间可能会存在一些实体物体,这样子玩家的视野就会被遮挡,还有就是在切换视角的时候,摄像机最好可以平滑移动,这些问题当然是要被解决的……
一、当摄像机被遮挡时,调整摄像机与玩家之间的距离
核心:使用射线
前提条件:障碍物(阻挡物)存在BoxCollider组件,或者存在空气墙,建议前者效果更好
一些重要的API:
- Physics.RaycastAll(当前目标,方向,射线长度):当前目标和方向都是Vector3向量,API返回一个数组RaycastHit[]
- Vector3.normalized:向量归一化
代码中有注释
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraCtro : MonoBehaviour
{
Vector3 dis;
RaycastHit[] hits;
private int type;
private float temp; //摄像机与人之间的距离参数
public float myUp;
public float myForward;
public float mySpeed;
private Transform playerTran, myTran;
void Start()
{
type = 1;
temp = 1;
playerTran = GameObject.Find("Player").transform;
myTran = this.GetComponent<Transform>();
LookPlayer(temp);
}
void FixedUpdate()
{
CameraAsix();
if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.Z)) //切换摄像机模式,自由模式:可以随时调节视角,但是人转向不会影响视角方向
type ^= 1; // 固定模式:视角方向始终朝向人正方向
if (Check(-1.7f) && temp > 0.3f) //通过判断摄像机看不看的到主角(是否被建筑遮挡),调整摄像机与人的距离
temp -= 0.017f;
else if (!Check(1.7f) && temp != 1) //这些参数根据实际情况要进行调整,调整好之后建议定死,不同游戏可能不一样,切记
temp += 0.017f;
LookPlayerInPlay(temp);
}
bool Check(float p) //摄像机与人之间是否存在碰撞体,用来判断视野是否被遮挡
{
Vector3 dir = -(playerTran.position - myTran.position).normalized; //向量归一化,也就是返回单位向量
hits = Physics.RaycastAll(playerTran.position, dir, Vector3.Distance(playerTran.position, myTran.position)+p); //+p放抖
if (hits.Length > 0 && hits[0].collider.name != "Player")
return true;
return false;
}
void CameraAsix()
{
float left, up, forward;
if (Input.GetMouseButton(1) && type==0) //通过获得鼠标横纵轴移位,来控制摄像头视角移动,z轴保持不变,只能在自由模式下编辑
{
up = Input.GetAxis("Mouse Y");
left = Input.GetAxis("Mouse X");
myTran.RotateAround(playerTran.position, playerTran.up, left * mySpeed);
if ((myTran.position.y >= 2.5 || up < 0) && (myTran.position.y <= 7.5 || up > 0))
myTran.RotateAround(playerTran.position, myTran.right, -up * mySpeed);
dis = myTran.position - playerTran.position;
}
forward = Camera.main.fieldOfView;
forward -= Input.GetAxis("Mouse ScrollWheel") * 8;
forward = Mathf.Clamp(forward, 10, 80);
Camera.main.fieldOfView = forward;
}
void LookPlayer(float p) //初始化
{
myTran.position = playerTran.position;
myTran.position += Vector3.up * myUp * p;
myTran.position += playerTran.forward * myForward * p;
myTran.LookAt(playerTran);
dis = myTran.position - playerTran.position;
}
void LookPlayerInPlay(float p)
{
if (type == 0) //两种摄像机跟随方式
{
myTran.position = playerTran.position + dis;
transform.LookAt(playerTran);
}
else
{
Vector3 temp;
temp = playerTran.position;
temp += Vector3.up * myUp * (p+(1-p)/2);
temp += playerTran.forward * myForward * p;
myTran.position = Vector3.Lerp(myTran.position, temp, 0.2f); //实现摄像机平滑移动,如果仍然出现摄像机抖动情况,可能是因为主角移动方式非刚体移动,解决方法为将该方法放入LastUpdate中
myTran.LookAt(playerTran);
dis = myTran.position - playerTran.position;
}
}
}
二、当摄像机被遮挡时,将遮挡物半透明化
……