|
4 | 4 | using UnityEngine;
|
5 | 5 | using UnityEngine.TestTools;
|
6 | 6 | using Unity.Netcode.TestHelpers.Runtime;
|
| 7 | +using Unity.Netcode.Transports.UTP; |
7 | 8 |
|
8 | 9 | namespace Unity.Netcode.RuntimeTests
|
9 | 10 | {
|
@@ -134,6 +135,111 @@ public enum OverrideState
|
134 | 135 | CommitToTransform
|
135 | 136 | }
|
136 | 137 |
|
| 138 | + [UnityTest] |
| 139 | + public IEnumerator NetworkTransformParentingLocalSpaceOffsetTests([Values] TransformSpace testLocalTransform, [Values] Interpolation interpolation, [Values] OverrideState overideState) |
| 140 | + { |
| 141 | + var overrideUpdate = overideState == OverrideState.CommitToTransform; |
| 142 | + m_AuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; |
| 143 | + m_NonAuthoritativeTransform.Interpolate = interpolation == Interpolation.EnableInterpolate; |
| 144 | + |
| 145 | + m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; |
| 146 | + |
| 147 | + // WIP |
| 148 | + |
| 149 | + yield return null; |
| 150 | + } |
| 151 | + |
| 152 | + private IEnumerator MoveAndRotateAuthority(Vector3 position, Vector3 rotation) |
| 153 | + { |
| 154 | + m_AuthoritativeTransform.transform.position = position; |
| 155 | + yield return null; |
| 156 | + var authoritativeRotation = m_AuthoritativeTransform.transform.rotation; |
| 157 | + authoritativeRotation.eulerAngles = rotation; |
| 158 | + m_AuthoritativeTransform.transform.rotation = authoritativeRotation; |
| 159 | + yield return null; |
| 160 | + } |
| 161 | + |
| 162 | + private int m_PositionRotationIterations = 8; |
| 163 | + |
| 164 | + private IEnumerator WaitForPositionAndRotationToMatch(int ticksToWait) |
| 165 | + { |
| 166 | + // Validate we interpolate to the appropriate position and rotation |
| 167 | + yield return WaitForConditionOrTimeOut(PositionAndRotationMatches); |
| 168 | + AssertOnTimeout("Timed out waiting for non-authority to match authority's position or rotation"); |
| 169 | + |
| 170 | + // Wait for the specified number of ticks |
| 171 | + for (int i = 0; i < ticksToWait; i++) |
| 172 | + { |
| 173 | + yield return s_DefaultWaitForTick; |
| 174 | + } |
| 175 | + |
| 176 | + // Verify both sides match (i.e. no drifting or over-extrapolating) |
| 177 | + Assert.IsTrue(PositionsMatch(), $"Non-authority position did not match after waiting for {ticksToWait} ticks! " + |
| 178 | + $"Authority ({m_AuthoritativeTransform.transform.position}) Non-Authority ({m_NonAuthoritativeTransform.transform.position})"); |
| 179 | + Assert.IsTrue(RotationsMatch(), $"Non-authority rotation did not match after waiting for {ticksToWait} ticks! " + |
| 180 | + $"Authority ({m_AuthoritativeTransform.transform.rotation.eulerAngles}) Non-Authority ({m_NonAuthoritativeTransform.transform.rotation.eulerAngles})"); |
| 181 | + } |
| 182 | + |
| 183 | + [UnityTest] |
| 184 | + public IEnumerator NetworkTransformMultipleChangesOverTime([Values] TransformSpace testLocalTransform, [Values] OverrideState overideState) |
| 185 | + { |
| 186 | + var overrideUpdate = overideState == OverrideState.CommitToTransform; |
| 187 | + m_AuthoritativeTransform.InLocalSpace = testLocalTransform == TransformSpace.Local; |
| 188 | + |
| 189 | + // Wait for tick to change (so we start close to the beginning the next tick) |
| 190 | + var currentTick = m_AuthoritativeTransform.NetworkManager.LocalTime.Tick; |
| 191 | + while (m_AuthoritativeTransform.NetworkManager.LocalTime.Tick == currentTick) |
| 192 | + { |
| 193 | + yield return null; |
| 194 | + } |
| 195 | + |
| 196 | + var positionStart = new Vector3(1.0f, 0.5f, 2.0f); |
| 197 | + var rotationStart = new Vector3(0.0f, 45.0f, 0.0f); |
| 198 | + var position = positionStart; |
| 199 | + var rotation = rotationStart; |
| 200 | + // Move and rotate within the same tick, validate the non-authoritative instance updates |
| 201 | + // to each set of changes. Repeat several times. |
| 202 | + for (int i = 1; i < m_PositionRotationIterations + 1; i++) |
| 203 | + { |
| 204 | + position = positionStart * i; |
| 205 | + rotation = rotationStart * i; |
| 206 | + MoveAndRotateAuthority(position, rotation); |
| 207 | + yield return WaitForPositionAndRotationToMatch(4); |
| 208 | + } |
| 209 | + |
| 210 | + // Repeat this in the opposite direction |
| 211 | + for (int i = -1; i > -1 * (m_PositionRotationIterations + 1); i--) |
| 212 | + { |
| 213 | + position = positionStart * i; |
| 214 | + rotation = rotationStart * i; |
| 215 | + MoveAndRotateAuthority(position, rotation); |
| 216 | + yield return WaitForPositionAndRotationToMatch(4); |
| 217 | + } |
| 218 | + |
| 219 | + // Move and rotate within the same tick several times, then validate the non-authoritative |
| 220 | + // instance updates to the authoritative instance's final position and rotation. |
| 221 | + for (int i = 1; i < m_PositionRotationIterations + 1; i++) |
| 222 | + { |
| 223 | + position = positionStart * i; |
| 224 | + rotation = rotationStart * i; |
| 225 | + MoveAndRotateAuthority(position, rotation); |
| 226 | + |
| 227 | + } |
| 228 | + |
| 229 | + yield return WaitForPositionAndRotationToMatch(1); |
| 230 | + |
| 231 | + // Repeat this in the opposite direction |
| 232 | + for (int i = -1; i > -1 * (m_PositionRotationIterations + 1); i--) |
| 233 | + { |
| 234 | + position = positionStart * i; |
| 235 | + rotation = rotationStart * i; |
| 236 | + MoveAndRotateAuthority(position, rotation); |
| 237 | + } |
| 238 | + yield return WaitForPositionAndRotationToMatch(1); |
| 239 | + } |
| 240 | + |
| 241 | + |
| 242 | + |
137 | 243 | /// <summary>
|
138 | 244 | /// Tests changing all axial values one at a time.
|
139 | 245 | /// These tests are performed:
|
@@ -504,6 +610,11 @@ private bool PositionRotationScaleMatches(Vector3 position, Vector3 eulerRotatio
|
504 | 610 | return PositionsMatchesValue(position) && RotationMatchesValue(eulerRotation) && ScaleMatchesValue(scale);
|
505 | 611 | }
|
506 | 612 |
|
| 613 | + private bool PositionAndRotationMatches() |
| 614 | + { |
| 615 | + return RotationsMatch() && PositionsMatch(); |
| 616 | + } |
| 617 | + |
507 | 618 | private bool RotationsMatch()
|
508 | 619 | {
|
509 | 620 | var authorityEulerRotation = m_AuthoritativeTransform.transform.rotation.eulerAngles;
|
|
0 commit comments