fishnet installed
This commit is contained in:
@ -0,0 +1,192 @@
|
||||
using FishNet.Managing.Statistic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Add to any object to display current ping(round trip time).
|
||||
/// </summary>
|
||||
[AddComponentMenu("FishNet/Component/BandwidthDisplay")]
|
||||
public class BandwidthDisplay : MonoBehaviour
|
||||
{
|
||||
#region Types.
|
||||
private enum Corner
|
||||
{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Color for text.
|
||||
/// </summary>
|
||||
[Tooltip("Color for text.")]
|
||||
[SerializeField]
|
||||
private Color _color = Color.white;
|
||||
/// <summary>
|
||||
/// Which corner to display network statistics in.
|
||||
/// </summary>
|
||||
[Tooltip("Which corner to display network statistics in.")]
|
||||
[SerializeField]
|
||||
private Corner _placement = Corner.TopRight;
|
||||
/// <summary>
|
||||
/// rue to show outgoing data bytes.
|
||||
/// </summary>
|
||||
[Tooltip("True to show outgoing data bytes.")]
|
||||
[SerializeField]
|
||||
private bool _showOutgoing = true;
|
||||
/// <summary>
|
||||
/// Sets ShowOutgoing value.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetShowOutgoing(bool value) => _showOutgoing = value;
|
||||
/// <summary>
|
||||
/// True to show incoming data bytes.
|
||||
/// </summary>
|
||||
[Tooltip("True to show incoming data bytes.")]
|
||||
[SerializeField]
|
||||
private bool _showIncoming = true;
|
||||
/// <summary>
|
||||
/// Sets ShowIncoming value.
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetShowIncoming(bool value) => _showIncoming = value;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Style for drawn ping.
|
||||
/// </summary>
|
||||
private GUIStyle _style = new GUIStyle();
|
||||
/// <summary>
|
||||
/// Text to show for client in/out data.
|
||||
/// </summary>
|
||||
private string _clientText;
|
||||
/// <summary>
|
||||
/// Text to show for server in/out data.
|
||||
/// </summary>
|
||||
private string _serverText;
|
||||
/// <summary>
|
||||
/// First found NetworkTrafficStatistics.
|
||||
/// </summary>
|
||||
private NetworkTraficStatistics _networkTrafficStatistics;
|
||||
#endregion
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_networkTrafficStatistics = InstanceFinder.NetworkManager.StatisticsManager.NetworkTraffic;
|
||||
//Subscribe to both traffic updates.
|
||||
_networkTrafficStatistics.OnClientNetworkTraffic += NetworkTraffic_OnClientNetworkTraffic;
|
||||
_networkTrafficStatistics.OnServerNetworkTraffic += NetworkTraffic_OnServerNetworkTraffic;
|
||||
|
||||
if (!_networkTrafficStatistics.UpdateClient && !_networkTrafficStatistics.UpdateServer)
|
||||
Debug.LogWarning($"StatisticsManager.NetworkTraffic is not updating for client nor server. To see results ensure your NetworkManager has a StatisticsManager component added with the NetworkTraffic values configured.");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (_networkTrafficStatistics != null)
|
||||
{
|
||||
_networkTrafficStatistics.OnClientNetworkTraffic -= NetworkTraffic_OnClientNetworkTraffic;
|
||||
_networkTrafficStatistics.OnServerNetworkTraffic -= NetworkTraffic_OnClientNetworkTraffic;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Called when client network traffic is updated.
|
||||
/// </summary>
|
||||
private void NetworkTraffic_OnClientNetworkTraffic(NetworkTrafficArgs obj)
|
||||
{
|
||||
string nl = System.Environment.NewLine;
|
||||
string result = string.Empty;
|
||||
if (_showIncoming)
|
||||
result += $"Client In: {NetworkTraficStatistics.FormatBytesToLargest(obj.FromServerBytes)}/s{nl}";
|
||||
if (_showOutgoing)
|
||||
result += $"Client Out: {NetworkTraficStatistics.FormatBytesToLargest(obj.ToServerBytes)}/s{nl}";
|
||||
|
||||
_clientText = result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when client network traffic is updated.
|
||||
/// </summary>
|
||||
private void NetworkTraffic_OnServerNetworkTraffic(NetworkTrafficArgs obj)
|
||||
{
|
||||
string nl = System.Environment.NewLine;
|
||||
string result = string.Empty;
|
||||
if (_showIncoming)
|
||||
result += $"Server In: {NetworkTraficStatistics.FormatBytesToLargest(obj.ToServerBytes)}/s{nl}";
|
||||
if (_showOutgoing)
|
||||
result += $"Server Out: {NetworkTraficStatistics.FormatBytesToLargest(obj.FromServerBytes)}/s{nl}";
|
||||
|
||||
_serverText = result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
//No need to perform these actions on server.
|
||||
#if !UNITY_EDITOR && UNITY_SERVER
|
||||
return;
|
||||
#endif
|
||||
|
||||
_style.normal.textColor = _color;
|
||||
_style.fontSize = 15;
|
||||
|
||||
float width = 100f;
|
||||
float height = 0f;
|
||||
if (_showIncoming)
|
||||
height += 15f;
|
||||
if (_showOutgoing)
|
||||
height += 15f;
|
||||
|
||||
bool isClient = InstanceFinder.IsClient;
|
||||
bool isServer = InstanceFinder.IsServer;
|
||||
if (!isClient)
|
||||
_clientText = string.Empty;
|
||||
if (!isServer)
|
||||
_serverText = string.Empty;
|
||||
if (isServer && isClient)
|
||||
height *= 2f;
|
||||
|
||||
float edge = 10f;
|
||||
|
||||
float horizontal;
|
||||
float vertical;
|
||||
|
||||
if (_placement == Corner.TopLeft)
|
||||
{
|
||||
horizontal = 10f;
|
||||
vertical = 10f;
|
||||
_style.alignment = TextAnchor.UpperLeft;
|
||||
}
|
||||
else if (_placement == Corner.TopRight)
|
||||
{
|
||||
horizontal = Screen.width - width - edge;
|
||||
vertical = 10f;
|
||||
_style.alignment = TextAnchor.UpperRight;
|
||||
}
|
||||
else if (_placement == Corner.BottomLeft)
|
||||
{
|
||||
horizontal = 10f;
|
||||
vertical = Screen.height - height - edge;
|
||||
_style.alignment = TextAnchor.LowerLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
horizontal = Screen.width - width - edge;
|
||||
vertical = Screen.height - height - edge;
|
||||
_style.alignment = TextAnchor.LowerRight;
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(horizontal, vertical, width, height), (_clientText + _serverText), _style);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bc8f0363ddc75946a958043c5e49a83
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,239 @@
|
||||
using FishNet.Connection;
|
||||
using FishNet.Managing;
|
||||
using FishNet.Managing.Logging;
|
||||
using FishNet.Managing.Scened;
|
||||
using FishNet.Transporting;
|
||||
using FishNet.Utility;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnitySceneManager = UnityEngine.SceneManagement.SceneManager;
|
||||
|
||||
/// <summary>
|
||||
/// Add to a NetworkManager object to change between Online and Offline scene based on connection states of the server or client.
|
||||
/// </summary>
|
||||
[AddComponentMenu("FishNet/Component/DefaultScene")]
|
||||
public class DefaultScene : MonoBehaviour
|
||||
{
|
||||
|
||||
#region Serialized.
|
||||
[Tooltip("True to load the online scene as global, false to load it as connection.")]
|
||||
[SerializeField]
|
||||
private bool _useGlobalScenes = true;
|
||||
/// <summary>
|
||||
/// True to replace all scenes with the offline scene immediately.
|
||||
/// </summary>
|
||||
[Tooltip("True to replace all scenes with the offline scene immediately.")]
|
||||
[SerializeField]
|
||||
private bool _startInOffline;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Tooltip("Scene to load when disconnected. Server and client will load this scene.")]
|
||||
[SerializeField, Scene]
|
||||
private string _offlineScene;
|
||||
/// <summary>
|
||||
/// Sets which offline scene to use.
|
||||
/// </summary>
|
||||
/// <param name="sceneName">Scene name to use as the offline scene.</param>
|
||||
public void SetOfflineScene(string sceneName) => _offlineScene = sceneName;
|
||||
/// <summary>
|
||||
/// Scene to load when disconnected. Server and client will load this scene.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetOfflineScene() => _offlineScene;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Tooltip("Scene to load when connected. Server and client will load this scene.")]
|
||||
[SerializeField, Scene]
|
||||
private string _onlineScene;
|
||||
/// <summary>
|
||||
/// Sets which online scene to use.
|
||||
/// </summary>
|
||||
/// <param name="sceneName">Scene name to use as the online scene.</param>
|
||||
public void SetOnlineScene(string sceneName) => _onlineScene = sceneName;
|
||||
/// <summary>
|
||||
/// Scene to load when connected. Server and client will load this scene.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetOnlineScene() => _onlineScene;
|
||||
/// <summary>
|
||||
/// Which scenes to replace when loading into OnlineScene.
|
||||
/// </summary>
|
||||
[Tooltip("Which scenes to replace when loading into OnlineScene.")]
|
||||
[SerializeField]
|
||||
private ReplaceOption _replaceScenes = ReplaceOption.All;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// NetworkManager for this component.
|
||||
/// </summary>
|
||||
private NetworkManager _networkManager;
|
||||
#endregion
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
InitializeOnce();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
|
||||
if (!ApplicationState.IsQuitting() && _networkManager != null && _networkManager.Initialized)
|
||||
{
|
||||
_networkManager.ClientManager.OnClientConnectionState -= ClientManager_OnClientConnectionState;
|
||||
_networkManager.ServerManager.OnServerConnectionState -= ServerManager_OnServerConnectionState;
|
||||
_networkManager.SceneManager.OnLoadEnd -= SceneManager_OnLoadEnd;
|
||||
_networkManager.ServerManager.OnAuthenticationResult -= ServerManager_OnAuthenticationResult;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this script for use.
|
||||
/// </summary>
|
||||
private void InitializeOnce()
|
||||
{
|
||||
_networkManager = GetComponentInParent<NetworkManager>();
|
||||
if (_networkManager == null)
|
||||
{
|
||||
|
||||
NetworkManager.StaticLogError($"NetworkManager not found on {gameObject.name} or any parent objects. DefaultScene will not work.");
|
||||
return;
|
||||
}
|
||||
//A NetworkManager won't be initialized if it's being destroyed.
|
||||
if (!_networkManager.Initialized)
|
||||
return;
|
||||
if (_onlineScene == string.Empty || _offlineScene == string.Empty)
|
||||
{
|
||||
|
||||
NetworkManager.StaticLogWarning("Online or Offline scene is not specified. Default scenes will not load.");
|
||||
return;
|
||||
}
|
||||
|
||||
_networkManager.ClientManager.OnClientConnectionState += ClientManager_OnClientConnectionState;
|
||||
_networkManager.ServerManager.OnServerConnectionState += ServerManager_OnServerConnectionState;
|
||||
_networkManager.SceneManager.OnLoadEnd += SceneManager_OnLoadEnd;
|
||||
_networkManager.ServerManager.OnAuthenticationResult += ServerManager_OnAuthenticationResult;
|
||||
if (_startInOffline)
|
||||
LoadOfflineScene();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a scene load ends.
|
||||
/// </summary>
|
||||
private void SceneManager_OnLoadEnd(SceneLoadEndEventArgs obj)
|
||||
{
|
||||
bool onlineLoaded = false;
|
||||
foreach (Scene s in obj.LoadedScenes)
|
||||
{
|
||||
if (s.name == GetSceneName(_onlineScene))
|
||||
{
|
||||
onlineLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//If online scene was loaded then unload offline.
|
||||
if (onlineLoaded)
|
||||
UnloadOfflineScene();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after the local server connection state changes.
|
||||
/// </summary>
|
||||
private void ServerManager_OnServerConnectionState(ServerConnectionStateArgs obj)
|
||||
{
|
||||
/* When server starts load online scene as global.
|
||||
* Since this is a global scene clients will automatically
|
||||
* join it when connecting. */
|
||||
if (obj.ConnectionState == LocalConnectionState.Started)
|
||||
{
|
||||
/* If not exactly one server is started then
|
||||
* that means either none are started, which isnt true because
|
||||
* we just got a started callback, or two+ are started.
|
||||
* When a server has already started there's no reason to load
|
||||
* scenes again. */
|
||||
if (!_networkManager.ServerManager.OneServerStarted())
|
||||
return;
|
||||
|
||||
//If here can load scene.
|
||||
SceneLoadData sld = new SceneLoadData(GetSceneName(_onlineScene));
|
||||
sld.ReplaceScenes = _replaceScenes;
|
||||
if (_useGlobalScenes)
|
||||
_networkManager.SceneManager.LoadGlobalScenes(sld);
|
||||
else
|
||||
_networkManager.SceneManager.LoadConnectionScenes(sld);
|
||||
}
|
||||
//When server stops load offline scene.
|
||||
else if (obj.ConnectionState == LocalConnectionState.Stopped)
|
||||
{
|
||||
LoadOfflineScene();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after the local client connection state changes.
|
||||
/// </summary>
|
||||
private void ClientManager_OnClientConnectionState(ClientConnectionStateArgs obj)
|
||||
{
|
||||
if (obj.ConnectionState == LocalConnectionState.Stopped)
|
||||
{
|
||||
//Only load offline scene if not also server.
|
||||
if (!_networkManager.IsServer)
|
||||
LoadOfflineScene();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a client completes authentication.
|
||||
/// </summary>
|
||||
private void ServerManager_OnAuthenticationResult(NetworkConnection arg1, bool authenticated)
|
||||
{
|
||||
/* This is only for loading connection scenes.
|
||||
* If using global there is no need to continue. */
|
||||
if (_useGlobalScenes)
|
||||
return;
|
||||
if (!authenticated)
|
||||
return;
|
||||
|
||||
SceneLoadData sld = new SceneLoadData(GetSceneName(_onlineScene));
|
||||
_networkManager.SceneManager.LoadConnectionScenes(arg1, sld);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Loads offlineScene as single.
|
||||
/// </summary>
|
||||
private void LoadOfflineScene()
|
||||
{
|
||||
//Already in offline scene.
|
||||
if (UnitySceneManager.GetActiveScene().name == GetSceneName(_offlineScene))
|
||||
return;
|
||||
//Only use scene manager if networking scenes. I may add something in later to do both local and networked.
|
||||
UnitySceneManager.LoadScene(_offlineScene);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unloads the offline scene.
|
||||
/// </summary>
|
||||
private void UnloadOfflineScene()
|
||||
{
|
||||
Scene s = UnitySceneManager.GetSceneByName(GetSceneName(_offlineScene));
|
||||
if (string.IsNullOrEmpty(s.name))
|
||||
return;
|
||||
|
||||
UnitySceneManager.UnloadSceneAsync(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a scene name from fullPath.
|
||||
/// </summary>
|
||||
/// <param name="fullPath"></param>
|
||||
/// <returns></returns>
|
||||
private string GetSceneName(string fullPath)
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(fullPath);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57ce8bbb58966cb45a7140f32da5327a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,118 @@
|
||||
using FishNet.Managing.Timing;
|
||||
using UnityEngine;
|
||||
|
||||
namespace FishNet.Component.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Add to any object to display current ping(round trip time).
|
||||
/// </summary>
|
||||
[AddComponentMenu("FishNet/Component/PingDisplay")]
|
||||
public class PingDisplay : MonoBehaviour
|
||||
{
|
||||
#region Types.
|
||||
private enum Corner
|
||||
{
|
||||
TopLeft,
|
||||
TopRight,
|
||||
BottomLeft,
|
||||
BottomRight
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Color for text.
|
||||
/// </summary>
|
||||
[Tooltip("Color for text.")]
|
||||
[SerializeField]
|
||||
private Color _color = Color.white;
|
||||
/// <summary>
|
||||
/// Which corner to display ping in.
|
||||
/// </summary>
|
||||
[Tooltip("Which corner to display ping in.")]
|
||||
[SerializeField]
|
||||
private Corner _placement = Corner.TopRight;
|
||||
/// <summary>
|
||||
/// True to show the real ping. False to include tick rate latency within the ping.
|
||||
/// </summary>
|
||||
[Tooltip("True to show the real ping. False to include tick rate latency within the ping.")]
|
||||
[SerializeField]
|
||||
private bool _hideTickRate = true;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Style for drawn ping.
|
||||
/// </summary>
|
||||
private GUIStyle _style = new GUIStyle();
|
||||
#endregion
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
//No need to perform these actions on server.
|
||||
#if !UNITY_EDITOR && UNITY_SERVER
|
||||
return;
|
||||
#endif
|
||||
|
||||
//Only clients can see pings.
|
||||
if (!InstanceFinder.IsClient)
|
||||
return;
|
||||
|
||||
_style.normal.textColor = _color;
|
||||
_style.fontSize = 15;
|
||||
float width = 85f;
|
||||
float height = 15f;
|
||||
float edge = 10f;
|
||||
|
||||
float horizontal;
|
||||
float vertical;
|
||||
|
||||
if (_placement == Corner.TopLeft)
|
||||
{
|
||||
horizontal = 10f;
|
||||
vertical = 10f;
|
||||
}
|
||||
else if (_placement == Corner.TopRight)
|
||||
{
|
||||
horizontal = Screen.width - width - edge;
|
||||
vertical = 10f;
|
||||
}
|
||||
else if (_placement == Corner.BottomLeft)
|
||||
{
|
||||
horizontal = 10f;
|
||||
vertical = Screen.height - height - edge;
|
||||
}
|
||||
else
|
||||
{
|
||||
horizontal = Screen.width - width - edge;
|
||||
vertical = Screen.height - height - edge;
|
||||
}
|
||||
|
||||
long ping;
|
||||
TimeManager tm = InstanceFinder.TimeManager;
|
||||
if (tm == null)
|
||||
{
|
||||
ping = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ping = tm.RoundTripTime;
|
||||
long deduction = 0;
|
||||
if (_hideTickRate)
|
||||
{
|
||||
deduction = (long)(tm.TickDelta * 1000d);
|
||||
/* If host subtract two ticks, if client only subtract one tick.
|
||||
* This will reflect the users real ping without the tick rate latency. */
|
||||
if (InstanceFinder.IsHost)
|
||||
deduction *= 2;
|
||||
}
|
||||
|
||||
ping = (long)Mathf.Max(0, ping - deduction);
|
||||
}
|
||||
|
||||
GUI.Label(new Rect(horizontal, vertical, width, height), $"Ping: {ping}ms", _style);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9b6b565cd9533c4ebc18003f0fc18a2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: bf9191e2e07d29749bca3a1ae44e4bc8, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user