Unity人物摄像机跟随简单实现

使用了 Mathf.SmoothDamp() 函数,来实现摄像机的平滑过度。

转载请注明出处:https://www.cnblogs.com/jietian331/p/12626530.html

代码如下:

  1 using System;
  2 using UnityEngine;
  3 using UnityEngine.EventSystems;
  4 
  5 class PlayerCamera : MonoBehaviour
  6 {
  7     const float
  8         MouseSmoothingFactor = 0.1f,
  9         MaxDistance = 16,
 10         MinDistance = 1f,
 11         MinAngleY = -30f,
 12         MaxAngleY = 60f;
 13 
 14     [SerializeField]
 15     Transform m_target;
 16     [SerializeField]
 17     float m_distance;
 18     [SerializeField]
 19     float m_offsetY;
 20 
 21     Camera m_camera;
 22     float m_mouseX;
 23     float m_mouseY = 30;
 24     float m_mouseXSmooth;
 25     float m_mouseYSmooth;
 26 
 27 
 28     #region singleton
 29 
 30     static PlayerCamera s_instance;
 31     public static PlayerCamera Singleton
 32     {
 33         get
 34         {
 35             if (s_instance == null)
 36             {
 37                 var asset = Resources.Load<PlayerCamera>("Prefabs/Game/PlayerCamera");
 38                 s_instance = GameObject.Instantiate(asset);
 39             }
 40             return s_instance;
 41         }
 42     }
 43 
 44     #endregion
 45 
 46 
 47     #region Property
 48 
 49     float Distance
 50     {
 51         get { return m_distance; }
 52         set { m_distance = Mathf.Clamp(value, MinDistance, MaxDistance); }
 53     }
 54 
 55     public Camera Camera
 56     {
 57         get { return m_camera; }
 58     }
 59 
 60     public static bool ClickedUI
 61     {
 62         get { return GUIUtility.hotControl != 0 || (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject()); }
 63     }
 64 
 65     public bool Active
 66     {
 67         set { gameObject.SetActive(value); }
 68     }
 69 
 70     #endregion
 71 
 72 
 73     static float ClampAngle(float angle, float min, float max)
 74     {
 75         while (angle < -360 || angle > 360)
 76         {
 77             if (angle < -360)
 78                 angle += 360;
 79             if (angle > 360)
 80                 angle -= 360;
 81         }
 82 
 83         return Mathf.Clamp(angle, min, max);
 84     }
 85 
 86 
 87     void Start()
 88     {
 89         DontDestroyOnLoad(gameObject);
 90 
 91         // camera
 92         m_camera = GetComponent<Camera>();
 93 
 94         // setting
 95         Distance = GameConfig.Instance.CameraDefaltDistance;
 96     }
 97 
 98 
 99     public void SetTarget(Transform target, float height)
100     {
101         if (target == null)
102             throw new ArgumentNullException("target");
103 
104         m_target = target;
105         m_offsetY = height * 0.8f;
106     }
107 
108     Vector3 GetSmoothDir()
109     {
110         if (Input.GetKey(KeyCode.Mouse1))
111         {
112             float mouseXAxis = Input.GetAxis("Mouse X");
113             float mouseYAxis = Input.GetAxis("Mouse Y");
114             m_mouseX += mouseXAxis * 6;
115             m_mouseY -= mouseYAxis * 4;
116         }
117         else
118         {
119             bool left = Input.GetKey(KeyCode.Q);
120             bool right = Input.GetKey(KeyCode.E);
121             bool downward = Input.GetKey(KeyCode.Z);
122             bool upward = Input.GetKey(KeyCode.C);
123             bool reset = Input.GetKey(KeyCode.X);
124 
125             if (left || right)
126             {
127                 float eulerY = left ? -2 : 2;
128                 m_mouseX += eulerY;
129             }
130             else if (downward || upward)
131             {
132                 float offsetY = downward ? 2f : -2f;
133                 m_mouseY -= offsetY;
134             }
135             else if (reset)
136             {
137                 m_mouseX = 0;
138                 m_mouseY = 30;
139             }
140         }
141 
142         float currentVelX = 0, currentVelY = 0;
143         m_mouseXSmooth = Mathf.SmoothDamp(m_mouseXSmooth, m_mouseX, ref currentVelX, MouseSmoothingFactor);
144         m_mouseY = ClampAngle(m_mouseY, MinAngleY, MaxAngleY);
145         m_mouseYSmooth = Mathf.SmoothDamp(m_mouseYSmooth, m_mouseY, ref currentVelY, MouseSmoothingFactor);
146         m_mouseYSmooth = ClampAngle(m_mouseYSmooth, MinAngleY, MaxAngleY);
147 
148         // Distance
149         float scrollWheel = Input.GetAxis("Mouse ScrollWheel") * 3;
150         if (scrollWheel != 0)
151             Distance -= scrollWheel;
152 
153         Vector3 offset = new Vector3(0, 0, Distance);
154         Quaternion rotation = Quaternion.Euler(m_mouseYSmooth, m_mouseXSmooth, 0);
155         return rotation * offset;
156     }
157 
158     //  A follow camera should always be implemented in LateUpdate because it tracks objects that might have moved inside Update
159     void LateUpdate()
160     {
161         if (!m_target)
162             return;
163 
164         Vector3 dir = GetSmoothDir();
165         ResetCamera(dir);
166     }
167 
168     void ResetCamera(Vector3 forward)
169     {
170         Vector3 center = m_target.position + new Vector3(0, m_offsetY);
171 
172         // 摄像机不会被物体遮住,用射线检测
173         RaycastHit hit;
174         Ray ray = new Ray(center, -forward);
175         int groundMask = StaticLayers.Ground.GetLayerMask();
176         bool raycast = Physics.Raycast(ray, out hit, Distance, groundMask);
177         Vector3 pos;
178         if (raycast)
179             pos = hit.point + forward * 0.05f;
180         else
181             pos = center - forward;
182 
183         transform.position = pos;
184         transform.LookAt(center);
185     }
186 }

 

上一篇:利用Canvas实现网页页面预加载动画效果,风车类动画特效


下一篇:turtle库读书笔记