[Add] FishNet
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
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.
|
||||
/// </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>
|
||||
/// Sets the PlayerPrefab to use.
|
||||
/// </summary>
|
||||
/// <param name = "nob"></param>
|
||||
public void SetPlayerPrefab(NetworkObject nob) => _playerPrefab = nob;
|
||||
|
||||
/// <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.")]
|
||||
public Transform[] Spawns = new Transform[0];
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// First instance of the NetworkManager found. This will be either the NetworkManager on or above this object, or InstanceFinder.NetworkManager.
|
||||
/// </summary>
|
||||
private NetworkManager _networkManager;
|
||||
/// <summary>
|
||||
/// Next spawns to use.
|
||||
/// </summary>
|
||||
private int _nextSpawn;
|
||||
#endregion
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
InitializeOnce();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_networkManager != null)
|
||||
_networkManager.SceneManager.OnClientLoadedStartScenes -= SceneManager_OnClientLoadedStartScenes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this script for use.
|
||||
/// </summary>
|
||||
private void InitializeOnce()
|
||||
{
|
||||
_networkManager = GetComponentInParent<NetworkManager>();
|
||||
if (_networkManager == null)
|
||||
_networkManager = InstanceFinder.NetworkManager;
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
_networkManager.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)
|
||||
{
|
||||
_networkManager.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, position, rotation, true);
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 211a9f6ec51ddc14f908f5acc0cd0423
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Generated/Component/Spawning/PlayerSpawner.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,101 @@
|
||||
using FishNet.Managing;
|
||||
using FishNet.Object;
|
||||
using System.Collections.Generic;
|
||||
using FishNet.Managing.Server;
|
||||
using FishNet.Transporting;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Spawning
|
||||
{
|
||||
/// <summary>
|
||||
/// Spawns network objects when the server starts.
|
||||
/// </summary>
|
||||
[AddComponentMenu("FishNet/Component/ServerSpawner")]
|
||||
public class ServerSpawner : MonoBehaviour
|
||||
{
|
||||
#region Serialized
|
||||
[Tooltip("True to spawn the objects as soon as the server starts. False if you wish to call Spawn manually.")]
|
||||
[SerializeField]
|
||||
private bool _automaticallySpawn = true;
|
||||
/// <summary>
|
||||
/// NetworkObjects to spawn when the server starts.
|
||||
/// </summary>
|
||||
[Tooltip("NetworkObjects to spawn when the server starts.")]
|
||||
[SerializeField]
|
||||
private List<NetworkObject> _networkObjects = new();
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// First instance of the ServerManager found. This will be either the ServerManager on or above this object, or InstanceFinder.ServerManager.
|
||||
/// </summary>
|
||||
private ServerManager _serverManager;
|
||||
#endregion
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
InitializeOnce();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_serverManager == null)
|
||||
return;
|
||||
|
||||
// Unsubscribe even if not automatically spawning; this is to protect against the user unchecking during play mode.
|
||||
_serverManager.OnServerConnectionState -= ServerManager_OnServerConnectionState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this script for use.
|
||||
/// </summary>
|
||||
private void InitializeOnce()
|
||||
{
|
||||
_serverManager = GetComponentInParent<ServerManager>();
|
||||
if (_serverManager == null)
|
||||
_serverManager = InstanceFinder.ServerManager;
|
||||
|
||||
if (_serverManager == null)
|
||||
{
|
||||
NetworkManagerExtensions.LogWarning($"{nameof(ServerSpawner)} on {gameObject.name} cannot work as NetworkManager wasn't found on this object or within parent objects.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Only subscribe if to automatically spawn.
|
||||
if (_automaticallySpawn)
|
||||
_serverManager.OnServerConnectionState += ServerManager_OnServerConnectionState;
|
||||
}
|
||||
|
||||
private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs args)
|
||||
{
|
||||
// If not started then exit.
|
||||
if (args.ConnectionState != LocalConnectionState.Started)
|
||||
return;
|
||||
|
||||
// If more than 1 server is started then exit. This means the user is using multipass and another server already started.
|
||||
if (!_serverManager.IsOnlyOneServerStarted())
|
||||
return;
|
||||
|
||||
Spawn_Internally();
|
||||
}
|
||||
|
||||
private void Spawn_Internally()
|
||||
{
|
||||
if (_serverManager == null)
|
||||
return;
|
||||
|
||||
// Spawn the objects now.
|
||||
foreach (NetworkObject networkObject in _networkObjects)
|
||||
{
|
||||
NetworkObject nob = _serverManager.NetworkManager.GetPooledInstantiated(networkObject, asServer: true);
|
||||
_serverManager.Spawn(nob);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns all provided NetworkObjects.
|
||||
/// </summary>
|
||||
/// <remarks>This will spawn the objects again even if they were already spawned automatically or manually before.</remarks>
|
||||
public void Spawn() => Spawn_Internally();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 859294e5d2aaf9a47b1e00bd20772f2b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Generated/Component/Spawning/ServerSpawner.cs
|
||||
uploadId: 866910
|
||||
Reference in New Issue
Block a user