- AutoCam.cs
- Scripts /
- Cameras /
- Standard Assets /
- Assets /
- project /
1 using System;
2 using UnityEngine;
3 #if UNITY_EDITOR
4
5 #endif
6
7 namespace UnityStandardAssets.Cameras
8 {
9 [ExecuteInEditMode]
10 public class AutoCam : PivotBasedCameraRig
11 {
12 [SerializeField] private float m_MoveSpeed = 3; // How fast the rig will move to keep up with target's position
13 [SerializeField] private float m_TurnSpeed = 1; // How fast the rig will turn to keep up with target's rotation
14 [SerializeField] private float m_RollSpeed = 0.2f;// How fast the rig will roll (around Z axis) to match target's roll.
15 [SerializeField] private bool m_FollowVelocity = false;// Whether the rig will rotate in the direction of the target's velocity.
16 [SerializeField] private bool m_FollowTilt = true; // Whether the rig will tilt (around X axis) with the target.
17 [SerializeField] private float m_SpinTurnLimit = 90;// The threshold beyond which the camera stops following the target's rotation. (used in situations where a car spins out, for example)
18 [SerializeField] private float m_TargetVelocityLowerLimit = 4f;// the minimum velocity above which the camera turns towards the object's velocity. Below this we use the object's forward direction.
19 [SerializeField] private float m_SmoothTurnTime = 0.2f; // the smoothing for the camera's rotation
20
21 private float m_LastFlatAngle; // The relative angle of the target and the rig from the previous frame.
22 private float m_CurrentTurnAmount; // How much to turn the camera
23 private float m_TurnSpeedVelocityChange; // The change in the turn speed velocity
24 private Vector3 m_RollUp = Vector3.up;// The roll of the camera around the z axis ( generally this will always just be up )
25
26
27 protected override void FollowTarget(float deltaTime)
28 {
29 // if no target, or no time passed then we quit early, as there is nothing to do
30 if (!(deltaTime > 0) || m_Target == null)
31 {
32 return;
33 }
34
35 // initialise some vars, we'll be modifying these in a moment
36 var targetForward = m_Target.forward;
37 var targetUp = m_Target.up;
38
39 if (m_FollowVelocity && Application.isPlaying)
40 {
41 // in follow velocity mode, the camera's rotation is aligned towards the object's velocity direction
42 // but only if the object is traveling faster than a given threshold.
43
44 if (targetRigidbody.velocity.magnitude > m_TargetVelocityLowerLimit)
45 {
46 // velocity is high enough, so we'll use the target's velocty
47 targetForward = targetRigidbody.velocity.normalized;
48 targetUp = Vector3.up;
49 }
50 else
51 {
52 targetUp = Vector3.up;
53 }
54 m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, 1, ref m_TurnSpeedVelocityChange, m_SmoothTurnTime);
55 }
56 else
57 {
58 // we're in 'follow rotation' mode, where the camera rig's rotation follows the object's rotation.
59
60 // This section allows the camera to stop following the target's rotation when the target is spinning too fast.
61 // eg when a car has been knocked into a spin. The camera will resume following the rotation
62 // of the target when the target's angular velocity slows below the threshold.
63 var currentFlatAngle = Mathf.Atan2(targetForward.x, targetForward.z)*Mathf.Rad2Deg;
64 if (m_SpinTurnLimit > 0)
65 {
66 var targetSpinSpeed = Mathf.Abs(Mathf.DeltaAngle(m_LastFlatAngle, currentFlatAngle))/deltaTime;
67 var desiredTurnAmount = Mathf.InverseLerp(m_SpinTurnLimit, m_SpinTurnLimit*0.75f, targetSpinSpeed);
68 var turnReactSpeed = (m_CurrentTurnAmount > desiredTurnAmount ? .1f : 1f);
69 if (Application.isPlaying)
70 {
71 m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, desiredTurnAmount,
72 ref m_TurnSpeedVelocityChange, turnReactSpeed);
73 }
74 else
75 {
76 // for editor mode, smoothdamp won't work because it uses deltaTime internally
77 m_CurrentTurnAmount = desiredTurnAmount;
78 }
79 }
80 else
81 {
82 m_CurrentTurnAmount = 1;
83 }
84 m_LastFlatAngle = currentFlatAngle;
85 }
86
87 // camera position moves towards target position:
88 transform.position = Vector3.Lerp(transform.position, m_Target.position, deltaTime*m_MoveSpeed);
89
90 // camera's rotation is split into two parts, which can have independend speed settings:
91 // rotating towards the target's forward direction (which encompasses its 'yaw' and 'pitch')
92 if (!m_FollowTilt)
93 {
94 targetForward.y = 0;
95 if (targetForward.sqrMagnitude < float.Epsilon)
96 {
97 targetForward = transform.forward;
98 }
99 }
100 var rollRotation = Quaternion.LookRotation(targetForward, m_RollUp);
101
102 // and aligning with the target object's up direction (i.e. its 'roll')
103 m_RollUp = m_RollSpeed > 0 ? Vector3.Slerp(m_RollUp, targetUp, m_RollSpeed*deltaTime) : Vector3.up;
104 transform.rotation = Quaternion.Lerp(transform.rotation, rollRotation, m_TurnSpeed*m_CurrentTurnAmount*deltaTime);
105 }
106 }
107 }
2 using UnityEngine;
3 #if UNITY_EDITOR
4
5 #endif
6
7 namespace UnityStandardAssets.Cameras
8 {
9 [ExecuteInEditMode]
10 public class AutoCam : PivotBasedCameraRig
11 {
12 [SerializeField] private float m_MoveSpeed = 3; // How fast the rig will move to keep up with target's position
13 [SerializeField] private float m_TurnSpeed = 1; // How fast the rig will turn to keep up with target's rotation
14 [SerializeField] private float m_RollSpeed = 0.2f;// How fast the rig will roll (around Z axis) to match target's roll.
15 [SerializeField] private bool m_FollowVelocity = false;// Whether the rig will rotate in the direction of the target's velocity.
16 [SerializeField] private bool m_FollowTilt = true; // Whether the rig will tilt (around X axis) with the target.
17 [SerializeField] private float m_SpinTurnLimit = 90;// The threshold beyond which the camera stops following the target's rotation. (used in situations where a car spins out, for example)
18 [SerializeField] private float m_TargetVelocityLowerLimit = 4f;// the minimum velocity above which the camera turns towards the object's velocity. Below this we use the object's forward direction.
19 [SerializeField] private float m_SmoothTurnTime = 0.2f; // the smoothing for the camera's rotation
20
21 private float m_LastFlatAngle; // The relative angle of the target and the rig from the previous frame.
22 private float m_CurrentTurnAmount; // How much to turn the camera
23 private float m_TurnSpeedVelocityChange; // The change in the turn speed velocity
24 private Vector3 m_RollUp = Vector3.up;// The roll of the camera around the z axis ( generally this will always just be up )
25
26
27 protected override void FollowTarget(float deltaTime)
28 {
29 // if no target, or no time passed then we quit early, as there is nothing to do
30 if (!(deltaTime > 0) || m_Target == null)
31 {
32 return;
33 }
34
35 // initialise some vars, we'll be modifying these in a moment
36 var targetForward = m_Target.forward;
37 var targetUp = m_Target.up;
38
39 if (m_FollowVelocity && Application.isPlaying)
40 {
41 // in follow velocity mode, the camera's rotation is aligned towards the object's velocity direction
42 // but only if the object is traveling faster than a given threshold.
43
44 if (targetRigidbody.velocity.magnitude > m_TargetVelocityLowerLimit)
45 {
46 // velocity is high enough, so we'll use the target's velocty
47 targetForward = targetRigidbody.velocity.normalized;
48 targetUp = Vector3.up;
49 }
50 else
51 {
52 targetUp = Vector3.up;
53 }
54 m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, 1, ref m_TurnSpeedVelocityChange, m_SmoothTurnTime);
55 }
56 else
57 {
58 // we're in 'follow rotation' mode, where the camera rig's rotation follows the object's rotation.
59
60 // This section allows the camera to stop following the target's rotation when the target is spinning too fast.
61 // eg when a car has been knocked into a spin. The camera will resume following the rotation
62 // of the target when the target's angular velocity slows below the threshold.
63 var currentFlatAngle = Mathf.Atan2(targetForward.x, targetForward.z)*Mathf.Rad2Deg;
64 if (m_SpinTurnLimit > 0)
65 {
66 var targetSpinSpeed = Mathf.Abs(Mathf.DeltaAngle(m_LastFlatAngle, currentFlatAngle))/deltaTime;
67 var desiredTurnAmount = Mathf.InverseLerp(m_SpinTurnLimit, m_SpinTurnLimit*0.75f, targetSpinSpeed);
68 var turnReactSpeed = (m_CurrentTurnAmount > desiredTurnAmount ? .1f : 1f);
69 if (Application.isPlaying)
70 {
71 m_CurrentTurnAmount = Mathf.SmoothDamp(m_CurrentTurnAmount, desiredTurnAmount,
72 ref m_TurnSpeedVelocityChange, turnReactSpeed);
73 }
74 else
75 {
76 // for editor mode, smoothdamp won't work because it uses deltaTime internally
77 m_CurrentTurnAmount = desiredTurnAmount;
78 }
79 }
80 else
81 {
82 m_CurrentTurnAmount = 1;
83 }
84 m_LastFlatAngle = currentFlatAngle;
85 }
86
87 // camera position moves towards target position:
88 transform.position = Vector3.Lerp(transform.position, m_Target.position, deltaTime*m_MoveSpeed);
89
90 // camera's rotation is split into two parts, which can have independend speed settings:
91 // rotating towards the target's forward direction (which encompasses its 'yaw' and 'pitch')
92 if (!m_FollowTilt)
93 {
94 targetForward.y = 0;
95 if (targetForward.sqrMagnitude < float.Epsilon)
96 {
97 targetForward = transform.forward;
98 }
99 }
100 var rollRotation = Quaternion.LookRotation(targetForward, m_RollUp);
101
102 // and aligning with the target object's up direction (i.e. its 'roll')
103 m_RollUp = m_RollSpeed > 0 ? Vector3.Slerp(m_RollUp, targetUp, m_RollSpeed*deltaTime) : Vector3.up;
104 transform.rotation = Quaternion.Lerp(transform.rotation, rollRotation, m_TurnSpeed*m_CurrentTurnAmount*deltaTime);
105 }
106 }
107 }