VR Development Framework
v 1.0.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
AVR_LocomotionProvider.cs
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 
5 using AVR.Core;
6 
7 namespace AVR.Motion {
8  /// <summary>
9  /// Provides locomotion-movement to a controller.
10  /// </summary>
11  [AVR.Core.Attributes.DocumentationUrl("class_a_v_r_1_1_motion_1_1_a_v_r___locomotion_provider.html")]
13  {
14  /// <summary>
15  /// What should determine the direction of movement? Example: "RELATIVE_TO_CONTROLLER" will move the Rig in the direction the controller is facing.
16  /// </summary>
17  public enum DirectionType { RELATIVE_TO_CONTROLLER, RELATIVE_TO_HEADSET, RELATIVE_TO_RIG, ABSOLUTE }
18 
19  /// <summary>
20  /// The input is given by a 2d vector from the controller (moveDirection), this value determines how this 2d vector maps into 3d movement.
21  /// It gives the directions (with local space given by DirectionType) that represent the x and y inputs.
22  /// Example: "XZ" mean input.x maps to movement along the x-axis and input.y maps to movement along the z-axis
23  /// </summary>
24  public enum DirectionAxes { XY, XZ, YX, YZ, ZX, ZY }
25 
26  [Header("Input")]
27  /// <summary>
28  /// Movement is only performed when this event is true.
29  /// </summary>
31 
32  /// <summary>
33  /// The event we retrieve our movement vector from.
34  /// </summary>
36 
37  [Header("Direction Controls")]
38  /// <summary>
39  /// What should determine the direction of movement? Example: "RELATIVE_TO_CONTROLLER" will move the Rig in the direction the controller is facing.
40  /// </summary>
41  public DirectionType dirType = DirectionType.RELATIVE_TO_CONTROLLER;
42 
43  /// <summary>
44  /// The input is given by a 2d vector from the controller (moveDirection), this value determines how this 2d vector maps into 3d movement.
45  /// It gives the directions (with local space given by DirectionType) that represent the x and y inputs.
46  /// Example: "XZ" mean input.x maps to movement along the x-axis and input.y maps to movement along the z-axis
47  /// </summary>
48  public DirectionAxes dirAxes = DirectionAxes.XZ;
49 
50  [Header("Settings")]
51  /// <summary>
52  /// Determines the base movement speed of the charactercontroller.
53  /// </summary>
54  public float speed = 2.0f;
55 
56  /// <summary>
57  /// Determines whether if gravity is applied to the charactercontroller.
58  /// </summary>
59  public bool use_gravity = true;
60 
61  /// <summary>
62  /// Disables movement along the world-space y-axis. This exludes gravity, which will still be applied if use_gravity is set.
63  /// </summary>
64  public bool disable_y_axis = false;
65 
66  /// <summary>
67  /// If set to false, speed will be set instantly. If set to true, movement will accelerate over time.
68  /// </summary>
69  public bool use_acceleration = false;
70 
71  [AVR.Core.Attributes.ConditionalHideInInspector("use_acceleration", true)]
72  [Range(0, 1)]
73  /// <summary>
74  /// Determines the amount acceleration. 0 means no movement ever, 1 means instant acceleration.
75  /// </summary>
76  public float acceleration_constant = 0.1f;
77 
78  // Private vars:
79  private System.Func<Vector2, Vector3> tF;
80  private CharacterController ch => playerRig.characterController;
81  private Vector3 movement = Vector3.zero;
82 
83  protected override void Awake()
84  {
85  base.Awake();
86 
87  switch(dirAxes) {
88  case DirectionAxes.XY: { tF = (v) => new Vector3(v.x, v.y, 0); break; }
89  case DirectionAxes.XZ: { tF = (v) => new Vector3(v.x, 0, v.y); break; }
90  case DirectionAxes.YX: { tF = (v) => new Vector3(v.y, v.x, 0); break; }
91  case DirectionAxes.YZ: { tF = (v) => new Vector3(0, v.x, v.y); break; }
92  case DirectionAxes.ZX: { tF = (v) => new Vector3(v.y, 0, v.x); break; }
93  case DirectionAxes.ZY: { tF = (v) => new Vector3(0, v.y, v.x); break; }
94  default: { AVR_DevConsole.cwarn("The given DirectionAxes are invalid.", this); tF = (v) => new Vector3(v.x, v.y, 0); break; }
95  }
96 
97  if(!use_acceleration) acceleration_constant = 1.0f;
98  }
99 
100  // This needs to be in LateUpdate because AVR_CharacterController.Update() NEEDS to run first.
101  void LateUpdate()
102  {
103 #if AVR_NET
104  if (IsOnline)
105  {
106  sync();
107  if (!IsOwner) return;
108  }
109 #endif
110 
111  if (controller.inputManager.getEventStatus(moveEvent)) {
112  Vector2 md = controller.inputManager.getEventStatus(moveDirection);
113  Vector3 dir = tF(md);
114 
115  switch(dirType) {
116  case DirectionType.RELATIVE_TO_CONTROLLER : {
117  dir = controller.transform.TransformDirection(dir);
118  break;
119  }
120  case DirectionType.RELATIVE_TO_RIG : {
121  dir = playerRig.transform.TransformDirection(dir);
122  break;
123  }
124  case DirectionType.RELATIVE_TO_HEADSET : {
125  dir = playerRig.MainCamera.transform.TransformDirection(dir);
126  break;
127  }
128  }
129 
130  movement = Vector3.Lerp(movement, dir * speed, acceleration_constant);
131 
132  if(disable_y_axis) movement.y = 0;
133 
134  if(ch) {
135  ch.Move(movement * Time.deltaTime);
136 
137  if(use_gravity) {
138  Vector3 gravity = Physics.gravity * Time.deltaTime;
139  ch.Move(gravity);
140  }
141  }
142  else {
143  AVR_DevConsole.cerror("The PlayerRig does not have a charactercontroller. LocomotionProvider requires a charactercontroller.", this);
144  }
145  }
146  }
147 
148 #if AVR_NET
149  [HideInInspector]
151  public bool synchronizeCharacterController = false;
152 
153  [Unity.Netcode.ServerRpc(RequireOwnership = false)]
154  private void syncServerRpc(InternalState state)
155  {
156  m_ReplicatedState.Value = state;
157  }
158 
159  private void sync()
160  {
161  if (!synchronizeCharacterController) return;
162  if (IsOwner)
163  {
164  InternalState state = new InternalState();
165  state.FromReference(this);
166  }
167  else
168  {
169  m_ReplicatedState.Value.ApplyState(this);
170  }
171  }
172 
173  private readonly Unity.Netcode.NetworkVariable<InternalState> m_ReplicatedState = new Unity.Netcode.NetworkVariable<InternalState>(Unity.Netcode.NetworkVariableReadPermission.Everyone, new InternalState());
174 
175  private struct InternalState : IInternalState<AVR_LocomotionProvider>
176  {
177  public Vector3 chCenter;
178  public float chHeight;
179 
180  public void FromReference(AVR_LocomotionProvider reference)
181  {
182  chCenter = reference.ch.center;
183  chHeight = reference.ch.height;
184  }
185 
186  public void ApplyState(AVR_LocomotionProvider reference)
187  {
188  reference.ch.center = chCenter;
189  reference.ch.height = chHeight;
190  }
191 
192  public void NetworkSerialize<T>(Unity.Netcode.BufferSerializer<T> serializer) where T : Unity.Netcode.IReaderWriter
193  {
194  serializer.SerializeValue(ref chCenter);
195  serializer.SerializeValue(ref chHeight);
196  }
197  }
198 #endif
199  }
200 }
BoolEvent
Boolean-returning events of a controller.
AVR_ControllerInputManager.Vec2Event moveDirection
The event we retrieve our movement vector from.
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...
Provides locomotion-movement to a controller.
DirectionAxes
The input is given by a 2d vector from the controller (moveDirection), this value determines how this...
AVR_Component specifically attatched to an AVR_Controller. Needs to have an AVR_Controller on this ga...
DirectionType
What should determine the direction of movement? Example: "RELATIVE_TO_CONTROLLER" will move the Rig ...
Vec2Event
2D vector returning events of a controller.
AVR_ControllerInputManager.BoolEvent moveEvent
Movement is only performed when this event is true.
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:
System.Func< Vector2, Vector3 > tF