okay so i have a game, all i want to do is sync the position. it will have one map loaded at a time, and to syncronize the position of the player on the map
currently i am only worried about working with TWO players, not really MMO, but its a start
okay so i have written my own networking code for the client and the server. i know it may not be very secure, but its a start. anyways.
when i play locally i get NO lag. when i have a remote player playing, his game lags like mad, but locally, it does not.
i was thinking it was my code but then again, i cannot figure out why it is lagging for him.
everything works, and works like this
client sends awake command
server checks if user exists, if does not, adds to list, either way, send play players ID number
on a timer, the client will send a command saying SETPOSITION to update the players position on the server
every remote player on the client, his script on the client, calls for a GETPOSITION command on the server, the server sends back the position set by set position. this is called every x seconds on the client from the remote controlelr script
everything works, when i play locally there is no lag. there server seems to receiving the remote players commands super slow. i changed the timers to send really fast, changed the times i sleep in between commands to really small intervals.
still locally it received data much faster, i completley understand why, but my server is getting the player updates very slowly.
i also am running a timer to update the active player list incase i need to instantiate a remote player and his model. i set this on a longer running timer, every 5 seconds.
the server is receiving the data one after anotjer,
GETPLAYERLIST
SETPOSITION
GETPOSITION (for each player)
with out fail, though timers are set to different times.
here is the remote controller script :
using UnityEngine;
using System.Collections;
public class MyRemoteController : MonoBehaviour {
private NetworkManager networkManager;
public string playerName = "My Player";
// Remote players position and rotation
public Vector3 MyPos;
public Quaternion MyRot;
private const string NETWORK_MANAGER = "Network Manager";
private float playerUpdateTimer = 0.0f;
private float playerStartTimer = 0.0f;
public float playerResetTimer = 1000.0f;
// Use this for initialization
void Start () {
// Find the network manager
networkManager = GameObject.FindGameObjectWithTag(NETWORK_MANAGER).GetComponent<NetworkManager>();
if (networkManager == null)
Debug.LogError("Cannot find the Network Manager!");
}
// Update is called once per frame
void Update () {
// Get data from server on this mobs position, on a timer
if (playerUpdateTimer <= playerResetTimer)
{
char[] delimiterChars = { '|' };
string loc = networkManager.SendGetLocation(name);
string[] position = loc.Split(delimiterChars);
int i = 0;
foreach (string word in position)
{
if (word != "GETLOCATION")
{
float myword = (float)System.Convert.ToSingle(word);
if (i==1)
MyPos.x = myword;
else if (i==2)
MyPos.y = myword;
else if (i==3)
MyPos.z = myword;
else if (i==4)
MyRot.x = myword;
else if (i==5)
MyRot.y = myword;
else if (i==6)
MyRot.x = myword;
}
i++;
}
playerUpdateTimer = 0.0f;
playerStartTimer = Time.time;
}
else // Update Timer
{
playerUpdateTimer = Time.time - playerStartTimer;
}
// IS the player moving? if he is..
if (PlayerIsMoving())
{
// Animate Moving
animation.CrossFade("run");
// Move - // GET THE REMOTE PLAYER INDEX AND ITS LOCATION POSITION
// AT ITS INDEX
transform.position = MyPos;
transform.rotation = MyRot;
}
// If he isnt moving
else
{
// Animate Idle
animation.CrossFade("idle");
}
}
// Has player changed location in X seconds
// TODO
public bool PlayerIsMoving () {
if (true)
return true;
else
return false;
}
}
here is the networjing engine i designed for the client
using UnityEngine;
using System.Collections;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System;
using System.Text;
public class NetworkManager : MonoBehaviour {
private GameManager gm;
public string ServerAddress = "127.0.0.1";
public int ServerPort = 3000;
public int ThreadSleepTime = 12;
private TcpClient client;
private IPEndPoint serverEndPoint;
private NetworkStream clientStream;
private const string GAME_MANAGER = "Game Manager";
// Use this for initialization
void Start () {
// Find the game manager
gm = GameObject.FindGameObjectWithTag(GAME_MANAGER).GetComponent<GameManager>();
if (gm == null)
Debug.LogError("Cannot find the Game Manager!");
// Create our client, endpoint, and then connect
client = new TcpClient();
serverEndPoint = new IPEndPoint(IPAddress.Parse(ServerAddress), ServerPort);
client.Connect(serverEndPoint);
// Setup our stream..
clientStream = client.GetStream();
}
// Update is called once per frame
void Update () {
}
// Close the connection
public void CloseConnection (){
client.Close();
}
// Send Data to server
public void SendDataToServer (string MyString){
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(MyString);
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
}
// Send the Awake Command
// Return True if we successfully connect
public bool SendServerAwake (){
try {
MyPlayerController MYPC = gm.GetPlayerController().GetComponent<MyPlayerController>();
string MyString = "AWAKE" + MYPC.playerName +"@";
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(MyString);
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
Thread.Sleep(ThreadSleepTime);
// Wait for the player list return
byte[] message = new byte[4096];
int bytesRead;
bytesRead = 0;
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
//message has successfully been received
MyString = encoder.GetString(message, 0, bytesRead);
char[] delimiterChars = { '|' };
string[] players = MyString.Split(delimiterChars);
MYPC.myPlayerIndex = System.Convert.ToInt32(players[1]);
return true;
}
catch {
return false;
}
}
// Send the Get Player List Command
public string SendGetPlayerList (){
string MyString = "GETPLAYERLIST@";
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(MyString);
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
// Wait for the player list return
byte[] message = new byte[4096];
int bytesRead;
bytesRead = 0;
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
//message has successfully been received
MyString = encoder.GetString(message, 0, bytesRead);
Thread.Sleep(ThreadSleepTime);
return MyString; // Return the player list
}
// Send the Get Player Location Command
public string SendGetLocation (string playerName){
string MyString = "GETLOCATION" + playerName +"@";
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(MyString);
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
// Wait for the player list return
byte[] message = new byte[4096];
int bytesRead;
bytesRead = 0;
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
//message has successfully been received
MyString = "";
MyString = encoder.GetString(message, 0, bytesRead);
Thread.Sleep(ThreadSleepTime);
return MyString; // Return the player list
}
// Send the Set Player Position Command
// Return True if we successfully send
public bool SendServerLocation (){
try {
MyPlayerController MYPC = gm.GetPlayerController().GetComponent<MyPlayerController>();
string MyString = "SETLOCATION" + MYPC.playerName + "|" + MYPC.transform.position.x + "|" + MYPC.transform.position.y + "|" + MYPC.transform.position.z
+ "|" + MYPC.transform.rotation.x + "|" + MYPC.transform.rotation.y + "|" + MYPC.transform.rotation.z +"@";
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(MyString);
clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();
Thread.Sleep(ThreadSleepTime);;
return true;
}
catch {
return false;
}
}
}
and here is the class i designed, a multi threaded server in c#
using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Collections.Generic;
namespace EuphonicServer
{
class MyServer
{
private TcpListener tcpListener;
private Thread listenThread;
private IPEndPoint serverEndPoint;
List<string> playerlist = new List<string>();
List<string> playerlocation = new List<string>();
public MyServer()
{
this.tcpListener = new TcpListener(IPAddress.Any,3000);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
//blocks until a client has connected to the server
TcpClient client = this.tcpListener.AcceptTcpClient();
//create a thread to handle communication
//with connected client
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private void HandleClientComm(object client)
{
TcpClient tcpClient = (TcpClient)client;
NetworkStream clientStream = tcpClient.GetStream();
byte[] message = new byte[4096];
int bytesRead;
while (tcpClient.Connected)
{
bytesRead = 0;
try
{
//blocks until a client sends a message
bytesRead = clientStream.Read(message, 0, 4096);
}
catch
{
//a socket error has occured
break;
}
if (bytesRead == 0)
{
//the client has disconnected from the server
break;
}
//message has successfully been received
ASCIIEncoding encoder = new ASCIIEncoding();
string TheString = encoder.GetString(message, 0, bytesRead);
// Incase we received more that we are supposed to, check
char[] delimiterCharz = { '@' };
string[] positions = TheString.Split(delimiterCharz);
string MyString = positions[0];
/// PLAYER AWAKE FUNCTION
/// ---------------------
/// Add the player to the game world
if (MyString.Substring(0, 5) == "AWAKE")
{
// Remove Protocol String, MyString will now contain argument
MyString = MyString.Replace("AWAKE", "");
bool playerExists = false;
int i = 0;
/* Is the player already in the game world and get the index */
foreach (string player in playerlist)
{
if (player == MyString){
playerExists = true;
break;
}
else
i++;
}
// add player to the game world
if (!playerExists)
{
playerlist.Add(MyString);
playerlocation.Add("0|0|0|0|0|0");
i++;
}
// Send the player the players index
byte[] buffer = encoder.GetBytes("AWAKE|" + i);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.WriteLine("AWAKE: " + MyString);
}
/// GET PLAYER LIST
/// ---------------
/// Send the client the current player list
else if (MyString.Substring(0, 13) == "GETPLAYERLIST")
{
string plist = "GETPLAYERLIST";
// Build a player list string
foreach (string player in playerlist)
{
plist = plist + "|" + player;
}
// Send the player list string we have built
byte[] buffer = encoder.GetBytes(plist);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.WriteLine(plist);
}
/// GET PLAYER LOCATION
/// ---------------
/// Send the client the requested players location
else if (MyString.Substring(0, 11) == "GETLOCATION")
{
// Remove Protocol String, MyString will now contain argument
MyString = MyString.Replace("GETLOCATION", "");
// Construct the player location string
string plist = "GETLOCATION";
int i = 0;
foreach (string player in playerlist)
{
if (player == MyString)
plist = plist + "|" + playerlocation[i];
i++;
}
// Send the player list string we have built
byte[] buffer = encoder.GetBytes(plist);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
Console.WriteLine(MyString + ": " + plist);
}
/// SET PLAYER LOCATION
/// ---------------
/// Set the requested players position
else if (MyString.Substring(0, 11) == "SETLOCATION")
{
// Remove Protocol String, MyString will now contain argument
MyString = MyString.Replace("SETLOCATION", "");
char[] delimiterChars = { '|' };
string[] position = MyString.Split(delimiterChars);
string myname = position[0];
string myposx = position[1];
string myposy = position[2];
string myposz = position[3];
string myrotx = position[4];
string myroty = position[5];
string myrotz = position[6];
// Set the players location
int i = 0;
foreach (string player in playerlist)
{
if (player == myname)
playerlocation[i] = myposx + "|" + myposy + "|" + myposz + "|" +myrotx + "|" + myroty + "|" + myrotz ;
i++;
}
Console.WriteLine("SETLOCATION: " + MyString);
}
}
Console.WriteLine("Client Disconnected");
tcpClient.Close();
}
}
}
my connection is fast enough to run apache and server websites with ease. why is my server getting this informaton so slowly? what can i do to prevent this lag?