VR Development Framework
v 1.0.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
AVR_GenericXRDevice.cs
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using UnityEngine.XR;
5 
6 namespace AVR.Core
7 {
8  /// <summary>
9  /// Represents some spatially tracked XR device. Provides functionality for spacial tracking.
10  /// Can be used to represent hardware trackers, game controllers or other references.
11  /// </summary>
12  [AVR.Core.Attributes.DocumentationUrl("class_a_v_r_1_1_core_1_1_a_v_r___generic_x_r_device.html")]
14  {
15  protected static Dictionary<XRNode, AVR_GenericXRDevice> nodeDevices = new Dictionary<XRNode, AVR_GenericXRDevice>();
16 
17  /// <summary>
18  /// Returns the last AVR_GenericXRDevice enabled that has a given controllerNode value.
19  /// </summary>
20  /// <param name="node">Node of the requested device</param>
21  /// <returns>last AVR_GenericXRDevice enabled that has a given controllerNode value. Null if none exists.</returns>
22  public static AVR_GenericXRDevice getDeviceAtNode(XRNode node) {
23  nodeDevices.TryGetValue(node, out var val);
24  return val;
25  }
26 
27  [Header("XR Node")]
28 
29  /// <summary>
30  /// Which XRNode this object represents.
31  /// </summary>
32  public XRNode controllerNode;
33 
34  /// <summary>
35  /// XR.Inputdevice that this controller represents.
36  /// </summary>
37  public InputDevice inputDevice => _inputDevice.isValid ? _inputDevice : _inputDevice = InputDevices.GetDeviceAtXRNode(controllerNode);
38  private InputDevice _inputDevice;
39 
40 
41  [Header("Tracking")]
42 
43  /// <summary>
44  /// Defines if spatial tracking should be performed.
45  /// </summary>
46  public bool tracking = true;
47 
48  /// <summary>
49  /// Defines when positional tracking should take place. Recommended setting is OnBeforeRenderAndUpdate
50  /// </summary>
51  public enum TrackingUpdateType
52  {
53  OnUpdate,
54  OnBeforeRender,
55  OnBeforeRenderAndUpdate,
56  }
57 
58  /// <summary>
59  /// Defines when positional tracking should take place. Recommended setting is OnBeforeRenderAndUpdate
60  /// </summary>
62  public TrackingUpdateType updateType;
63 
64 
65  [Header("Smoothing")]
66 
67  /// <summary>
68  /// Defines if positional tracking is smoothed across several frames. Makes controllers less shaky.
69  /// </summary>
70  public bool smoothing = false;
71 
72  /// <summary>
73  /// Defines the amount of smoothing.
74  /// </summary>
76  public float smoothingFidelity = 0.3f;
77 
78  // Variables for smoothing
79  private Vector3 prevPos = Vector3.zero;
80  private Quaternion prevRot = Quaternion.identity;
81 
82 
83  protected override void Awake()
84  {
85  nodeDevices[controllerNode] = this;
86  base.Awake();
87  }
88 
89  /// <summary>
90  /// Updates the controller position and rotation.
91  /// </summary>
92  protected void UpdateTracking()
93  {
94  if (inputDevice.TryGetFeatureValue(CommonUsages.trackingState, out var trackingState))
95  {
96  if ((trackingState & InputTrackingState.Position) != 0 && inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out var devicePosition))
97  {
98  if (smoothing)
99  {
100  transform.localPosition = Vector3.Lerp(transform.localPosition, devicePosition, Time.deltaTime * smoothingFidelity * 90.0f);
101  }
102  else
103  {
104  transform.localPosition = devicePosition;
105  }
106  }
107 
108  if ((trackingState & InputTrackingState.Rotation) != 0 && inputDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out var deviceRotation))
109  {
110  if (smoothing)
111  {
112  transform.localRotation = Quaternion.Lerp(transform.localRotation, deviceRotation, Time.deltaTime * smoothingFidelity * 90.0f);
113  }
114  else
115  {
116  transform.localRotation = deviceRotation;
117  }
118  }
119  }
120  }
121 
122  protected void OnBeforeRender()
123  {
124 #if AVR_NET
125  if (IsOnline)
126  {
127  sync();
128  if (!IsOwner) return;
129  }
130 #endif
131  if (tracking && (updateType == TrackingUpdateType.OnBeforeRender || updateType == TrackingUpdateType.OnBeforeRenderAndUpdate))
132  {
133  UpdateTracking();
134  }
135  }
136 
137  protected void Update()
138  {
139 #if AVR_NET
140  if (IsOnline)
141  {
142  sync();
143  if (!IsOwner) return;
144  }
145 #endif
146 
147  if (tracking && (updateType == TrackingUpdateType.OnUpdate || updateType == TrackingUpdateType.OnBeforeRenderAndUpdate))
148  {
149  UpdateTracking();
150  }
151  }
152 
153  protected override void OnEnable()
154  {
155  base.OnEnable();
156  nodeDevices[controllerNode] = this;
157  Application.onBeforeRender += OnBeforeRender;
158  }
159 
160  protected override void OnDisable()
161  {
162  base.OnDisable();
163  if(nodeDevices.ContainsKey(controllerNode) && nodeDevices[controllerNode] == this) nodeDevices.Remove(controllerNode);
164  Application.onBeforeRender -= OnBeforeRender;
165  }
166 
167 #if AVR_NET
168  [HideInInspector]
170  public bool synchronizeTransform = false;
171 
172  [Unity.Netcode.ServerRpc(RequireOwnership = false)]
173  private void syncServerRpc(InternalState state)
174  {
175  m_ReplicatedState.Value = state;
176  }
177 
178  private void sync()
179  {
180  if (!synchronizeTransform) return;
181  if (IsOwner)
182  {
183  InternalState state = new InternalState();
184  state.FromReference(this);
185  syncServerRpc(state);
186  }
187  else
188  {
189  m_ReplicatedState.Value.ApplyState(this);
190  }
191  }
192 
193  private readonly Unity.Netcode.NetworkVariable<InternalState> m_ReplicatedState = new Unity.Netcode.NetworkVariable<InternalState>(Unity.Netcode.NetworkVariableReadPermission.Everyone, new InternalState());
194 
195  private struct InternalState : IInternalState<AVR_GenericXRDevice>
196  {
197  public Vector3 trackingPos;
198  public Quaternion trackingRot;
199 
200  public void FromReference(AVR_GenericXRDevice reference)
201  {
202  trackingPos = reference.transform.position;
203  trackingRot = reference.transform.rotation;
204  }
205 
206  public void ApplyState(AVR_GenericXRDevice reference)
207  {
208  reference.transform.position = trackingPos;
209  reference.transform.rotation = trackingRot;
210  }
211 
212  public void NetworkSerialize<T>(Unity.Netcode.BufferSerializer<T> serializer) where T : Unity.Netcode.IReaderWriter
213  {
214  serializer.SerializeValue(ref trackingPos);
215  serializer.SerializeValue(ref trackingRot);
216  }
217  }
218 #endif
219  }
220 }
Makes a property of an object only show in the Network-behaviour window. Also works for private/prote...
Sets the documentation html file inside of Packages/com.avr.core/Documentation/html of a given class...
static AVR_GenericXRDevice getDeviceAtNode(XRNode node)
Returns the last AVR_GenericXRDevice enabled that has a given controllerNode value.
XRNode controllerNode
Which XRNode this object represents.
Allows for simple hiding of properties in the UnityEditor depending on certain conditions. For instance, in the following example the "type" field will only be displayed in the inspector if the "tracking" field is set to true:
Represents some spatially tracked XR device. Provides functionality for spacial tracking. Can be used to represent hardware trackers, game controllers or other references.
void UpdateTracking()
Updates the controller position and rotation.
TrackingUpdateType
Defines when positional tracking should take place. Recommended setting is OnBeforeRenderAndUpdate ...
Base class for all arc-vr components. A component is typically a Monobehaviour that represents a virt...