-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFollowCamera.cs
More file actions
150 lines (127 loc) · 4.82 KB
/
Copy pathFollowCamera.cs
File metadata and controls
150 lines (127 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
using UnityEngine;
/// <summary>
/// Creates a Google Glass-style HUD that stays in a fixed position relative to the camera.
/// Reparents the object to the camera transform so it moves with the user's head.
/// </summary>
public class FollowCamera : MonoBehaviour
{
[Header("HUD Positioning")]
[Tooltip("Horizontal offset from center (positive = right, negative = left)")]
public float horizontalOffset = 0.6f;
[Tooltip("Vertical offset from center (positive = up, negative = down)")]
public float verticalOffset = 0.15f;
[Tooltip("Distance from camera (further = smaller in view)")]
public float distance = 1.2f;
[Header("Scale")]
[Tooltip("Scale multiplier for the UI (1 = original size, 0.5 = half size)")]
public float scaleMultiplier = 0.35f;
[Header("Transition")]
[Tooltip("Smooth transition when reparenting (0 = instant)")]
public float reparentSmoothTime = 0.3f;
private Transform _cameraTransform;
private bool _isReparented = false;
private Vector3 _targetLocalPosition;
private Vector3 _velocity = Vector3.zero;
private Vector3 _originalScale;
void Start()
{
// Store original scale
_originalScale = transform.localScale;
// Find the camera
var rig = FindFirstObjectByType<OVRCameraRig>();
if (rig != null)
{
_cameraTransform = rig.centerEyeAnchor;
Debug.Log("FollowCamera: Found OVRCameraRig centerEyeAnchor");
}
else if (Camera.main != null)
{
_cameraTransform = Camera.main.transform;
Debug.Log("FollowCamera: Using Camera.main");
}
if (_cameraTransform == null)
{
Debug.LogError("FollowCamera: Could not find camera. Make sure OVRCameraRig or Camera.main exists.");
enabled = false;
return;
}
// Calculate target local position (top-right corner)
_targetLocalPosition = new Vector3(horizontalOffset, verticalOffset, distance);
// Reparent to camera
if (transform.parent != _cameraTransform)
{
// Convert current world position to local space of camera
Vector3 startLocalPos = _cameraTransform.InverseTransformPoint(transform.position);
// Set parent
transform.SetParent(_cameraTransform, true);
// Apply scale
transform.localScale = _originalScale * scaleMultiplier;
// Smooth transition to target position
if (reparentSmoothTime > 0)
{
StartCoroutine(SmoothTransitionToPosition(startLocalPos, _targetLocalPosition));
}
else
{
transform.localPosition = _targetLocalPosition;
_isReparented = true;
}
}
else
{
transform.localScale = _originalScale * scaleMultiplier;
transform.localPosition = _targetLocalPosition;
_isReparented = true;
}
}
System.Collections.IEnumerator SmoothTransitionToPosition(Vector3 start, Vector3 target)
{
float elapsedTime = 0f;
while (elapsedTime < reparentSmoothTime)
{
elapsedTime += Time.deltaTime;
float t = elapsedTime / reparentSmoothTime;
// Smoothstep for smooth acceleration/deceleration
t = t * t * (3f - 2f * t);
transform.localPosition = Vector3.Lerp(start, target, t);
yield return null;
}
transform.localPosition = target;
_isReparented = true;
}
void LateUpdate()
{
if (!_isReparented) return;
// Update position if parameters change during runtime
Vector3 newTargetPos = new Vector3(horizontalOffset, verticalOffset, distance);
if (transform.localPosition != newTargetPos)
{
transform.localPosition = Vector3.SmoothDamp(
transform.localPosition,
newTargetPos,
ref _velocity,
0.1f
);
}
// Ensure scale is maintained
Vector3 targetScale = _originalScale * scaleMultiplier;
if (transform.localScale != targetScale)
{
transform.localScale = targetScale;
}
// Reset rotation to identity (face same direction as camera)
transform.localRotation = Quaternion.identity;
}
void OnDestroy()
{
// Restore original scale and unparent when destroyed
if (transform != null)
{
transform.localScale = _originalScale;
if (transform.parent != null && _cameraTransform != null && transform.parent == _cameraTransform)
{
transform.SetParent(null, true);
}
}
}
}