unity 中间摄像机的移动
现在很多情况下都会出现游戏摄像机跟随着人物移动,网上关于这个也是很多的,但是有时候只是和游戏人物简单的出现保持相对的距离,这样子运动起来会很干涩,动作不够连贯,给游戏玩家很不好的感觉。
如果遇到墙,和其他的物体对游戏主角进行遮挡,这个样子,就无法看到游戏玩家了。下面的方法巧妙的解决了这个问题。
代码实现
首先定义几个变量:
public float smooth = 1.5f;
private Transform player;
private Vector3 relCameraPos; //相对位置摄像机对人物
private float relCameraPosMag; //摄像机和人物的距离
private Vector3 newPos; //摄像机试着抵达的位置
对几个变量进行初始化:
void Awake()
{
player = GameObject.FindGameObjectWithTag(Tags.player).transform;
//摄像机相对位置 = 摄像机位置 - 玩家位置
relCameraPos = transform.position - player.position;
//实际向量长度-0.5 小一点
relCameraPosMag = relCameraPos.magnitude - 0.5f;
}
下面在fixedUpdate()里面是重点。
定义五个摄像机位置:Vector3[] checkPoints = new Vector3[5];
再把第一个位置设为摄像机初始的位置,把最后一个位置设为于游戏人物垂直上方的位置。
//摄像机的初始位置 = 玩家位置 + 相对位置
Vector3 standardPos = player.position + relCameraPos;
//摄像机的俯视位置 = 玩家位置 + 玩家正上方 * 相对位置向量长度
Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;
摄像头会慢慢位移,直到射线能过看到的地方。
checkPoints[4] = abovePos;
for (int i = 0;i<checkPoints.Length;i++)
{
if (ViewingPosCheck(checkPoints[i]))
{
break;
}
}
//使用光线投射的方法检测摄像机能否投射碰撞到玩家
bool ViewingPosCheck(Vector3 checkPos)
{
RaycastHit hit;
if (Physics.Raycast(checkPos,player.position-checkPos,out hit,relCameraPosMag))
{
if (hit.transform!=player)
{
return false;
}
}
newPos = checkPos;
return true;
}
下面的函数使摄像机在运动的过程中始终面对着游戏人物。
//使摄像机函数在移动过程中始终面对玩家
void SmoothLookAt()
{
Vector3 relPlayPosition = player.position - transform.position;
Quaternion lookAtRotation = Quaternion.LookRotation(relPlayPosition, Vector3.up);
transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
}
using UnityEngine;
using System.Collections;
public class CameraMovement : MonoBehaviour {
public float smooth = 1.5f;
private Transform player;
private Vector3 relCameraPos; //相对位置摄像机对人物
private float relCameraPosMag; //摄像机和人物的距离
private Vector3 newPos; //摄像机试着抵达的位置
void Awake()
{
player = GameObject.FindGameObjectWithTag(Tags.player).transform;
//摄像机相对位置 = 摄像机位置 - 玩家位置
relCameraPos = transform.position - player.position;
//实际向量长度-0.5 小一点
relCameraPosMag = relCameraPos.magnitude - 0.5f;
}
void FixedUpdate()
{
//摄像机的初始位置 = 玩家位置 + 相对位置
Vector3 standardPos = player.position + relCameraPos;
//摄像机的俯视位置 = 玩家位置 + 玩家正上方 * 相对位置向量长度
Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;
Vector3[] checkPoints = new Vector3[5];
checkPoints[0] = standardPos;
checkPoints[1] = Vector3.Lerp(standardPos, abovePos, 0.25f);
checkPoints[2] = Vector3.Lerp(standardPos, abovePos, 0.5f);
checkPoints[3] = Vector3.Lerp(standardPos, abovePos, 0.75f);
checkPoints[4] = abovePos;
for (int i = 0;i<checkPoints.Length;i++)
{
if (ViewingPosCheck(checkPoints[i]))
{
break;
}
}
transform.position = Vector3.Lerp(transform.position, newPos, smooth * Time.deltaTime);
SmoothLookAt();
}
//使用光线投射的方法检测摄像机能否投射碰撞到玩家
bool ViewingPosCheck(Vector3 checkPos)
{
RaycastHit hit;
if (Physics.Raycast(checkPos,player.position-checkPos,out hit,relCameraPosMag))
{
if (hit.transform!=player)
{
return false;
}
}
newPos = checkPos;
return true;
}
//使摄像机函数在移动过程中始终面对玩家
void SmoothLookAt()
{
Vector3 relPlayPosition = player.position - transform.position;
Quaternion lookAtRotation = Quaternion.LookRotation(relPlayPosition, Vector3.up);
transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
}
}