diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index fd680daedf..8817dfbe9c 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -12,6 +12,7 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Fixed +- Fixed issue where applying the position and/or rotation to the `NetworkManager.ConnectionApprovalResponse` when connection approval and auto-spawn player prefab were enabled would not apply the position and/or rotation when the player prefab was instantiated. (#3078) - Fixed issue with the client count not being correct on the host or server side when a client disconnects itself from a session. (#3075) ### Changed diff --git a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs index d3b2f9acd6..ce359c180a 100644 --- a/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs +++ b/com.unity.netcode.gameobjects/Runtime/Spawning/NetworkSpawnManager.cs @@ -752,8 +752,8 @@ internal NetworkObject GetNetworkObjectToSpawn(uint globalObjectIdHash, ulong ow } else { - // Create prefab instance - networkObject = UnityEngine.Object.Instantiate(networkPrefabReference).GetComponent(); + // Create prefab instance while applying any pre-assigned position and rotation values + networkObject = UnityEngine.Object.Instantiate(networkPrefabReference, position, rotation).GetComponent(); networkObject.NetworkManagerOwner = NetworkManager; networkObject.PrefabGlobalObjectIdHash = globalObjectIdHash; } diff --git a/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApproval.cs b/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApproval.cs index 6fd311ffa9..efa19cffd5 100644 --- a/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApproval.cs +++ b/com.unity.netcode.gameobjects/Tests/Runtime/ConnectionApproval.cs @@ -4,6 +4,7 @@ using System.Text; using NUnit.Framework; using Unity.Netcode.TestHelpers.Runtime; +using UnityEngine; using UnityEngine.TestTools; namespace Unity.Netcode.RuntimeTests @@ -12,9 +13,10 @@ namespace Unity.Netcode.RuntimeTests [TestFixture(PlayerCreation.PrefabHash)] [TestFixture(PlayerCreation.NoPlayer)] [TestFixture(PlayerCreation.FailValidation)] - internal class ConnectionApprovalTests : NetcodeIntegrationTest + internal class ConnectionApprovalTests : IntegrationTestWithApproximation { private const string k_InvalidToken = "Invalid validation token!"; + public enum PlayerCreation { Prefab, @@ -24,6 +26,8 @@ public enum PlayerCreation } private PlayerCreation m_PlayerCreation; private bool m_ClientDisconnectReasonValidated; + private Vector3 m_ExpectedPosition; + private Quaternion m_ExpectedRotation; private Dictionary m_Validated = new Dictionary(); @@ -43,6 +47,12 @@ protected override bool ShouldCheckForSpawnedPlayers() protected override void OnServerAndClientsCreated() { + if (m_PlayerCreation == PlayerCreation.Prefab || m_PlayerCreation == PlayerCreation.PrefabHash) + { + m_ExpectedPosition = GetRandomVector3(-10.0f, 10.0f); + m_ExpectedRotation = Quaternion.Euler(GetRandomVector3(-359.98f, 359.98f)); + } + m_ClientDisconnectReasonValidated = false; m_BypassConnectionTimeout = m_PlayerCreation == PlayerCreation.FailValidation; m_Validated.Clear(); @@ -104,11 +114,36 @@ private bool ClientAndHostValidated() return true; } + private bool ValidatePlayersPositionRotation() + { + foreach (var playerEntries in m_PlayerNetworkObjects) + { + foreach (var player in playerEntries.Value) + { + if (!Approximately(player.Value.transform.position, m_ExpectedPosition)) + { + return false; + } + if (!Approximately(player.Value.transform.rotation, m_ExpectedRotation)) + { + return false; + } + } + } + return true; + } + [UnityTest] public IEnumerator ConnectionApproval() { yield return WaitForConditionOrTimeOut(ClientAndHostValidated); AssertOnTimeout("Timed out waiting for all clients to be approved!"); + + if (m_PlayerCreation == PlayerCreation.Prefab || m_PlayerCreation == PlayerCreation.PrefabHash) + { + yield return WaitForConditionOrTimeOut(ValidatePlayersPositionRotation); + AssertOnTimeout("Not all player prefabs spawned in the correct position and/or rotation!"); + } } private void NetworkManagerObject_ConnectionApprovalCallback(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response) @@ -127,8 +162,8 @@ private void NetworkManagerObject_ConnectionApprovalCallback(NetworkManager.Conn } response.CreatePlayerObject = ShouldCheckForSpawnedPlayers(); - response.Position = null; - response.Rotation = null; + response.Position = m_ExpectedPosition; + response.Rotation = m_ExpectedRotation; response.PlayerPrefabHash = m_PlayerCreation == PlayerCreation.PrefabHash ? m_PlayerPrefab.GetComponent().GlobalObjectIdHash : null; }