Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果
梗概:
一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置.
二. 当目标物体被障碍物挡住后, 需要将摄像机移动到障碍物前方能看见目标物体的位置.
思路:
一. 摄像机绕轴心旋转, 可以在轴心处创建一个空物体, 将摄像机设为该轴心的子物体. 如图:
这样便可以简单地实现摄像机旋转轴心 (注意: 旋转时应旋转轴心而不是单独旋转摄像机) . 还应注意, 如果摄像机的目标物体可以移动的话, 就应每帧将轴心的坐标设为目标物体的坐标 (尽量不要直接将轴心设为目标物体的子物体! 除非有特别需要) .
二. 当目标物体被障碍物挡住后, 可以在目标物体处发射一条射线, 射线原点就是目标物体的坐标 (也就是轴心) , 射线方向就是从原点到摄像机的方向. 此时射线的碰撞点就是将要把摄像机调整到的位置.
三. 当将摄像机移动到后方没有障碍物的位置时, 就应将摄像机移回至原距离.
过程:
-
创建任意目标物体;
-
创建一个空物体并命名, 这个空物体就是轴心, 并将其 Tag 设为 "3rdCameraAxle":
或者将其 Tag 设为你喜欢的一个都可以;
-
创建摄像机, 将其 Tag 设为 "MainCamera", 并设为刚创建的轴心的子物体;
-
创建任意障碍物.
代码:
一. 此时绕物体旋转摄像机便可简化为直接旋转轴心, 代码也简化了许多:
-
定义鼠标灵敏度:
public float mouseSensitivity = 2;
-
定义目标物体的 Transform :
public Transform targetTrans;
-
定义轴心 Transform 与轴心旋转角度:
Transform thirdPCamAxle; Vector3 thirdPCamEuler;
在 void Start() 下对其赋值:
void Start () { thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform; //括号里的引号中也可以写上你自己对轴心设的 Tag. thirdPCamEuler = thirdPCamAxle.localEulerAngles; //推荐写 localEulerAngles, 要不之后处理起来会比较麻烦. }
-
定义摄像机:
Camera thirdPCam;
在 void Start() 下对其赋值:
void Start () { thirdPCam = Camera.main; }
-
定义并赋值摄像机离物体的最大距离, 摄像机离物体的当前距离:
float camForwardMaxDistance = 9; float camForwardDistance; float camBackDistance;
-
在 void Update() 下写:
thirdPCamAxle.position = targetTrans.position; //将摄像机旋转轴心位置设为目标物体位置 //定义旋转量 float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; thirdPCamEuler.y += mouseX; //控制摄像机左右旋转 //控制摄像机上下旋转, 并且上下旋转范围不能超过90°或-90°, 此方法适用于 localEulerAngles. if (thirdPCamEuler.z < 90 && mouseY > 0) { thirdPCamEuler.z += mouseY; } if (thirdPCamEuler.z > -90 && mouseY < 0) { thirdPCamEuler.z += mouseY; } thirdPCamAxle.localEulerAngles = thirdPCamEuler; //将旋转量应用到摄像机上.
至此, 控制摄像机旋转完成. 此部分代码如下:
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class ThirdPCamC : MonoBehaviour { 6 public float mouseSensitivity = 2; 7 public Transform targetTrans; 8 9 Transform thirdPCamAxle; 10 Vector3 thirdPCamEuler; 11 12 Camera thirdPCam; 13 float camForwardMaxDistance = 9; 14 float camForwardDistance; 15 float camBackDistance; 16 17 void Start () { 18 thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform; 19 thirdPCamEuler = thirdPCamAxle.localEulerAngles; 20 21 thirdPCam = Camera.main; 22 } 23 24 void Update () { 25 thirdPCamAxle.position = targetTrans.position; 26 27 float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; 28 float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; 29 thirdPCamEuler.y += mouseX; 30 if (thirdPCamEuler.z < 90 && mouseY > 0) { thirdPCamEuler.z += mouseY; } 31 if (thirdPCamEuler.z > -90 && mouseY < 0) { thirdPCamEuler.z += mouseY; } 32 thirdPCamAxle.localEulerAngles = thirdPCamEuler; 33 } 34 }
二. 摄像机避开障碍物, 并在后方没有障碍物时移回原距离 (原距离可通过设置对 camForwardMaxDistance 的赋值来改变):
在 void Update() 下写:
Ray camForwardRay = new Ray(thirdPCam.transform.position, thirdPCam.transform.forward); //在摄像机处发射一条向前的射线, 用来检测摄像机当前离目标的距离 (此处不必担心射线碰撞处是障碍物的情况). RaycastHit forwardRayHit; //定义射线碰撞. if (Physics.Raycast(camForwardRay, out forwardRayHit)) //当射线有碰撞物时 (也就是目标物体), { camForwardDistance = Vector3.Distance(thirdPCam.transform.position, forwardRayHit.point); //计算从摄像机到碰撞点的距离 (碰撞点也可以改为目标物体的位置). } Vector3 dir = thirdPCam.transform.position - targetTrans.position; //定义从目标物体到摄像机的方向. dir = dir.normalized; //将方向单位化. Ray ray = new Ray(targetTrans.position, dir); //在目标物体处发射一条射线, 方向即为刚刚定义的向量. RaycastHit hit; //定义射线碰撞. if (Physics.Raycast(ray, out hit)) //当该射线有碰撞, 即目标物体被障碍物挡住时, { thirdPCam.transform.position = hit.point; //将摄像机位置设为碰撞点位置. } else //如果没有碰撞, 即目标物体没有被障碍物挡住, { if (camForwardDistance < camForwardMaxDistance) //并且当前距离没有超过最大距离时, { thirdPCam.transform.Translate(Vector3.back * Time.deltaTime * 5); //将摄像机缓慢后移至最大距离. } }
全部代码如下:
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class ThirdPCamC : MonoBehaviour { 6 public float mouseSensitivity = 2; 7 public Transform targetTrans; 8 9 Transform thirdPCamAxle; 10 Vector3 thirdPCamEuler; 11 12 Camera thirdPCam; 13 float camForwardMaxDistance = 9; 14 float camForwardDistance; 15 float camBackDistance; 16 17 void Start () { 18 thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform; 19 thirdPCamEuler = thirdPCamAxle.localEulerAngles; 20 21 thirdPCam = Camera.main; 22 } 23 24 void Update () { 25 thirdPCamAxle.position = targetTrans.position; 26 27 float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; 28 float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; 29 thirdPCamEuler.y += mouseX; 30 if (thirdPCamEuler.z < 90 && mouseY > 0) { thirdPCamEuler.z += mouseY; } 31 if (thirdPCamEuler.z > -90 && mouseY < 0) { thirdPCamEuler.z += mouseY; } 32 thirdPCamAxle.localEulerAngles = thirdPCamEuler; 33 34 Ray camForwardRay = new Ray(thirdPCam.transform.position, thirdPCam.transform.forward); 35 RaycastHit forwardRayHit; 36 if (Physics.Raycast(camForwardRay, out forwardRayHit)) 37 { 38 camForwardDistance = Vector3.Distance(thirdPCam.transform.position, forwardRayHit.point); 39 } 40 41 Vector3 dir = thirdPCam.transform.position - targetTrans.position;; 42 dir = dir.normalized; 43 Ray ray = new Ray(targetTrans.position, dir); 44 RaycastHit hit; 45 if (Physics.Raycast(ray, out hit)) 46 { 47 Debug.DrawLine(ray.origin, hit.point, Color.green); 48 thirdPCam.transform.position = hit.point; 49 } 50 else 51 { 52 if (camForwardDistance < camForwardMaxDistance) 53 { 54 thirdPCam.transform.Translate(Vector3.back * Time.deltaTime * 5); 55 } 56 } 57 } 58 }
最终效果图:
希望本篇教程能够帮到大家!
源码: [GitHub](https://github.com/JadMax/Unity3D-Miscellaneous/blob/master/ThirdpersonCameraController.cs)