Implement player network spawning and position synchronization

This commit is contained in:
2024-08-25 17:43:19 +02:00
parent 6e037b4d06
commit b05cab8288
30 changed files with 689 additions and 26 deletions

View File

@@ -0,0 +1,112 @@
using HurricaneVR.Framework.Components;
using HurricaneVR.Framework.Core.Player;
using Meta.XR.MultiplayerBlocks.NGO;
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using Unity.Netcode.Components;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using Zenject;
using static Unity.Burst.Intrinsics.X86.Avx;
public class PlayerComponent : NetworkBehaviour
{
[SerializeField]
private NetworkObject networkObject;
[SerializeField]
private HVRTeleporter teleporter;
[SerializeField]
private HVRPlayerController controller;
[SerializeField]
private CharacterController characterController;
[ReadOnly]
[SerializeField]
private float fadeDuration = 2f;
[SerializeField]
public GameManager gameManager;
public Vector3 Position
{
get { return controller.transform.position; }
}
public Vector3 Rotation
{
get { return controller.transform.eulerAngles; }
}
public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();
name = $"Player - {networkObject.OwnerClientId}"
+ (networkObject.IsLocalPlayer ? " (local)" : "");
if (!networkObject.IsOwner)
{
StartCoroutine(DestroyMultiplayerComponents());
}
}
private IEnumerator DestroyMultiplayerComponents()
{
yield return new WaitForEndOfFrame();
DestroyDependencies();
foreach (var t in new[]
{
typeof(UniversalAdditionalCameraData),
})
{
foreach (var component in GetComponentsInChildren(t))
{
Destroy(component);
}
}
controller.RemoveMultiplayerComponents();
}
public void DestroyDependencies()
{
Destroy(controller.RightHand.ForceGrabber._anchor.gameObject);
Destroy(controller.LeftHand.ForceGrabber._anchor.gameObject);
Destroy(controller.LeftHand._anchor);
Destroy(controller.RightHand._anchor);
}
public void DestroyWithDependencies()
{
DestroyDependencies();
Destroy(gameObject);
}
public void Teleport(Vector3 position, Vector3 direction)
{
teleporter.Teleport(position, direction);
}
public void FadeScreen(float to, float duration)
{
controller.ScreenFader.Fade(to, duration);
}
public void FadeIn()
{
controller.ScreenFader.Fade(1, fadeDuration);
}
public void FadeOut()
{
controller.ScreenFader.Fade(0, fadeDuration);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 983bb31c4dab2d84b857006f5099d030
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
using Sirenix.OdinInspector.Editor;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(NetworkBehaviour), true)]
public class OdinNetworkBehaviourEditor : OdinEditor { }

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e4a312837e470c54faa1f6a28f0a201e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -19,8 +19,9 @@ public class PlayerSpawner : MonoBehaviour
.ToArray();
}
public void Spawn(GameObject player)
public void Spawn(PlayerComponent player)
{
player.GetComponent<HVRTeleporter>().Teleport(spawns.First().position);
var spawn = spawns.First();
player.Teleport(spawn.position, spawn.eulerAngles);
}
}

View File

@@ -1,13 +1,12 @@
using HurricaneVR.Framework.Core;
using HurricaneVR.Framework.Core.Player;
using HurricaneVR.Framework.Core.Utils;
using Unity.Netcode;
using UnityEngine;
using Zenject;
public class GlobalInstaller : MonoInstaller
{
[SerializeField]
private GameObject musicPlayerPrefab;
@@ -15,10 +14,16 @@ public class GlobalInstaller : MonoInstaller
private GameObject hvrGlobalPrefab;
[SerializeField]
private GameObject playerPrefab;
private GameObject sceneManagerPrefab;
[SerializeField]
private GameObject sceneManagerPrefab;
private GameObject networkManagerPrefab;
[SerializeField]
private GameObject gameManagerPrefab;
[SerializeField]
private GameObject playerPrefab;
public override void Start()
{
@@ -46,12 +51,12 @@ public class GlobalInstaller : MonoInstaller
})
.NonLazy();
Container.Bind<HVRPlayerController>()
.FromComponentInNewPrefab(playerPrefab)
Container.Bind<GameManager>()
.FromComponentInNewPrefab(gameManagerPrefab)
.AsSingle()
.OnInstantiated<HVRPlayerController>((ctx, obj) =>
.OnInstantiated<GameManager>((ctx, obj) =>
{
obj.transform.parent.name = playerPrefab.name;
obj.name = gameManagerPrefab.name;
})
.NonLazy();
@@ -63,5 +68,23 @@ public class GlobalInstaller : MonoInstaller
obj.name = sceneManagerPrefab.name;
})
.NonLazy();
Container.Bind<NetworkManager>()
.FromComponentInNewPrefab(networkManagerPrefab)
.AsSingle()
.OnInstantiated<NetworkManager>((ctx, obj) =>
{
obj.name = networkManagerPrefab.name;
})
.NonLazy();
Container.Bind<PlayerComponent>()
.FromComponentInNewPrefab(playerPrefab)
.AsSingle()
.OnInstantiated<PlayerComponent>((ctx, obj) =>
{
obj.name = playerPrefab.name;
})
.NonLazy();
}
}

