Added many other things and processings
This commit is contained in:
@@ -1,43 +1,116 @@
|
||||
using Unity.Netcode;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public sealed class PlayerSpawnController : NetworkBehaviour, IPlayerSystem
|
||||
{
|
||||
[Header("Random spawn area")]
|
||||
[SerializeField] private Vector3 spawnCenter = new(0f, 1f, 0f);
|
||||
[SerializeField, Min(0f)] private float spawnRadius = 8f;
|
||||
[Header("Start Room Spawn")]
|
||||
[SerializeField, Min(0f)] private float edgePadding = 0.75f;
|
||||
[SerializeField, Min(0f)] private float heightAboveFloor = 0.15f;
|
||||
|
||||
private readonly NetworkVariable<Vector3> assignedSpawnPosition = new(
|
||||
Vector3.zero,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
private readonly NetworkVariable<bool> hasAssignedSpawnPosition = new(
|
||||
false,
|
||||
NetworkVariableReadPermission.Everyone,
|
||||
NetworkVariableWritePermission.Server);
|
||||
|
||||
private int assignedSceneHandle = -1;
|
||||
|
||||
public void Initialize(PlayerFacade facade) { }
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
assignedSpawnPosition.OnValueChanged += HandleSpawnPositionChanged;
|
||||
hasAssignedSpawnPosition.OnValueChanged += HandleSpawnAssignmentChanged;
|
||||
SceneManager.sceneLoaded += HandleSceneLoaded;
|
||||
|
||||
if (IsServer)
|
||||
{
|
||||
Vector2 randomOffset = Random.insideUnitCircle * spawnRadius;
|
||||
assignedSpawnPosition.Value = spawnCenter + new Vector3(randomOffset.x, 0f, randomOffset.y);
|
||||
}
|
||||
TryAssignStartRoomPosition(SceneManager.GetActiveScene());
|
||||
|
||||
ApplySpawnPosition(assignedSpawnPosition.Value);
|
||||
if (hasAssignedSpawnPosition.Value)
|
||||
ApplySpawnPosition(assignedSpawnPosition.Value);
|
||||
}
|
||||
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
assignedSpawnPosition.OnValueChanged -= HandleSpawnPositionChanged;
|
||||
hasAssignedSpawnPosition.OnValueChanged -= HandleSpawnAssignmentChanged;
|
||||
SceneManager.sceneLoaded -= HandleSceneLoaded;
|
||||
}
|
||||
|
||||
private void HandleSpawnPositionChanged(Vector3 _, Vector3 position) =>
|
||||
ApplySpawnPosition(position);
|
||||
private void HandleSceneLoaded(Scene scene, LoadSceneMode _)
|
||||
{
|
||||
if (IsServer)
|
||||
TryAssignStartRoomPosition(scene);
|
||||
|
||||
if (IsOwner && hasAssignedSpawnPosition.Value)
|
||||
ApplySpawnPosition(assignedSpawnPosition.Value);
|
||||
}
|
||||
|
||||
private void TryAssignStartRoomPosition(Scene scene)
|
||||
{
|
||||
if (!scene.IsValid() || !scene.isLoaded || scene.handle == assignedSceneHandle)
|
||||
return;
|
||||
|
||||
StartRoomZone startRoom = FindStartRoomInScene(scene);
|
||||
if (startRoom == null ||
|
||||
!startRoom.TryGetRandomSpawnPosition(
|
||||
edgePadding,
|
||||
heightAboveFloor,
|
||||
out Vector3 position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hasAssignedSpawnPosition.Value = false;
|
||||
assignedSpawnPosition.Value = position;
|
||||
hasAssignedSpawnPosition.Value = true;
|
||||
assignedSceneHandle = scene.handle;
|
||||
}
|
||||
|
||||
private static StartRoomZone FindStartRoomInScene(Scene scene)
|
||||
{
|
||||
foreach (GameObject rootObject in scene.GetRootGameObjects())
|
||||
{
|
||||
StartRoomZone startRoom = rootObject.GetComponentInChildren<StartRoomZone>(true);
|
||||
if (startRoom != null)
|
||||
return startRoom;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void HandleSpawnPositionChanged(Vector3 _, Vector3 position)
|
||||
{
|
||||
if (hasAssignedSpawnPosition.Value)
|
||||
ApplySpawnPosition(position);
|
||||
}
|
||||
|
||||
private void HandleSpawnAssignmentChanged(bool _, bool isAssigned)
|
||||
{
|
||||
if (isAssigned)
|
||||
ApplySpawnPosition(assignedSpawnPosition.Value);
|
||||
}
|
||||
|
||||
private void ApplySpawnPosition(Vector3 position)
|
||||
{
|
||||
if (IsOwner)
|
||||
transform.position = position;
|
||||
if (!IsOwner)
|
||||
return;
|
||||
|
||||
CharacterController characterController = GetComponent<CharacterController>();
|
||||
bool restoreCharacterController = characterController != null && characterController.enabled;
|
||||
|
||||
if (restoreCharacterController)
|
||||
characterController.enabled = false;
|
||||
|
||||
transform.position = position;
|
||||
Physics.SyncTransforms();
|
||||
|
||||
if (restoreCharacterController)
|
||||
characterController.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user