用比较简易的方法制作可以绕物体旋转的且可以避开障碍的摄像机.

Unity 3D 简易制作摄像机围绕物体随鼠标旋转效果

梗概:

一. 摄像机围绕目标物体旋转, 即摄像机离目标物体有一定的距离且旋转轴心为该物体的位置.

 

二. 当目标物体被障碍物挡住后, 需要将摄像机移动到障碍物前方能看见目标物体的位置.

思路:

一. 摄像机绕轴心旋转, 可以在轴心处创建一个空物体, 将摄像机设为该轴心的子物体. 如图:

 

unity 监听屏幕旋转 unity怎么旋转摄像机_System

unity 监听屏幕旋转 unity怎么旋转摄像机_Time_02

unity 监听屏幕旋转 unity怎么旋转摄像机_System_03

unity 监听屏幕旋转 unity怎么旋转摄像机_赋值_04

这样便可以简单地实现摄像机旋转轴心 (注意: 旋转时应旋转轴心而不是单独旋转摄像机) . 还应注意, 如果摄像机的目标物体可以移动的话, 就应每帧将轴心的坐标设为目标物体的坐标 (尽量不要直接将轴心设为目标物体的子物体! 除非有特别需要) .

二. 当目标物体被障碍物挡住后, 可以在目标物体处发射一条射线, 射线原点就是目标物体的坐标 (也就是轴心) , 射线方向就是从原点到摄像机的方向. 此时射线的碰撞点就是将要把摄像机调整到的位置.

 

unity 监听屏幕旋转 unity怎么旋转摄像机_unity 监听屏幕旋转_05

unity 监听屏幕旋转 unity怎么旋转摄像机_System_06

三. 当将摄像机移动到后方没有障碍物的位置时, 就应将摄像机移回至原距离.

 

unity 监听屏幕旋转 unity怎么旋转摄像机_赋值_07

过程:

  1. 创建任意目标物体;
  2. 创建一个空物体并命名, 这个空物体就是轴心, 并将其 Tag 设为 "3rdCameraAxle":
  3. unity 监听屏幕旋转 unity怎么旋转摄像机_Time_08

  4. 或者将其 Tag 设为你喜欢的一个都可以;
  5. 创建摄像机, 将其 Tag 设为 "MainCamera", 并设为刚创建的轴心的子物体;
  6. 创建任意障碍物.

代码:

一. 此时绕物体旋转摄像机便可简化为直接旋转轴心, 代码也简化了许多:

  1. 定义鼠标灵敏度:
public float mouseSensitivity = 2;
  1. 定义目标物体的  Transform
public Transform targetTrans;
  1. 定义轴心  Transform
Transform thirdPCamAxle;
Vector3 thirdPCamEuler;

在  void

void Start () {
    thirdPCamAxle = GameObject.FindGameObjectWithTag("3rdCameraAxle").transform; //括号里的引号中也可以写上你自己对轴心设的 Tag.
    thirdPCamEuler = thirdPCamAxle.localEulerAngles; //推荐写 localEulerAngles, 要不之后处理起来会比较麻烦.
}
  1. 定义摄像机:
Camera thirdPCam;

在  void

void Start () {
    thirdPCam = Camera.main;
}
  1. 定义并赋值摄像机离物体的最大距离, 摄像机离物体的当前距离:
float camForwardMaxDistance = 9;
float camForwardDistance;
float camBackDistance;
  1. 在  void
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

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 }

最终效果图:

unity 监听屏幕旋转 unity怎么旋转摄像机_unity 监听屏幕旋转_09

希望本篇教程能够帮到大家!

源码: [GitHub](https://github.com/JadMax/Unity3D-Miscellaneous/blob/master/ThirdpersonCameraController.cs)