forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			159 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using FishNet.Connection;
 | 
						|
using FishNet.Managing;
 | 
						|
using FishNet.Object;
 | 
						|
using System;
 | 
						|
using UnityEngine;
 | 
						|
using UnityEngine.Serialization;
 | 
						|
 | 
						|
namespace FishNet.Component.Spawning
 | 
						|
{
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Spawns a player object for clients when they connect.
 | 
						|
    /// Must be placed on or beneath the NetworkManager object.
 | 
						|
    /// </summary>
 | 
						|
    [AddComponentMenu("FishNet/Component/PlayerSpawner")]
 | 
						|
    public class PlayerSpawner : MonoBehaviour
 | 
						|
    {
 | 
						|
        #region Public.
 | 
						|
        /// <summary>
 | 
						|
        /// Called on the server when a player is spawned.
 | 
						|
        /// </summary>
 | 
						|
        public event Action<NetworkObject> OnSpawned;
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Serialized.
 | 
						|
        /// <summary>
 | 
						|
        /// Prefab to spawn for the player.
 | 
						|
        /// </summary>
 | 
						|
        [Tooltip("Prefab to spawn for the player.")]
 | 
						|
        [SerializeField]
 | 
						|
        private NetworkObject _playerPrefab;
 | 
						|
        /// <summary>
 | 
						|
        /// True to add player to the active scene when no global scenes are specified through the SceneManager.
 | 
						|
        /// </summary>
 | 
						|
        [Tooltip("True to add player to the active scene when no global scenes are specified through the SceneManager.")]
 | 
						|
        [SerializeField]
 | 
						|
        private bool _addToDefaultScene = true;
 | 
						|
        /// <summary>
 | 
						|
        /// Areas in which players may spawn.
 | 
						|
        /// </summary>
 | 
						|
        [Tooltip("Areas in which players may spawn.")]
 | 
						|
        [FormerlySerializedAs("_spawns")]
 | 
						|
        public Transform[] Spawns = new Transform[0];
 | 
						|
        #endregion
 | 
						|
 | 
						|
        #region Private.
 | 
						|
        /// <summary>
 | 
						|
        /// NetworkManager on this object or within this objects parents.
 | 
						|
        /// </summary>
 | 
						|
        private NetworkManager _networkManager;
 | 
						|
        /// <summary>
 | 
						|
        /// Next spawns to use.
 | 
						|
        /// </summary>
 | 
						|
        private int _nextSpawn;
 | 
						|
        #endregion
 | 
						|
 | 
						|
        private void Start()
 | 
						|
        {
 | 
						|
            InitializeOnce();
 | 
						|
        }
 | 
						|
 | 
						|
        private void OnDestroy()
 | 
						|
        {
 | 
						|
            if (_networkManager != null)
 | 
						|
                _networkManager.SceneManager.OnClientLoadedStartScenes -= SceneManager_OnClientLoadedStartScenes;
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Initializes this script for use.
 | 
						|
        /// </summary>
 | 
						|
        private void InitializeOnce()
 | 
						|
        {
 | 
						|
            _networkManager = InstanceFinder.NetworkManager;
 | 
						|
            if (_networkManager == null)
 | 
						|
            {
 | 
						|
                Debug.LogWarning($"PlayerSpawner on {gameObject.name} cannot work as NetworkManager wasn't found on this object or within parent objects.");
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            _networkManager.SceneManager.OnClientLoadedStartScenes += SceneManager_OnClientLoadedStartScenes;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Called when a client loads initial scenes after connecting.
 | 
						|
        /// </summary>
 | 
						|
        private void SceneManager_OnClientLoadedStartScenes(NetworkConnection conn, bool asServer)
 | 
						|
        {
 | 
						|
            if (!asServer)
 | 
						|
                return;
 | 
						|
            if (_playerPrefab == null)
 | 
						|
            {
 | 
						|
                Debug.LogWarning($"Player prefab is empty and cannot be spawned for connection {conn.ClientId}.");
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            Vector3 position;
 | 
						|
            Quaternion rotation;
 | 
						|
            SetSpawn(_playerPrefab.transform, out position, out rotation);
 | 
						|
 | 
						|
            NetworkObject nob = _networkManager.GetPooledInstantiated(_playerPrefab, true);
 | 
						|
            nob.transform.SetPositionAndRotation(position, rotation);
 | 
						|
            _networkManager.ServerManager.Spawn(nob, conn);
 | 
						|
 | 
						|
            //If there are no global scenes 
 | 
						|
            if (_addToDefaultScene)
 | 
						|
                _networkManager.SceneManager.AddOwnerToDefaultScene(nob);
 | 
						|
 | 
						|
            OnSpawned?.Invoke(nob);
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Sets a spawn position and rotation.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="pos"></param>
 | 
						|
        /// <param name="rot"></param>
 | 
						|
        private void SetSpawn(Transform prefab, out Vector3 pos, out Quaternion rot)
 | 
						|
        {
 | 
						|
            //No spawns specified.
 | 
						|
            if (Spawns.Length == 0)
 | 
						|
            {
 | 
						|
                SetSpawnUsingPrefab(prefab, out pos, out rot);
 | 
						|
                return;
 | 
						|
            }
 | 
						|
 | 
						|
            Transform result = Spawns[_nextSpawn];
 | 
						|
            if (result == null)
 | 
						|
            {
 | 
						|
                SetSpawnUsingPrefab(prefab, out pos, out rot);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                pos = result.position;
 | 
						|
                rot = result.rotation;
 | 
						|
            }
 | 
						|
 | 
						|
            //Increase next spawn and reset if needed.
 | 
						|
            _nextSpawn++;
 | 
						|
            if (_nextSpawn >= Spawns.Length)
 | 
						|
                _nextSpawn = 0;
 | 
						|
        }
 | 
						|
 | 
						|
        /// <summary>
 | 
						|
        /// Sets spawn using values from prefab.
 | 
						|
        /// </summary>
 | 
						|
        /// <param name="prefab"></param>
 | 
						|
        /// <param name="pos"></param>
 | 
						|
        /// <param name="rot"></param>
 | 
						|
        private void SetSpawnUsingPrefab(Transform prefab, out Vector3 pos, out Quaternion rot)
 | 
						|
        {
 | 
						|
            pos = prefab.position;
 | 
						|
            rot = prefab.rotation;
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
} |