View File

@@ -0,0 +1,54 @@
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using Zenject;
public class ConnectionManager : NetworkBehaviour
{
[SerializeField]
private NetworkManager networkManager;
[Inject]
[SerializeField]
[ReadOnly]
private GameManager gameManager;
private void Start()
{
networkManager.OnClientConnectedCallback += OnClientConnectedCallback;
networkManager.OnClientDisconnectCallback += OnClientDisconnectCallback;
}
private void OnClientConnectedCallback(ulong clientId)
{
Debug.Log($"Client-{clientId} is connected and can spawn {nameof(NetworkObject)}s.");
if (networkManager.LocalClientId == clientId)
{
StartCoroutine(SpawnLocalPlayer());
}
}
private IEnumerator SpawnLocalPlayer()
{
yield return new WaitForEndOfFrame();
var playerObject = networkManager.LocalClient.PlayerObject;
var player = playerObject.GetComponent<PlayerComponent>();
player.gameManager = gameManager;
gameManager.PlayerSpawnedOnNetwork(player);
yield return null;
}
private void OnClientDisconnectCallback(ulong clientId)
{
Debug.Log($"Client-{clientId} is disconnected and can spawn {nameof(NetworkObject)}s.");
if (networkManager.LocalClientId == clientId)
{
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb16de57aad3ebe42bb3df246dc58d5f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,27 @@
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using Zenject;
public class GameManager : NetworkBehaviour
{
[SerializeField]
[ReadOnly]
[Inject]
private PlayerComponent localPlayer;
public PlayerComponent LocalPlayer {
get { return localPlayer; }
}
public void PlayerSpawnedOnNetwork(PlayerComponent player)
{
if (player.IsLocalPlayer)
{
player.Teleport(localPlayer.Position, localPlayer.Rotation);
localPlayer.DestroyWithDependencies();
localPlayer = player;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d357a0b6e2db94a4aadef95ef4fff758
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -33,7 +33,7 @@ public class LevelManager : MonoBehaviour
[Inject]
[SerializeField]
[ReadOnly]
private HVRPlayerController playerController;
private GameManager gameManager;
private void Start()
{
@@ -44,7 +44,8 @@ public class LevelManager : MonoBehaviour
musicManager.Play(level.pauseClip);
}
playerSpawner.Spawn(playerController.gameObject);
var player = gameManager.LocalPlayer;
playerSpawner.Spawn(player);
}
public void OnEnemyReachedFinish(EnemyComponent enemy)

View File

@@ -2,10 +2,11 @@ using HurricaneVR.Framework.Core.Player;
using Sirenix.OdinInspector;
using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using Zenject;
public class LobbyManager : MonoBehaviour
public class LobbyManager : NetworkBehaviour
{
[Inject]
[SerializeField]
@@ -20,7 +21,7 @@ public class LobbyManager : MonoBehaviour
[Inject]
[SerializeField]
[ReadOnly]
private HVRPlayerController playerController;
private GameManager gameManager;
[SerializeField]
private AudioClip backgroundMusicClip;
@@ -29,6 +30,7 @@ public class LobbyManager : MonoBehaviour
{
musicManager.Play(backgroundMusicClip);
playerSpawner.Spawn(playerController.gameObject);
var player = gameManager.LocalPlayer;
playerSpawner.Spawn(player);
}
}

View File

@@ -18,7 +18,7 @@ public class SceneManager : MonoBehaviour
[Inject]
[ReadOnly]
[SerializeField]
private HVRPlayerController playerController;
private GameManager gameManager;
[ReadOnly]
[SerializeField]
@@ -36,7 +36,7 @@ public class SceneManager : MonoBehaviour
private IEnumerator SwitchToScene(Scene scene)
{
playerController.ScreenFader.Fade(1, fadeDuration);
gameManager.LocalPlayer.FadeScreen(1, fadeDuration);
var operation = UnityEngine.SceneManagement.SceneManager
.LoadSceneAsync((int)scene);
@@ -55,6 +55,6 @@ public class SceneManager : MonoBehaviour
this.scene = scene;
playerController.ScreenFader.Fade(0, fadeDuration);
gameManager.LocalPlayer.FadeScreen(0, fadeDuration);
}
}