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:
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
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a helper script for quick prototyping, used to start Netick.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Game Starter")]
|
||||
public class GameStarter : NetworkEventsListener
|
||||
/// <summary>
|
||||
/// This is a helper script for quick prototyping, used to start Netick.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Game Starter")]
|
||||
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;
|
||||
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()
|
||||
{
|
||||
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);
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"name": "Netick.Samples",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:32b718c5820ccce438606ca82358f1da"
|
||||
"GUID:84651a3751eca9349aac36a66bba901b",
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@@ -5,91 +5,91 @@ using Network = Netick.Unity.Network;
|
||||
|
||||
namespace Netick.Samples
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a helper script for quick prototyping, used to show useful network information of Netick.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Network Info")]
|
||||
public class NetworkInfo : NetworkEventsListener
|
||||
{
|
||||
[Header("Network Stats")]
|
||||
public Vector2 Offset = new Vector2(27, 20);
|
||||
/// <summary>
|
||||
/// This is a helper script for quick prototyping, used to show useful network information of Netick.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Network Info")]
|
||||
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;
|
||||
[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;
|
||||
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 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 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,37 +5,37 @@ using Network = Netick.Unity.Network;
|
||||
|
||||
namespace Netick.Samples
|
||||
{
|
||||
/// <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.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Player Spawner")]
|
||||
public class PlayerSpawner : NetworkEventsListener
|
||||
/// <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.
|
||||
/// </summary>
|
||||
[AddComponentMenu("Netick/Player Spawner")]
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user