mirror of
https://github.com/Kaveinator/NetickProForUnity.git
synced 2025-10-26 09:49:06 -07:00
Added support for custom scene handling, in addition to an addressable scene handler.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
166
Scripts/AddressableSceneHandler.cs
Normal file
166
Scripts/AddressableSceneHandler.cs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.AddressableAssets;
|
||||||
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||||
|
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||||
|
using UnityEngine;
|
||||||
|
using Netick.Unity;
|
||||||
|
|
||||||
|
namespace Netick.Samples
|
||||||
|
{
|
||||||
|
[AddComponentMenu("Netick/Addressable Scene Handler")]
|
||||||
|
public class AddressableSceneHandler : NetworkSceneHandler
|
||||||
|
{
|
||||||
|
private class AddressableSceneOperation : ISceneOperation
|
||||||
|
{
|
||||||
|
AsyncOperationHandle<SceneInstance> Handle;
|
||||||
|
bool ISceneOperation.IsDone => Handle.IsDone;
|
||||||
|
float ISceneOperation.Progress => Handle.PercentComplete;
|
||||||
|
public AddressableSceneOperation(AsyncOperationHandle<SceneInstance> handle)
|
||||||
|
{
|
||||||
|
Handle = handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] AddressableScenes = new string[0];
|
||||||
|
public override int CustomScenesCount => AddressableScenes != null ? AddressableScenes.Length : 0;
|
||||||
|
|
||||||
|
private Dictionary<string, int> _keyToIndex;
|
||||||
|
private Dictionary<int, string> _indexToKey;
|
||||||
|
private Dictionary<Scene, SceneInstance> _loadedScenes;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
_keyToIndex = new(AddressableScenes.Length);
|
||||||
|
_indexToKey = new(AddressableScenes.Length);
|
||||||
|
_loadedScenes = new(AddressableScenes.Length);
|
||||||
|
|
||||||
|
for (int i = 0; i < AddressableScenes.Length; i++)
|
||||||
|
{
|
||||||
|
_keyToIndex.Add(AddressableScenes[i], i);
|
||||||
|
_indexToKey.Add(i, AddressableScenes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ISceneOperation LoadCustomSceneAsync(int index, LoadSceneParameters loadSceneParameters, out string sceneName)
|
||||||
|
{
|
||||||
|
var key = _indexToKey[index];
|
||||||
|
sceneName = key;
|
||||||
|
|
||||||
|
var handle = Addressables.LoadSceneAsync(key, loadSceneParameters);
|
||||||
|
handle.Completed += handle =>
|
||||||
|
{
|
||||||
|
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||||
|
_loadedScenes.Add(handle.Result.Scene, handle.Result);
|
||||||
|
else
|
||||||
|
Sandbox.LogError($"Addressables.LoadSceneAsync: failed to load an addressable scene {handle.DebugName}");
|
||||||
|
};
|
||||||
|
|
||||||
|
return new AddressableSceneOperation(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ISceneOperation UnloadCustomSceneAsync(Scene scene)
|
||||||
|
{
|
||||||
|
var didGetSceneInstance = _loadedScenes.TryGetValue(scene, out var sceneInstance);
|
||||||
|
|
||||||
|
if (!didGetSceneInstance || !scene.IsValid())
|
||||||
|
{
|
||||||
|
Sandbox.LogError($"Unloading scene: couldn't find a scene to unload {scene.name}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var handle = Addressables.UnloadSceneAsync(sceneInstance);
|
||||||
|
handle.Completed += handle =>
|
||||||
|
{
|
||||||
|
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||||
|
_loadedScenes.Remove(handle.Result.Scene);
|
||||||
|
else
|
||||||
|
Sandbox.LogError($"Addressables.UnloadSceneAsync: failed to unload scene {scene.name}");
|
||||||
|
};
|
||||||
|
|
||||||
|
return new AddressableSceneOperation(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Addressable Scenes
|
||||||
|
public void LoadAddressableSceneAsync(string key, LoadSceneMode loadSceneMode)
|
||||||
|
{
|
||||||
|
if (_keyToIndex.TryGetValue(key, out int customIndex))
|
||||||
|
Sandbox.LoadCustomSceneAsync(customIndex, new LoadSceneParameters(loadSceneMode, Sandbox.GetDefaultPhysicsMode()));
|
||||||
|
else
|
||||||
|
Sandbox.LogError("Loading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadAddressableSceneAsync(string key, LoadSceneParameters loadSceneParameters)
|
||||||
|
{
|
||||||
|
if (_keyToIndex.TryGetValue(key, out int customIndex))
|
||||||
|
Sandbox.LoadCustomSceneAsync(customIndex, loadSceneParameters);
|
||||||
|
else
|
||||||
|
Sandbox.LogError("Loading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnloadAddressableSceneAsync(string key)
|
||||||
|
{
|
||||||
|
if (_keyToIndex.TryGetValue(key, out int customIndex))
|
||||||
|
Sandbox.UnloadSceneAsync(customIndex);
|
||||||
|
else
|
||||||
|
Sandbox.LogError("Unloading scene: failed to find the addressable scene key in the AddressableScenes array. Make sure to add all scenes keys to the array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnloadAddressableSceneAsync(Scene scene)
|
||||||
|
{
|
||||||
|
Sandbox.UnloadSceneAsync(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- Build Scenes
|
||||||
|
// NetworkSceneHandler already implements exactly the code shown here, the reason we still included it in here is for demonstration purposes.
|
||||||
|
protected override AsyncOperation LoadBuildSceneAsync(int buildIndex, LoadSceneParameters loadSceneParameters) => SceneManager.LoadSceneAsync(buildIndex, loadSceneParameters);
|
||||||
|
protected override AsyncOperation UnloadBuildSceneAsync(Scene scene) => SceneManager.UnloadSceneAsync(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AddressableSceneHandlerSandboxExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <i><b>[Server Only]</b></i> Loads an addressable scene asynchronously using a key.
|
||||||
|
/// </summary>
|
||||||
|
public static void LoadAddressableSceneAsync(this NetworkSandbox sandbox, string key, LoadSceneMode loadSceneMode)
|
||||||
|
{
|
||||||
|
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
|
||||||
|
defaultSceneHandler.LoadAddressableSceneAsync(key, loadSceneMode);
|
||||||
|
else
|
||||||
|
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <i><b>[Server Only]</b></i> Loads an addressable scene asynchronously using a key.
|
||||||
|
/// </summary>
|
||||||
|
public static void LoadAddressableSceneAsync(this NetworkSandbox sandbox, string key, LoadSceneParameters loadSceneParameters)
|
||||||
|
{
|
||||||
|
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
|
||||||
|
defaultSceneHandler.LoadAddressableSceneAsync(key, loadSceneParameters);
|
||||||
|
else
|
||||||
|
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <i><b>[Server Only]</b></i> Unloads an addressable scene asynchronously using a key.
|
||||||
|
/// </summary>
|
||||||
|
public static void UnloadAddressableSceneAsync(this NetworkSandbox sandbox, string key)
|
||||||
|
{
|
||||||
|
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
|
||||||
|
defaultSceneHandler.UnloadAddressableSceneAsync(key);
|
||||||
|
else
|
||||||
|
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <i><b>[Server Only]</b></i> Unloads an addressable scene asynchronously using a Scene struct.
|
||||||
|
/// </summary>
|
||||||
|
public static void UnloadAddressableSceneAsync(this NetworkSandbox sandbox, Scene scene)
|
||||||
|
{
|
||||||
|
if (sandbox.TryGetComponent<AddressableSceneHandler>(out var defaultSceneHandler))
|
||||||
|
defaultSceneHandler.UnloadAddressableSceneAsync(scene);
|
||||||
|
else
|
||||||
|
sandbox.LogError($"{nameof(AddressableSceneHandler)} is not added to the sandbox. Make sure to add {nameof(AddressableSceneHandler)} to your sandbox prefab.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Scripts/AddressableSceneHandler.cs.meta
Normal file
11
Scripts/AddressableSceneHandler.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 02be3a9e2ac6d2c45a70578c62ae81d1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -5,141 +5,141 @@ using Network = Netick.Unity.Network;
|
|||||||
|
|
||||||
namespace Netick.Samples
|
namespace Netick.Samples
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a helper script for quick prototyping, used to start Netick.
|
/// This is a helper script for quick prototyping, used to start Netick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AddComponentMenu("Netick/Game Starter")]
|
[AddComponentMenu("Netick/Game Starter")]
|
||||||
public class GameStarter : NetworkEventsListener
|
public class GameStarter : NetworkEventsListener
|
||||||
|
{
|
||||||
|
public GameObject SandboxPrefab;
|
||||||
|
public NetworkTransportProvider Transport;
|
||||||
|
public StartMode Mode = StartMode.MultiplePeers;
|
||||||
|
[Range(1, 5)]
|
||||||
|
public int Clients = 1;
|
||||||
|
public bool StartServerInMultiplePeersMode = true;
|
||||||
|
|
||||||
|
public bool AutoStart;
|
||||||
|
public bool AutoConnect;
|
||||||
|
|
||||||
|
[Header("Network")]
|
||||||
|
[Range(0, 65535)]
|
||||||
|
public int Port;
|
||||||
|
public string ServerIPAddress = "127.0.0.1";
|
||||||
|
|
||||||
|
[Header("Headless Server FPS")]
|
||||||
|
public bool Cap = true;
|
||||||
|
public int FPS = 450;
|
||||||
|
|
||||||
|
[Header("UI")]
|
||||||
|
public bool ShowDisconnectButton = true;
|
||||||
|
public bool ShowConnectButton = true;
|
||||||
|
public Vector2 Offset = new Vector2(36, 0);
|
||||||
|
|
||||||
|
private void Reset()
|
||||||
{
|
{
|
||||||
public GameObject SandboxPrefab;
|
if (Port == 0)
|
||||||
public NetworkTransportProvider Transport;
|
Port = Random.Range(4000, 65535);
|
||||||
public StartMode Mode = StartMode.MultiplePeers;
|
|
||||||
[Range(1, 5)]
|
|
||||||
public int Clients = 1;
|
|
||||||
public bool StartServerInMultiplePeersMode = true;
|
|
||||||
|
|
||||||
public bool AutoStart;
|
|
||||||
public bool AutoConnect;
|
|
||||||
|
|
||||||
[Header("Network")]
|
|
||||||
[Range(0, 65535)]
|
|
||||||
public int Port;
|
|
||||||
public string ServerIPAddress = "127.0.0.1";
|
|
||||||
|
|
||||||
[Header("Headless Server FPS")]
|
|
||||||
public bool Cap = true;
|
|
||||||
public int FPS = 450;
|
|
||||||
|
|
||||||
[Header("UI")]
|
|
||||||
public bool ShowDisconnectButton = true;
|
|
||||||
public bool ShowConnectButton = true;
|
|
||||||
public Vector2 Offset = new Vector2(36, 0);
|
|
||||||
|
|
||||||
private void Reset()
|
|
||||||
{
|
|
||||||
if (Port == 0)
|
|
||||||
Port = Random.Range(4000, 65535);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
if (Application.isBatchMode)
|
|
||||||
{
|
|
||||||
Application.targetFrameRate = FPS;
|
|
||||||
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (AutoStart)
|
|
||||||
{
|
|
||||||
if (Network.Instance == null)
|
|
||||||
{
|
|
||||||
switch (Mode)
|
|
||||||
{
|
|
||||||
case StartMode.Server:
|
|
||||||
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
|
||||||
break;
|
|
||||||
case StartMode.Client:
|
|
||||||
Network.StartAsClient(Transport, Port, SandboxPrefab).Connect(Port, ServerIPAddress);
|
|
||||||
break;
|
|
||||||
case StartMode.MultiplePeers:
|
|
||||||
var sandboxes = Network.StartAsMultiplePeers(Transport, Port, SandboxPrefab, StartServerInMultiplePeersMode, true, Clients);
|
|
||||||
|
|
||||||
if (AutoConnect)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sandboxes.Clients.Length; i++)
|
|
||||||
sandboxes.Clients[i].Connect(Port, ServerIPAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
if (Network.IsRunning)
|
|
||||||
{
|
|
||||||
if (Sandbox != null && Sandbox.IsClient)
|
|
||||||
{
|
|
||||||
if (!Sandbox.IsVisible)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Sandbox.IsConnected)
|
|
||||||
{
|
|
||||||
if (ShowDisconnectButton)
|
|
||||||
{
|
|
||||||
GUI.Label(new Rect(Offset.x, Offset.y + 170, 200, 50), $"Connected to {Sandbox.ServerEndPoint}");
|
|
||||||
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 220, 200, 50), "Disconnect"))
|
|
||||||
Sandbox.DisconnectFromServer();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (ShowConnectButton)
|
|
||||||
{
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 40, 200, 50), "Connect"))
|
|
||||||
Sandbox.Connect(Port, ServerIPAddress);
|
|
||||||
|
|
||||||
ServerIPAddress = GUI.TextField(new Rect(Offset.x, Offset.y + 100, 200, 50), ServerIPAddress);
|
|
||||||
Port = int.Parse(GUI.TextField(new Rect(Offset.x, Offset.y+ 160, 200, 50), Port.ToString()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 40, 200, 50), "Run Host"))
|
|
||||||
{
|
|
||||||
Network.StartAsHost(Transport, Port, SandboxPrefab);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 100, 200, 50), "Run Client"))
|
|
||||||
{
|
|
||||||
var sandbox = Network.StartAsClient(Transport, Port, SandboxPrefab);
|
|
||||||
sandbox.Connect(Port, ServerIPAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 160, 200, 50), "Run Server"))
|
|
||||||
{
|
|
||||||
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.Button(new Rect(Offset.x, Offset.y + 220, 200, 50), "Run Host + Client"))
|
|
||||||
{
|
|
||||||
var sandboxes = Network.StartAsMultiplePeers(Transport, Port, SandboxPrefab, StartServerInMultiplePeersMode, true, Clients);
|
|
||||||
|
|
||||||
if (AutoConnect)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Clients; i++)
|
|
||||||
sandboxes.Clients[i].Connect(Port, ServerIPAddress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerIPAddress = GUI.TextField(new Rect(Offset.x, Offset.y + 280, 200, 50), ServerIPAddress);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
|
{
|
||||||
|
if (Application.isBatchMode)
|
||||||
|
{
|
||||||
|
Application.targetFrameRate = FPS;
|
||||||
|
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (AutoStart)
|
||||||
|
{
|
||||||
|
if (Network.Instance == null)
|
||||||
|
{
|
||||||
|
switch (Mode)
|
||||||
|
{
|
||||||
|
case StartMode.Server:
|
||||||
|
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
||||||
|
break;
|
||||||
|
case StartMode.Client:
|
||||||
|
Network.StartAsClient(Transport, Port, SandboxPrefab).Connect(Port, ServerIPAddress);
|
||||||
|
break;
|
||||||
|
case StartMode.MultiplePeers:
|
||||||
|
var sandboxes = Network.StartAsMultiplePeers(Transport, Port, SandboxPrefab, StartServerInMultiplePeersMode, true, Clients);
|
||||||
|
|
||||||
|
if (AutoConnect)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sandboxes.Clients.Length; i++)
|
||||||
|
sandboxes.Clients[i].Connect(Port, ServerIPAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
if (Network.IsRunning)
|
||||||
|
{
|
||||||
|
if (Sandbox != null && Sandbox.IsClient)
|
||||||
|
{
|
||||||
|
if (!Sandbox.IsVisible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Sandbox.IsConnected)
|
||||||
|
{
|
||||||
|
if (ShowDisconnectButton)
|
||||||
|
{
|
||||||
|
GUI.Label(new Rect(Offset.x, Offset.y + 170, 200, 50), $"Connected to {Sandbox.ServerEndPoint}");
|
||||||
|
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 220, 200, 50), "Disconnect"))
|
||||||
|
Sandbox.DisconnectFromServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ShowConnectButton)
|
||||||
|
{
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 40, 200, 50), "Connect"))
|
||||||
|
Sandbox.Connect(Port, ServerIPAddress);
|
||||||
|
|
||||||
|
ServerIPAddress = GUI.TextField(new Rect(Offset.x, Offset.y + 100, 200, 50), ServerIPAddress);
|
||||||
|
Port = int.Parse(GUI.TextField(new Rect(Offset.x, Offset.y + 160, 200, 50), Port.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 40, 200, 50), "Run Host"))
|
||||||
|
{
|
||||||
|
Network.StartAsHost(Transport, Port, SandboxPrefab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 100, 200, 50), "Run Client"))
|
||||||
|
{
|
||||||
|
var sandbox = Network.StartAsClient(Transport, Port, SandboxPrefab);
|
||||||
|
sandbox.Connect(Port, ServerIPAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 160, 200, 50), "Run Server"))
|
||||||
|
{
|
||||||
|
Network.StartAsServer(Transport, Port, SandboxPrefab);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GUI.Button(new Rect(Offset.x, Offset.y + 220, 200, 50), "Run Host + Client"))
|
||||||
|
{
|
||||||
|
var sandboxes = Network.StartAsMultiplePeers(Transport, Port, SandboxPrefab, StartServerInMultiplePeersMode, true, Clients);
|
||||||
|
|
||||||
|
if (AutoConnect)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Clients; i++)
|
||||||
|
sandboxes.Clients[i].Connect(Port, ServerIPAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerIPAddress = GUI.TextField(new Rect(Offset.x, Offset.y + 280, 200, 50), ServerIPAddress);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "Netick.Samples",
|
"name": "Netick.Samples",
|
||||||
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:32b718c5820ccce438606ca82358f1da"
|
"GUID:84651a3751eca9349aac36a66bba901b",
|
||||||
|
"GUID:9e24947de15b9834991c9d8411ea37cf"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
|||||||
@@ -5,91 +5,91 @@ using Network = Netick.Unity.Network;
|
|||||||
|
|
||||||
namespace Netick.Samples
|
namespace Netick.Samples
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a helper script for quick prototyping, used to show useful network information of Netick.
|
/// This is a helper script for quick prototyping, used to show useful network information of Netick.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AddComponentMenu("Netick/Network Info")]
|
[AddComponentMenu("Netick/Network Info")]
|
||||||
public class NetworkInfo : NetworkEventsListener
|
public class NetworkInfo : NetworkEventsListener
|
||||||
|
{
|
||||||
|
[Header("Network Stats")]
|
||||||
|
public Vector2 Offset = new Vector2(27, 20);
|
||||||
|
|
||||||
|
[Header("Network Conditions Icons")]
|
||||||
|
public float MediumLatencyThreshold = 150;
|
||||||
|
public float HighLatencyThreshold = 250;
|
||||||
|
public float MediumPacketLossThreshold = 1;
|
||||||
|
public float HighPacketLossThreshold = 10;
|
||||||
|
|
||||||
|
public Vector2 PacketLossIconOffset = new Vector2(-80, 30);
|
||||||
|
public Vector2 LatencyIconOffset = new Vector2(-80, 70);
|
||||||
|
public Vector2 ServerLagIconOffset = new Vector2(-80, 110);
|
||||||
|
public float IconSize = 30;
|
||||||
|
|
||||||
|
private Texture _packetLossIcon;
|
||||||
|
private Texture _latencyIcon;
|
||||||
|
private Texture _serverLagIcon;
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
{
|
{
|
||||||
[Header("Network Stats")]
|
_packetLossIcon = Resources.Load<Texture>("Network Icons/PacketLoss");
|
||||||
public Vector2 Offset = new Vector2(27, 20);
|
_latencyIcon = Resources.Load<Texture>("Network Icons/Latency");
|
||||||
|
_serverLagIcon = Resources.Load<Texture>("Network Icons/ServerLag");
|
||||||
[Header("Network Conditions Icons")]
|
|
||||||
public float MediumLatencyThreshold = 150;
|
|
||||||
public float HighLatencyThreshold = 250;
|
|
||||||
public float MediumPacketLossThreshold = 1;
|
|
||||||
public float HighPacketLossThreshold = 10;
|
|
||||||
|
|
||||||
public Vector2 PacketLossIconOffset = new Vector2(-80, 30);
|
|
||||||
public Vector2 LatencyIconOffset = new Vector2(-80, 70);
|
|
||||||
public Vector2 ServerLagIconOffset = new Vector2(-80, 110);
|
|
||||||
public float IconSize = 30;
|
|
||||||
|
|
||||||
private Texture _packetLossIcon;
|
|
||||||
private Texture _latencyIcon;
|
|
||||||
private Texture _serverLagIcon;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_packetLossIcon = Resources.Load<Texture>("Network Icons/PacketLoss");
|
|
||||||
_latencyIcon = Resources.Load<Texture>("Network Icons/Latency");
|
|
||||||
_serverLagIcon = Resources.Load<Texture>("Network Icons/ServerLag");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnGUI()
|
|
||||||
{
|
|
||||||
if (Network.IsRunning)
|
|
||||||
{
|
|
||||||
if (Sandbox != null && Sandbox.IsConnected && Sandbox.IsVisible)
|
|
||||||
{
|
|
||||||
DrawText(0, "RTT", (Sandbox.RTT * 1000f).ToString(), "ms");
|
|
||||||
DrawText(1, "In", Sandbox.InKBps.ToString(), "KB/s");
|
|
||||||
DrawText(2, "Out", Sandbox.OutKBps.ToString(), "KB/s");
|
|
||||||
DrawText(3, "In Loss", (Sandbox.InPacketLoss * 100f).ToString(), "%");
|
|
||||||
DrawText(4, "Out Loss", (Sandbox.OutPacketLoss * 100f).ToString(), "%");
|
|
||||||
DrawText(5, "Interp Delay", (Sandbox.InterpolationDelay * 1000f).ToString(), "ms");
|
|
||||||
DrawText(6, "Resims", Sandbox.Monitor.Resimulations.Average.ToString(), "Ticks");
|
|
||||||
DrawText(7, "Srv Tick Time", (Sandbox.Monitor.ServerTickTime.Max * 1000f).ToString(), "ms");
|
|
||||||
DrawText(8, "Delta time", (Time.deltaTime * 1000f).ToString(), "ms");
|
|
||||||
|
|
||||||
DrawIcons();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawText(int offset, string title, string content, string unit)
|
|
||||||
{
|
|
||||||
GUI.Label(new Rect(Offset.x + 10, Offset.y + 10 + (15 * offset), 200, 50), $"{title}: ");
|
|
||||||
GUI.Label(new Rect(Offset.x + 130, Offset.y + 10 + (15 * offset), 200, 50), $"{content} {unit}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DrawIcons()
|
|
||||||
{
|
|
||||||
var pktLossIconPos = PacketLossIconOffset + (Screen.width * Vector2.right);
|
|
||||||
var latencyIconPos = LatencyIconOffset + (Screen.width * Vector2.right);
|
|
||||||
var serverLagIconPos = ServerLagIconOffset + (Screen.width * Vector2.right);
|
|
||||||
|
|
||||||
var pktLoss = Mathf.Max(Sandbox.InPacketLoss, Sandbox.OutPacketLoss) * 100; // multiplying by 100 to convert from a decimal to a percentage.
|
|
||||||
var rtt = Sandbox.RTT * 1000f; // multiplying by 1000 to convert from seconds to milliseconds.
|
|
||||||
|
|
||||||
if (pktLoss >= MediumPacketLossThreshold)
|
|
||||||
{
|
|
||||||
Color color = pktLoss < HighPacketLossThreshold ? Color.yellow : Color.red;
|
|
||||||
GUI.DrawTexture(new Rect(pktLossIconPos, Vector2.one * IconSize), _packetLossIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rtt >= MediumLatencyThreshold)
|
|
||||||
{
|
|
||||||
Color color = rtt >= HighLatencyThreshold ? Color.red : Color.yellow;
|
|
||||||
GUI.DrawTexture(new Rect(latencyIconPos, Vector2.one * IconSize), _latencyIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Sandbox.Monitor.ServerTickTime.Max >= Sandbox.FixedDeltaTime)
|
|
||||||
{
|
|
||||||
Color color = Sandbox.Monitor.ServerTickTime.Average >= Sandbox.FixedDeltaTime ? Color.red : Color.yellow;
|
|
||||||
GUI.DrawTexture(new Rect(serverLagIconPos, Vector2.one * IconSize), _serverLagIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnGUI()
|
||||||
|
{
|
||||||
|
if (Network.IsRunning)
|
||||||
|
{
|
||||||
|
if (Sandbox != null && Sandbox.IsConnected && Sandbox.IsVisible)
|
||||||
|
{
|
||||||
|
DrawText(0, "RTT", (Sandbox.RTT * 1000f).ToString(), "ms");
|
||||||
|
DrawText(1, "In", Sandbox.InKBps.ToString(), "KB/s");
|
||||||
|
DrawText(2, "Out", Sandbox.OutKBps.ToString(), "KB/s");
|
||||||
|
DrawText(3, "In Loss", (Sandbox.InPacketLoss * 100f).ToString(), "%");
|
||||||
|
DrawText(4, "Out Loss", (Sandbox.OutPacketLoss * 100f).ToString(), "%");
|
||||||
|
DrawText(5, "Interp Delay", (Sandbox.InterpolationDelay * 1000f).ToString(), "ms");
|
||||||
|
DrawText(6, "Resims", Sandbox.Monitor.Resimulations.Average.ToString(), "ticks");
|
||||||
|
DrawText(7, "Srv Tick Time", (Sandbox.Monitor.ServerTickTime.Max * 1000f).ToString(), "ms");
|
||||||
|
DrawText(8, "Delta time", (Time.deltaTime * 1000f).ToString(), "ms");
|
||||||
|
|
||||||
|
DrawIcons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawText(int offset, string title, string content, string unit)
|
||||||
|
{
|
||||||
|
GUI.Label(new Rect(Offset.x + 10, Offset.y + 10 + (15 * offset), 200, 50), $"{title}: ");
|
||||||
|
GUI.Label(new Rect(Offset.x + 130, Offset.y + 10 + (15 * offset), 200, 50), $"{content} {unit}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawIcons()
|
||||||
|
{
|
||||||
|
var pktLossIconPos = PacketLossIconOffset + (Screen.width * Vector2.right);
|
||||||
|
var latencyIconPos = LatencyIconOffset + (Screen.width * Vector2.right);
|
||||||
|
var serverLagIconPos = ServerLagIconOffset + (Screen.width * Vector2.right);
|
||||||
|
|
||||||
|
var pktLoss = Mathf.Max(Sandbox.InPacketLoss, Sandbox.OutPacketLoss) * 100; // multiplying by 100 to convert from a decimal to a percentage.
|
||||||
|
var rtt = Sandbox.RTT * 1000f; // multiplying by 1000 to convert from seconds to milliseconds.
|
||||||
|
|
||||||
|
if (pktLoss >= MediumPacketLossThreshold)
|
||||||
|
{
|
||||||
|
Color color = pktLoss < HighPacketLossThreshold ? Color.yellow : Color.red;
|
||||||
|
GUI.DrawTexture(new Rect(pktLossIconPos, Vector2.one * IconSize), _packetLossIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtt >= MediumLatencyThreshold)
|
||||||
|
{
|
||||||
|
Color color = rtt >= HighLatencyThreshold ? Color.red : Color.yellow;
|
||||||
|
GUI.DrawTexture(new Rect(latencyIconPos, Vector2.one * IconSize), _latencyIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Sandbox.Monitor.ServerTickTime.Max >= Sandbox.FixedDeltaTime)
|
||||||
|
{
|
||||||
|
Color color = Sandbox.Monitor.ServerTickTime.Average >= Sandbox.FixedDeltaTime ? Color.red : Color.yellow;
|
||||||
|
GUI.DrawTexture(new Rect(serverLagIconPos, Vector2.one * IconSize), _serverLagIcon, ScaleMode.ScaleToFit, true, 1f, color, 0f, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,37 +5,37 @@ using Network = Netick.Unity.Network;
|
|||||||
|
|
||||||
namespace Netick.Samples
|
namespace Netick.Samples
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a helper script for quick prototyping, used to spawn/despawn a player prefab when a player (client or host) has connected/disconnected.
|
/// This is a helper script for quick prototyping, used to spawn/despawn a player prefab when a player (client or host) has connected/disconnected.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AddComponentMenu("Netick/Player Spawner")]
|
[AddComponentMenu("Netick/Player Spawner")]
|
||||||
public class PlayerSpawner : NetworkEventsListener
|
public class PlayerSpawner : NetworkEventsListener
|
||||||
|
{
|
||||||
|
public GameObject PlayerPrefab;
|
||||||
|
public Transform SpawnPosition;
|
||||||
|
public float HorizontalOffset = 5f;
|
||||||
|
public bool StaggerSpawns = true;
|
||||||
|
public bool DestroyPlayerObjectWhenLeaving = true;
|
||||||
|
|
||||||
|
// This is called on the server when a player has connected.
|
||||||
|
public override void OnPlayerConnected(NetworkSandbox sandbox, Netick.NetworkPlayer client)
|
||||||
{
|
{
|
||||||
public GameObject PlayerPrefab;
|
var spawnPos = SpawnPosition.position;
|
||||||
public Transform SpawnPosition;
|
if (StaggerSpawns)
|
||||||
public float HorizontalOffset = 5f;
|
spawnPos += (HorizontalOffset * Vector3.left) * (sandbox.ConnectedPlayers.Count - 1);
|
||||||
public bool StaggerSpawns = true;
|
var player = sandbox.NetworkInstantiate(PlayerPrefab, spawnPos, SpawnPosition.rotation, client);
|
||||||
public bool DestroyPlayerObjectWhenLeaving = true;
|
client.PlayerObject = player;
|
||||||
|
|
||||||
// This is called on the server when a player has connected.
|
|
||||||
public override void OnPlayerConnected(NetworkSandbox sandbox, Netick.NetworkPlayer client)
|
|
||||||
{
|
|
||||||
var spawnPos = SpawnPosition.position;
|
|
||||||
if (StaggerSpawns)
|
|
||||||
spawnPos += (HorizontalOffset * Vector3.left) * (sandbox.ConnectedPlayers.Count - 1);
|
|
||||||
var player = sandbox.NetworkInstantiate(PlayerPrefab, spawnPos, SpawnPosition.rotation, client);
|
|
||||||
client.PlayerObject = player;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is called on the server when a player has disconnected.
|
|
||||||
public override void OnPlayerDisconnected(NetworkSandbox sandbox, Netick.NetworkPlayer client, TransportDisconnectReason transportDisconnectReason)
|
|
||||||
{
|
|
||||||
if (!DestroyPlayerObjectWhenLeaving)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var netObj = client.PlayerObject as NetworkObject;
|
|
||||||
if (netObj != null)
|
|
||||||
Sandbox.Destroy(netObj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called on the server when a player has disconnected.
|
||||||
|
public override void OnPlayerDisconnected(NetworkSandbox sandbox, Netick.NetworkPlayer client, TransportDisconnectReason transportDisconnectReason)
|
||||||
|
{
|
||||||
|
if (!DestroyPlayerObjectWhenLeaving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var netObj = client.PlayerObject as NetworkObject;
|
||||||
|
if (netObj != null)
|
||||||
|
Sandbox.Destroy(netObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "com.karrar.netick",
|
"name": "com.karrar.netick",
|
||||||
"version": "0.13.21",
|
"version": "0.13.24",
|
||||||
"displayName": "Netick",
|
"displayName": "Netick",
|
||||||
"description": "A networking solution for Unity",
|
"description": "A networking solution for Unity",
|
||||||
"unity": "2021.3",
|
"unity": "2021.3",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"com.unity.nuget.mono-cecil": "1.11.4"
|
"com.unity.nuget.mono-cecil": "1.11.4",
|
||||||
|
"com.unity.addressables": "1.22.3"
|
||||||
},
|
},
|
||||||
"documentationUrl": "https://www.netick.net/docs.html",
|
"documentationUrl": "https://www.netick.net/docs.html",
|
||||||
"samples": [
|
"samples": [
|
||||||
|
|||||||
Reference in New Issue
Block a user