Unity 相机跟随人物的几种方式 |
您所在的位置:网站首页 › unity如何移动相机 › Unity 相机跟随人物的几种方式 |
相机跟随一般写在生命周期LateUpdate中 1、最简单,无代码,固定距离,固定视角 最简单的就是 直接 把主相机作为Player角色的子物体,并自行固定好相机的位置和角度 优点:使用方便 缺点:使用不灵活,相机转动死板,体验不好,相机瞬间移动位置 2、代码控制,固定距离,固定视角,对1进行改进 设置一个空的GameObject,并且与Player的旋转和位置保持一致,然后将 主相机 设置成该GameObject的子对象。这种做法和方案 1 相似。 using UnityEngine; /// /// 创建一个空物体, /// 此空物体的位置信息始终与主角的位置信息保持一致, /// 主相机或主角相机给此空物体当子物体 /// 当主角死亡时,空物体的位置信息更新为上一帧主角的位置信息 /// public class CameraTest : MonoBehaviour{ public Transform player; Vector3 tempPostion; Quaternion tempRotation; void Update(){ if (player){ transform.position = player.position; transform.rotation = player.rotation; } else{ transform.position = tempPostion; transform.rotation = tempRotation; } tempPostion = player.position; tempRotation = player.rotation; } }(这种做法好处在于 当模拟角色死亡倒地的时候不会获取不到人物信息,如果采用方案 1 ,只能是重新创建一个相机,因为角色倒地的时候,子物体相机也会视角倒地,所以效率肯定方案 2 高) 优点:使用方便,适合大部分游戏模式 缺点:使用不灵活,相机转动死板(强制位移),体验不好 3、代码控制,固定距离,固定视角,直接移动,不会旋转 使用代码获取到一个相机的初始位置与人物之间的差值向量,在给相机赋值时再用这个差值向量与人物坐标求出相机的实时位置 using UnityEngine; public class CameraTest2 : MonoBehaviour{ public Transform player; Vector3 distance; void Start(){ distance = transform.position - player.position; } void LateUpdate(){ transform.position = player.position + distance; } }优点:简单,方便, 缺点:无法一直跟随角色身后,适合固定视角游戏 4、代码控制,固定距离,固定视角,插值移动(因为Update和LateUpdate刷新率不同,会有抖动现象) using UnityEngine; public class CameraTest2 : MonoBehaviour{ public Transform player; Vector3 distance; public float speed; void Start(){ distance = transform.position - player.position; } void LateUpdate(){ transform.position = Vector3.Lerp(transform.position, player.position + distance, Time.deltaTime * speed); } }不建议使用 5、代码控制,固定距离,固定视角,平滑阻尼移动 using UnityEngine; public class CameraTest2 : MonoBehaviour{ public Transform player; Vector3 distance; public float speed; Vector3 ve; void Start(){ distance = transform.position - player.position; } void LateUpdate(){ transform.position = Vector3.SmoothDamp(transform.position, player.position + distance, ref ve, 0); } }代码实现相机跟随物体,可使用一个接口函数Vector3.SmoothDamp() 平滑阻尼 。 函数介绍:随着时间的推移,逐渐改变一个向量朝向预期的目标(有点类似受阻力减速运动) 在官方的手册里也有推荐用此函数 来实现 平滑的相机跟随 public static Vector3 SmoothDamp( Vector3 current, //当前物体位置 Vector3 target, //目标位置 ref Vector3 currentVelocity, //当前速度,这个值由你每次调用这个函数时被修改 //虽然使用ref关键字,不过函数运行时会自动修改 //一般传入参数值为0 float smoothTime, //到达目标的大约时间,较小的值将快速到达目标 float maxSpeed = Mathf.Infinity,//选择允许你限制的最大速度(默认为正无穷) float deltaTime = Time.deltaTime//自上次调用这个函数的时间(默认为Time.deltaTime) ); 6、代码控制,固定距离,跟随主角视角,平滑阻尼移动,看向主角 要使相机始终跟随主角身后,就要始终更新相机的位置在主角的Y轴后面,于是手动设置设置相机相对于主角的距离 using UnityEngine; public class CameraTest2 : MonoBehaviour{ public Transform player; //角色位置信息 Vector3 off; //相机目标点位置信息 Vector3 ve; //平滑阻尼的返回值 Quaternion angel; //相机看向目标的旋转值 public float hight; //相机的高度 public float foward; //相机在角色后的距离 void LateUpdate(){ off = player.position + hight * player.up - foward * player.forward; transform.position = Vector3.SmoothDamp(transform.position, off, ref ve, 0); transform.LookAt(player.position); } }这样的注视,相机移动还是太快 7、代码控制,固定距离,平滑的旋转相机,平滑阻尼移动,看向主角 using UnityEngine; public class CameraTest2 : MonoBehaviour{ public Transform player; //角色位置信息 Vector3 off; //相机目标点位置信息 public float speed; //相机移动速度 Vector3 ve; //平滑阻尼的返回值 Quaternion angel; //相机看向目标的旋转值 public float hight; //相机的高度 public float foward; //相机在角色后的距离 void LateUpdate(){ off = player.position + hight * player.up - foward * player.forward; transform.position = Vector3.SmoothDamp(transform.position, off, ref ve, 0); //看向向量指向的方向 angel = Quaternion.LookRotation(player.position - off); transform.rotation = Quaternion.Slerp(transform.rotation, angel, Time.deltaTime * speed); } }8、代码控制,固定距离,平滑的旋转相机,平滑阻尼移动,看向主角,有物体遮挡(方法一) using UnityEngine; /// /// 相机进行射线检测,如果检测不到主角, /// 就在起始点与结束点(主角头顶的一个点)之间寻找几个点, /// 直到找到可以看到主角的点 /// public class CameraTest2 : MonoBehaviour { public Transform player; //角色位置信息 Vector3[] v3; //相机自动找寻的位置点 public int num; //相机临时点的个数 public Vector3 start; //相机开始时的位置 public Vector3 end; //相机没有找到主角时的位置 Vector3 tagetPostion; //相机看向的目标点 Vector3 ve3; //平滑阻尼的ref参数 Quaternion angel; //相机看向目标的旋转值 public float speed; //相机移动速度 void Start() { //外界赋值数组长度 v3 = new Vector3[num]; } void LateUpdate() { //记录相机初始位置 start = player.position + player.up * 2.0f - player.forward * 3.0f; //记录相机最终位置 end = player.position + player.up * 5.0f; //相机目标位置,开始等于初始位置 tagetPostion = start; v3[0] = start; v3[num - 1] = end; //动态获取相机的几个点 for (int i = 1; i < num; i++) { v3[i] = Vector3.Lerp(start, end, i / num); } //判断相机在那个点可以看到主角 for (int i = 0; i < num; i++) { if (Function(v3[i])) { tagetPostion = v3[i]; break; } if (i == num - 1) { tagetPostion = end; } } //主角的移动和看向 transform.position = Vector3.SmoothDamp(transform.position, tagetPostion, ref ve3, 0); angel = Quaternion.LookRotation(player.position - tagetPostion); transform.rotation = Quaternion.Slerp(transform.rotation, angel, speed); } /// /// 射线检测,相机是否能照到主角 /// /// 计算射线发射的方向 /// 是否检测到 bool Function(Vector3 v3) { RaycastHit hit; if (Physics.Raycast(v3, player.position - v3, out hit)) { if (hit.collider.tag == "Player") { return true; } } return false; } }9、代码控制,固定距离,平滑的旋转相机,平滑阻尼移动,看向主角,有物体遮挡(方法二) using UnityEngine; /// /// 从主角发射射线检测相机的位置 /// 检测不到,就把相机移动到,射线的碰撞点的前面 /// public class CameraTest2 : MonoBehaviour { public Transform player; //角色头部(设置空物体)位置信息 private Vector3 tagetPostion; //相机看向的目标点 private Vector3 ve3; //平滑阻尼的ref参数 Quaternion angel; //相机看向目标的旋转值 public float speed; //相机移动速度 public float upFloat; //Y轴上升距离 public float backFloat; //Z轴与主角的距离 void LateUpdate() { //记录相机初始位置 tagetPostion = player.position + player.up * upFloat - player.forward * backFloat; [size=12.6667px]//刷新相机目标点的坐标 tagetPostion = Function(tagetPostion); //主角的移动和看向 transform.position = Vector3.SmoothDamp(transform.position, tagetPostion, ref ve3, 0); angel = Quaternion.LookRotation(player.position - tagetPostion); transform.rotation = Quaternion.Slerp(transform.rotation, angel, speed); } /// /// 射线检测,主角向后检测是否有相机跟随 /// /// 用来计算射线发射的方向 /// 是否检测到 Vector3 Function(Vector3 v3) { RaycastHit hit; if (Physics.Raycast(player.position, v3 - player.position, out hit, 5.0f)) { if (hit.collider.tag != "MainCamera") { v3 = hit.point + transform.forward * 0.5f; } } return v3; } }10、代码控制,固定距离,平滑的旋转相机,平滑阻尼移动,看向主角,有物体遮挡,结合手游中相机的旋转和复位 using UnityEngine; /// /// 相机进行射线检测,如果检测不到主角, /// 就在起始点与结束点之间寻找几个点, /// 直到找到可以看到主角的点 /// 在游戏中玩家可以用鼠标控制相机的旋转 /// public class CameraTest2 : MonoBehaviour { public Transform player; //角色位置信息 Vector3[] v3; //相机自动找寻的位置点 public int num; //相机临时点的个数 public Vector3 start; //相机开始时的位置 public Vector3 end; //相机没有找到主角时的位置 Vector3 tagetPostion; //相机看向的目标点 Vector3 ve3; //平滑阻尼的ref参数 Quaternion angel; //相机看向目标的旋转值 public float speed; //相机移动速度 void Start() { //外界赋值数组长度 v3 = new Vector3[num]; } void LateUpdate() { //记录相机初始位置 start = player.position + player.up * 2.0f - player.forward * 3.0f; //记录相机最终位置 end = player.position + player.up * 5.0f; //鼠标控制相机的旋转 if (Input.GetMouseButton(1)) { //记录相机的初始位置和旋转角度 Vector3 pos = transform.position; Vector3 rot = transform.eulerAngles; //让相机绕着指定轴向旋转 transform.RotateAround(transform.position, Vector3.up, Input.GetAxis("Mouse X") * 10); transform.RotateAround(transform.position, Vector3.left, -Input.GetAxis("Mouse Y") * 10); //限制相机的绕X旋转的角度 if (transform.eulerAngles.x < -60 || transform.eulerAngles.x > 60) { transform.position = pos; transform.eulerAngles = rot; } return; } //相机目标位置,开始等于初始位置 tagetPostion = start; v3[0] = start; v3[num - 1] = end; //动态获取相机的几个点 for (int i = 1; i < num; i++) { v3[i] = Vector3.Lerp(start, end, i / num); } //判断相机在那个点可以看到主角 for (int i = 0; i < num; i++) { if (Function(v3[i])) { tagetPostion = v3[i]; break; } if (i == num - 1) { tagetPostion = end; } } //主角的移动和看向 transform.position = Vector3.SmoothDamp(transform.position, tagetPostion, ref ve3, 0); angel = Quaternion.LookRotation(player.position - tagetPostion); transform.rotation = Quaternion.Slerp(transform.rotation, angel, speed); } /// /// 射线检测,相机是否能照到主角 /// /// 计算射线发射的方向 /// 是否检测到 bool Function(Vector3 v3) { RaycastHit hit; if (Physics.Raycast(v3, player.position - v3, out hit)) { if (hit.collider.tag == "Player") { return true; } } return false; } } |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |