I am building a 2d top down multiplayer mmo. very lightweight.
a note on architecture
I am using Unity as an engine, I have a backend Nodejs/socket.io websockets server. and a main Master client that defines what target monsters have, where people and NPCs are positioned in the world and who gets hit by projectiles etc so everyone is in agreement. Thing seem to be working pretty well. But I have thing weird problem where if I have 1 monster it works perfectly. However as I add more monsters to the game messages like for example (Enemy is moving) Get transmitted in the command promt as many times as there are monsters. Whats worse, if I delete those monsters through code (see below) the server still sends messages based on the amount of monsters that ever existed. until I restart the master client and normal client and start over. at which point itll reset everything.
I have been going over my code a great deal and cannot find the problem really. and could use a little help.
server code
// Section for Enemy logic from Master Client
socket.on('enemyRegister', function(data){
// builds a monster on the client
socket.broadcast.emit('enemyRegister', data);
socket.on('enemyMove', function(data){
// moves the monster that matches the given ID
console.log('enemy is moving', data);
socket.broadcast.emit('enemyMove', data);
});
socket.on('enemyStopMove', function(data){
// stops the monster that matches the given ID
console.log('enemy stopped moving', data);
socket.broadcast.emit('enemyStopMove', data);
});
socket.on('enemyTarget', function(data){
// feeds a 'target' data string to the monster that matches the given ID
console.log('setting target', data);
socket.broadcast.emit('enemyTarget', data);
});
socket.on('enemyLoseTarget', function(data){
// remove a 'target' data string to the monster that matches the given ID
console.log('removing target', data);
socket.broadcast.emit('enemyLoseTarget', data);
});
socket.on('enemyShoot', function(data){
// Plays 'shoot' animation on the monster that matches the given ID
console.log('shooting on', data);
socket.broadcast.emit('enemyShoot', data);
});
socket.on('enemyMelee', function(data){
// Plays 'hit' animation on the monster that matches the given ID
console.log('melee hit on', data);
socket.broadcast.emit('enemyMelee', data);
});
socket.on('hitPlayer', function(data){
// Send damage information
var something = players[data.playerId];
console.log('sending info to ', something.socketID);
socket.broadcast.to(something.socketID).emit('hitPlayer', data);
});
socket.on('deleteAllEnemies', function(data){
// Deletes All enemies
console.log('deleting all enemies');
socket.broadcast.emit('deleteAllEnemies');
});
});
Master client enemy creation
void Update () {
if (Input.GetKeyDown("i"))
{
CreateMonster();
}
if (Input.GetKeyDown("o"))
{
foreach(KeyValuePair<string, Vector3> enemy in spawnedEnemies)
{
var thisEnemy = GameObject.Find(enemy.Key);
Destroy(thisEnemy);
}
spawnedEnemies.Clear();
mobNumber = 0;
socket.Emit("deleteAllEnemies");
}
}
void CreateMonster()
{
var selectedSpawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)]; // create a variable,
selectedSpawnPoint.transform.position = new Vector3(Random.Range(0, 10), Random.Range(0,10), 0);
var spawnedEnemy = Instantiate(Enemy[Random.Range(0, Enemy.Length)], selectedSpawnPoint.transform.position, selectedSpawnPoint.transform.rotation);
spawnedEnemy.name = "enemy " + mobNumber;
mobNumber++;
spawnedEnemies.Add(spawnedEnemy.name, spawnedEnemy.transform.position);
numberOfMonsters = spawnedEnemies.Count;
socket.Emit("enemyRegister", Network.MobIdAndLocationToJson(spawnedEnemy.name, spawnedEnemy.transform.position));
}
}
normal client enemy spawning code
public void SpawnEnemy(SocketIOEvent e)
{
var id = e.data["id"].str;
var spawnPosition = new Vector3(e.data["x"].n, e.data["y"].n, 0);
var enemy = Instantiate(orcShaman, spawnPosition, Quaternion.identity) as GameObject;
enemy.name = id;
enemies.Add(id, enemy);
}
code for deleting all enemies on client
public void DeleteAll() // TODO Delete Before Launch
{
foreach (KeyValuePair<string, GameObject> enemy in enemies)
{
var thisEnemy = GameObject.Find(enemy.Key);
Destroy(thisEnemy);
}
enemies.Clear();
}
Any guidance or a push in the right direction would be greatly appreciated im at a loss as to what the issue could be. The server does not store an array of the monsters, only the master client does and the normal client do that. so I dont understand how the server is trying to send information for each monster that has been created. specially when the actions acctually come out correct in game.
thank you for reading.