HI
i have create a client/server solution for me with this tutorials
its works good, but the performance are very bad at my extended solution.
The server do “nothing” an take over 50% CPU and with one client i have 100% CPU used.
I am new on Unity/Multiplayer and i speak with one other unity developer an he say i must putout so much things from Update(). I look my code but no ideas what i can do.
Here the code i shorted the code where i think it not needed for better view.
Have you ideas for better performance??
That is my cleint:
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class User
{
public GameObject avatar;
public string visibleClientName;
public int connectionId;
public bool isBusy;
}
public class NET_Client : MonoBehaviour {
public static NET_Client instance;
private int hostId;
private int webHostId;
private int reliableChannel;
private int unreliableChannel;
private int ourClientId;
private int connectionId;
private float connectionTime;
private bool isConnected = false;
private bool isStarted = false;
public bool isCalling = false;
private byte error;
private string playerName;
[Header("Loging Prefab")]
public GameObject playerPrefab;
public GameObject emailImput;
public InputField loginStatus;
//public GameObject login;
public Dictionary<int, User> allUsersDic = new Dictionary<int,User>();
[Header("Connection Settings")]
public string uHostIp;
//private string hostIp = "127.0.0.1";
public int uPort;
//private int port = 5701;
private const int MAX_CONNECTION = 100;
[Header("Debuing Console")]
/// <summary>
/// Debug console to be able to see the unity log on every platform
/// </summary>
public bool uDebugConsole = false;
[Header("Call Prefab")]
public GameObject IncomingCall;
public InputField CalledByName;
private void Start()
{
if (uDebugConsole)
DebugHelper.ActivateConsole();
}
private void Update()
{
if (!isConnected)
return;
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType.DataEvent:
string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize);
Debug.Log("Receving : " + msg);
string[] splitData = msg.Split('|');
switch (splitData[0])
{
case "ASKNAME":
OnAskName(splitData);
break;
case "CNN":
SpawnUser(splitData[1], int.Parse(splitData[2]));
break;
case "WAITCALL":
OnWaitkCall(splitData);
break;
case "BUSY":
OnBusyStatus(splitData);
break;
case "DC":
PlayerDisconnected(int.Parse(splitData[1]));
break;
default:
Debug.Log("Invalid message : " + msg);
break;
}
break;
}
}
public void Connect()
{
//Does the player have a name?
//string pName = GameObject.Find("EmailImput").GetComponent<InputField>().text;
string pName = emailImput.GetComponent<InputField>().text;
if (pName == "")
{
Debug.Log("You must enter your email!");
return;
}
playerName = pName;
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
unreliableChannel = cc.AddChannel(QosType.Unreliable);
HostTopology topo = new HostTopology(cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost(topo, 0);
connectionId = NetworkTransport.Connect(hostId, uHostIp, uPort, 0, out error);
connectionTime = Time.time;
isConnected = true;
// Set the login name on the top InputField
SetLoginStatus();
}
// Show the dictionary from the client. Show the busy status of all users
public void ShowUsersCalling() {...}
// Send request for ask the player there are busy?
public bool AskIsUserBusy(string toAskUser)
{...}
// Look at all user and return true if find the searchUser, then the searchUser is online/connect
public bool AskOnlineUser(string searchUser)
{...}
// Show the login status in the right top corner
private void SetLoginStatus()
{...}
private void OnAskName(string[] data)
{...}
private void SpawnUser(string userName, int cnnId)
{...}
// Open call request to the other player
public void CallByPlayer(InputField calledNameInput)
{...}
// Set the client in isCalling status and seng this status to all users
public void BlockClientForCall()
{...}
// Set the client in not calling status and send this status to all users
public void UnblockedClientFromCall()
{...}
// Open the signal window by the call player
private void OnWaitkCall(string [] splitData)
{...}
private void OnBusyStatus(string[] splitData)
{...}
private void PlayerDisconnected(int cnnId)
{...}
private void Send(string message, int channelId)
{...}
}
That is the server:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
public class ServerClient
{
public static ServerClient instance;
public int connectionId;
public string playerName;
public Vector3 position;
public bool clientIsCalling;
}
public class NET_Server : MonoBehaviour
{
public static NET_Server instance;
private int hostId;
private int webHostId;
private int reliableChannel;
private int unreliableChannel;
private bool isStarted = false;
private byte error;
public List<ServerClient> clients = new List<ServerClient>();
private float lastMovementUpdate;
private float movementUpdateRate = 0.5f;
private const int MAX_CONNECTION = 100;
public int uPort;
//private int port = 5701;
/// <summary>
/// Debug console to be able to see the unity log on every platform
/// </summary>
public bool uDebugConsole = false;
private void Start()
{
if (uDebugConsole)
DebugHelper.ActivateConsole();
NetworkTransport.Init();
ConnectionConfig cc = new ConnectionConfig();
reliableChannel = cc.AddChannel(QosType.Reliable);
unreliableChannel = cc.AddChannel(QosType.Unreliable);
HostTopology topo = new HostTopology(cc, MAX_CONNECTION);
hostId = NetworkTransport.AddHost(topo, uPort, null);
webHostId = NetworkTransport.AddWebsocketHost(topo, uPort, null);
isStarted = true;
Debug.Log("Server is started.");
}
private void Update()
{
if (!isStarted)
return;
int recHostId;
int connectionId;
int channelId;
byte[] recBuffer = new byte[1024];
int bufferSize = 1024;
int dataSize;
byte error;
NetworkEventType recData = NetworkTransport.Receive(out recHostId, out connectionId, out channelId, recBuffer, bufferSize, out dataSize, out error);
switch (recData)
{
case NetworkEventType.ConnectEvent: //2
Debug.Log("Player " + connectionId + " has connected.");
OnConnection(connectionId);
break;
case NetworkEventType.DataEvent: //3
string msg = Encoding.Unicode.GetString(recBuffer, 0, dataSize);
Debug.Log("Receiving from " + connectionId + " : " + msg);
string[] splitData = msg.Split('|');
switch (splitData[0])
{
case "NAMEIS":
OnNameIs(connectionId, splitData[1]);
break;
case "MYPOSITION":
OnMyPosition(connectionId, float.Parse(splitData[1]), float.Parse(splitData[2]));
break;
case "CALL":
CallByPlayer(connectionId, splitData[1], splitData[2]);
break;
case "SENDBUSY":
SendBusy(connectionId, splitData);
break;
default:
Debug.Log("Invalid message : " + msg);
break;
}
break;
case NetworkEventType.DisconnectEvent: //4
Debug.Log("Player " + connectionId + " has disconnected.");
OnDisconnection(connectionId);
break;
}
/***
// It was only for the testing the server at the moment don't needed
// Ask player for ther position
if (Time.time - lastMovementUpdate > movementUpdateRate)
{
lastMovementUpdate = Time.time;
string msg = "ASKPOSITION|";
foreach(ServerClient sc in clients)
msg += sc.connectionId.ToString() + '%' + sc.position.x.ToString() + '%' + sc.position.y.ToString() + '|';
msg = msg.Trim('|');
Send(msg, unreliableChannel, clients);
}
*/
}
private void OnConnection(int cnnId)
{
// Add him to a list
ServerClient c = new ServerClient();
c.connectionId = cnnId;
c.playerName = "Temp";
clients.Add(c);
//Debug.Log("[OnConnection] Client: ID-" + c.connectionId + "; " + c.playerName);
// When the player joins the server, tell him his ID
// Request his name and send the name of the other players
string msg = "ASKNAME|" + cnnId + "|";
foreach (ServerClient sc in clients)
msg += sc.playerName + '%' + sc.connectionId + '|';
msg = msg.Trim('|');
// ASKNAME|3|Dave%1|Michael%2|Temp%3
Send(msg, reliableChannel, cnnId);
}
private void CallByPlayer(int cnnId, string playerName, string callByName)
{...}
// Send all users the user busystatus with the playerName
private void SendBusy(int cnnId, string[] splitData)
{...}
private void OnDisconnection(int cnnId)
{...}
private void OnNameIs(int cnnId, string userName)
{...}
private void OnMyPosition(int cnnId, float x, float y)
{...}
private void Send(string message, int channelId, int cnnId)
{...}
private void Send(string message, int channelId, List<ServerClient> c)
{...}
}