Tanoda
FollowScript.cs
Go to the documentation of this file.
1using System.Collections;
2using System.Collections.Generic;
3using UnityEngine;
4
5public class FollowScript : MonoBehaviour
6{
7 public Camera followMe;
8
9 [SerializeField, Range(0.0f, 100.0f), Tooltip("How quickly to interpolate the window towards its target position and rotation.")]
10 private float windowFollowSpeed = 5.0f;
11
12 public float WindowFollowSpeed
13 {
14 get { return windowFollowSpeed; }
15 set { windowFollowSpeed = Mathf.Abs(value); }
16 }
17 [SerializeField, Range(0.0f, 10.0f), Tooltip("Extra distance.")]
18 private float windowExtraDistance = 1.0f;
19
21 {
22 get { return windowExtraDistance; }
23 set { windowExtraDistance = Mathf.Abs(value); }
24 }
25 [Header("Window Settings")]
26 [SerializeField, Tooltip("What part of the view port to anchor the window to.")]
27 private TextAnchor windowAnchor = TextAnchor.LowerCenter;
28
29 public TextAnchor WindowAnchor
30 {
31 get { return windowAnchor; }
32 set { windowAnchor = value; }
33 }
34
35 [SerializeField, Tooltip("The offset from the view port center applied based on the window anchor selection.")]
36 private Vector2 windowOffset = new Vector2(0.1f, 0.1f);
37
38 public Vector2 WindowOffset
39 {
40 get { return windowOffset; }
41 set { windowOffset = value; }
42 }
43
44 public bool TryCorrectParentRotation = false;
45 public bool FollowPosition = true;
46 public bool IgnoreY = false;
47 public bool FollowRotation = true;
48 public bool OnlyY = false;
49 [SerializeField, Range(-180.0f, 180.0f)]
50 private float YOffset = 0.0f;
51 public bool OnlyFollowAfterAngleDifference = false;
53 public float AngleDifference = 10.0f;
54
55
56
57 private byte initialFollow = 0;
58
59 private Transform cameraTransform;
60 private Quaternion windowHorizontalRotation;
61 private Quaternion windowHorizontalRotationInverse;
62 private Quaternion windowVerticalRotation;
63 private Quaternion windowVerticalRotationInverse;
64
65 private static readonly Vector2 defaultWindowRotation = new Vector2(10.0f, 20.0f);
66 // Start is called before the first frame update
67 void Start()
68 {
69 if (!followMe)
70 cameraTransform = Camera.main ? Camera.main.transform : null;
71 else
72 cameraTransform = followMe.transform;
73 }
74
75 // Update is called once per frame
76 void LateUpdate()
77 {
78 windowHorizontalRotation = Quaternion.AngleAxis(defaultWindowRotation.y, Vector3.right);
79 windowHorizontalRotationInverse = Quaternion.Inverse(windowHorizontalRotation);
80 windowVerticalRotation = Quaternion.AngleAxis(defaultWindowRotation.x, Vector3.up);
81 windowVerticalRotationInverse = Quaternion.Inverse(windowVerticalRotation);
82 if (cameraTransform != null)
83 {
84 bool shouldFollow = !(!(Mathf.Abs(transform.rotation.eulerAngles.y - cameraTransform.rotation.eulerAngles.y)
85 > AngleDifference) && OnlyFollowAfterAngleDifference) || initialFollow < 180;
86 if (!shouldFollow) return;
87 if (initialFollow < 180)
88 initialFollow++;
89 float t = Time.deltaTime * windowFollowSpeed;
90 bool shouldFollowY = !(!(Mathf.Abs(transform.rotation.eulerAngles.y - cameraTransform.rotation.eulerAngles.y)
91 > AngleDifference) && OnlyFollowAfterAngleDifferenceY) || initialFollow < 180;
92 float distance = Mathf.Max(16.0f / Camera.main.fieldOfView, Camera.main.nearClipPlane + 0.25f) + windowExtraDistance;
93 bool inGoodDistance = Vector3.Distance(cameraTransform.position, transform.position) >= distance * 0.95 && Vector3.Distance(cameraTransform.position, transform.position) <= distance * 1.05;
95 {
96 if (IgnoreY)
97 {
98 var position = Vector3.Lerp(transform.position, CalculateWindowPosition(cameraTransform), t);
99 transform.position = new Vector3(position.x, cameraTransform.position.y, position.z);
100 }
101
102 if (!shouldFollowY && inGoodDistance)
103 {
104 var cameraWorldPos = cameraTransform.parent.TransformPoint(cameraTransform.localPosition);
105
106 //windowDistance = Mathf.Max(16.0f / Camera.main.fieldOfView, Camera.main.nearClipPlane + 0.25f) + windowExtraDistance;
107 var position = Vector3.Lerp(transform.position, CalculateWindowPosition(cameraTransform), t);
108 //var distance = cameraTransform.forward * windowDistance + cameraTransform.position;
109 transform.position = new Vector3(transform.position.x, position.y, transform.position.z);
110 }
111 else
112 {
113 transform.position = Vector3.Lerp(transform.position, CalculateWindowPosition(cameraTransform), t);
114 }
115 }
116 if (FollowRotation)
117 {
118 if (OnlyY)
119 {
120 var rotation =
121 Quaternion.Slerp(transform.rotation, CalculateWindowRotation(cameraTransform),
122 t);
123
124 transform.eulerAngles = new Vector3(transform.eulerAngles.x, rotation.eulerAngles.y, transform.eulerAngles.z);
125 }
126
127 if (!shouldFollowY && inGoodDistance)
128 {
129 var rotation =
130 Quaternion.Slerp(transform.rotation, CalculateWindowRotation(cameraTransform),
131 t);
132
133 transform.eulerAngles = new Vector3(rotation.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
134 }
135
136 else
137 {
138 transform.rotation =
139 Quaternion.Slerp(transform.rotation, CalculateWindowRotation(cameraTransform),
140 t);
141 }
142 }
143 }
144 }
145
146 private Vector3 CalculateWindowPosition(Transform cameraTransform)
147 {
148 float windowDistance = Mathf.Max(16.0f / Camera.main.fieldOfView, Camera.main.nearClipPlane + 0.25f) + windowExtraDistance;
149 Vector3 position = cameraTransform.position + (cameraTransform.forward * windowDistance);
150 Vector3 horizontalOffset = cameraTransform.right * windowOffset.x;
151 Vector3 verticalOffset = cameraTransform.up * windowOffset.y;
152
153 switch (windowAnchor)
154 {
155 case TextAnchor.UpperLeft: position += verticalOffset - horizontalOffset; break;
156 case TextAnchor.UpperCenter: position += verticalOffset; break;
157 case TextAnchor.UpperRight: position += verticalOffset + horizontalOffset; break;
158 case TextAnchor.MiddleLeft: position -= horizontalOffset; break;
159 case TextAnchor.MiddleRight: position += horizontalOffset; break;
160 case TextAnchor.LowerLeft: position -= verticalOffset + horizontalOffset; break;
161 case TextAnchor.LowerCenter: position -= verticalOffset; break;
162 case TextAnchor.LowerRight: position -= verticalOffset - horizontalOffset; break;
163 }
164
165 return position;
166 }
167
168 private Quaternion CalculateWindowRotation(Transform cameraTransform)
169 {
170 Quaternion rotation = cameraTransform.rotation;
171
172 switch (windowAnchor)
173 {
174 case TextAnchor.UpperLeft: rotation *= windowHorizontalRotationInverse * windowVerticalRotationInverse; break;
175 case TextAnchor.UpperCenter: rotation *= windowHorizontalRotationInverse; break;
176 case TextAnchor.UpperRight: rotation *= windowHorizontalRotationInverse * windowVerticalRotation; break;
177 case TextAnchor.MiddleLeft: rotation *= windowVerticalRotationInverse; break;
178 case TextAnchor.MiddleRight: rotation *= windowVerticalRotation; break;
179 case TextAnchor.LowerLeft: rotation *= windowHorizontalRotation * windowVerticalRotationInverse; break;
180 case TextAnchor.LowerCenter: rotation *= windowHorizontalRotation; break;
181 case TextAnchor.LowerRight: rotation *= windowHorizontalRotation * windowVerticalRotation; break;
182 }
183
184 if (TryCorrectParentRotation && transform.parent != null)
185 {
186 rotation *= Quaternion.AngleAxis(180, Vector3.forward);
187 rotation *= Quaternion.AngleAxis(90, Vector3.right);
188 }
189
190 rotation *= Quaternion.AngleAxis(YOffset, Vector3.up);
191
192 return rotation;
193 }
194}
Vector2 WindowOffset
Definition: FollowScript.cs:39
float WindowFollowSpeed
Definition: FollowScript.cs:13
bool OnlyFollowAfterAngleDifferenceY
Definition: FollowScript.cs:52
TextAnchor WindowAnchor
Definition: FollowScript.cs:30
bool TryCorrectParentRotation
Definition: FollowScript.cs:44
bool FollowPosition
Definition: FollowScript.cs:45
bool OnlyFollowAfterAngleDifference
Definition: FollowScript.cs:51
bool FollowRotation
Definition: FollowScript.cs:47
float WindowExtraDistance
Definition: FollowScript.cs:21
float AngleDifference
Definition: FollowScript.cs:53
Camera followMe
Definition: FollowScript.cs:7