Files
2026-06-07 16:58:24 +01:00

93 lines
3.4 KiB
C#

using UnityEngine;
using VRC.SDKBase;
namespace VRC.SDK3.ClientSim
{
/// <summary>
/// System that handles spawning new players for ClientSim.
/// New players will then be initialized through the PlayerManager.
/// </summary>
[AddComponentMenu("")]
public class ClientSimPlayerSpawner : ClientSimBehaviour
{
[SerializeField]
private GameObject localPlayerPrefab;
[SerializeField]
private GameObject remotePlayerPrefab;
private IClientSimSceneManager _sceneManager;
private IClientSimPlayerManager _playerManager;
private IClientSimBlacklistManager _blacklistManager;
private IClientSimEventDispatcher _eventDispatcher;
private Transform _parent;
public void Initialize(
IClientSimSceneManager sceneManager,
IClientSimPlayerManager playerManager,
IClientSimBlacklistManager blacklistManager,
IClientSimEventDispatcher eventDispatcher,
Transform parent)
{
_sceneManager = sceneManager;
_playerManager = playerManager;
_blacklistManager = blacklistManager;
_eventDispatcher = eventDispatcher;
_parent = parent;
}
public static Vector3 GetRandomPositionAroundSpawn(Vector3 spawnPosition, float radius)
{
Vector2 randomPosition = Random.insideUnitCircle * radius;
return new Vector3(randomPosition.x + spawnPosition.x, spawnPosition.y, randomPosition.y + spawnPosition.z);
}
public ClientSimPlayer SpawnPlayer(string playerName, bool isLocal)
{
if (!_sceneManager.HasSceneDescriptor())
{
throw new ClientSimException("Cannot spawn player if there is no world descriptor!");
}
GameObject playerPrefab = isLocal ? localPlayerPrefab : remotePlayerPrefab;
if (playerPrefab == null)
{
throw new ClientSimException("Failed to spawn player! Player prefab was not found.");
}
Transform spawn = _sceneManager.GetSpawnPoint(!isLocal);
float radius = _sceneManager.GetSpawnRadius();
Vector3 position = GetRandomPositionAroundSpawn(spawn.position, radius);
Quaternion rotation = Quaternion.Euler(0, spawn.rotation.eulerAngles.y, 0);
GameObject playerInstance = Instantiate(playerPrefab, position, rotation, _parent);
if (_parent == null)
{
DontDestroyOnLoad(playerInstance);
}
_blacklistManager.AddObjectAndChildrenToBlackList(playerInstance);
ClientSimPlayer player = playerInstance.GetComponent<ClientSimPlayer>();
if (player == null)
{
throw new ClientSimException("Failed to spawn player! ClientSimPlayer script was not found.");
}
// PlayerManager will automatically handle sending player join event
_playerManager.CreateNewPlayer(isLocal, player, playerName);
if (isLocal)
{
// Disable player controller until ClientSim is initialized, which is when the player should be able to gain control.
playerInstance.SetActive(false);
}
player.SetEventDispatcher(_eventDispatcher);
return player;
}
}
}