0
\$\begingroup\$

I am building a 2d top-down mmo. very lightweight.

I have a master client that determines everythings position, and actions and send this information to all other clients.

Now I have made a great deal of different solutions to movement of my NPCs across the network and some solutions are better than others but noone have been perfect. So I would love some feedback on this.

Master client sends information to server:

 void Start () {
    InvokeRepeating("CheckForMove", 1.0f, 1f);
 }
    void CheckForMove()
{
    var distance = Vector3.Distance(lastPos, transform.position);
    if (distance > 0.02)  // Dont send information if movement is very small i.e bumping into a wall repeatedly etc
    {
        socket.Emit("enemyMove", Network.MobIdAndLocationToJson(gameObject.name, transform.position));
        moveEmit = true;
        lastPos = transform.position;
        spawnScript.spawnedEnemies[gameObject.name] = transform.position;
    }
}

Server reveives the information:

   socket.on('enemyMove', function(data){

        // moves the monster that matches the given ID

        console.log('enemy is moving', data);

    socket.broadcast.emit('enemyMove', data);

    });

Player Clients receive the move information:

    private void OnEnemyMove(SocketIOEvent e)
{
        var position = new Vector3(e.data["x"].n, e.data["y"].n, -0.5f);
        var enemy = enemySpawner.FindEnemy(e.data["id"].str);
        var enemyNavigator = enemy.GetComponent<EnemyNavigator>();
        enemyNavigator.MoveThisEnemy(position);
}

now the question becomes what is the best way to go from here to smooth this movement best I can?

The solutions I have tried are as follows:

------------------ solution 1 ----------------------

    public void MoveThisEnemy(Vector3 position)
{
    anim.SetBool("walk", true);

    startTime = Time.time;
    DistanceToDest = Vector3.Distance(transform.position, position);

    destPos = position;
    isMoving = true;
}

and in update:

if (isMoving)
    {
        if (currentTarget != null)
        {
            float currentDuration = Time.time - startTime;
            float journeyFraction = currentDuration / totalDistanceToDestination;
            transform.position = Vector3.Lerp(transform.position, destPos, journeyFraction);
        }

although this works fine the NPcs movement is wonky as in it finishes its movement faster than the next update can come no matter what and therefore although lerping it seems to move faster than I can provide it with updates. imagine a cartoon slug that moves fast, stops, moves again, stops. so Npc is always there and not just teleporting but still not the effect I am looking for.

------------------ solution 2 ----------------------

Here I simply try to just reproduce on the player client what I am doing on the master client but I make sure to correct the position of the NPC ever so often to guarantee its in the correct position.

    public void MoveThisEnemy(Vector3 position)
{
    anim.SetBool("walk", true);
    transform.position = position;
    isMoving = true;
}

and in update:

       if (isMoving)
    {
        if (currentTarget != null)
        {
        var targetDistance = Vector3.Distance(transform.position, currentTarget.transform.position);

        if (targetDistance > minDist)
        {
        Vector3 direction = (currentTarget.transform.position - transform.position).normalized;
        rigid.MovePosition(transform.position + direction * speed * Time.deltaTime);
        }
     }

this is actually a very good solution as I can get the position correct with minimal amounts of data sent over the network. but since I have obstacles in my game it gets very weird as moving the NPCs transform doesnt include collisions and it can perform weird movements when colliding. Furthermore it seems to teleport to its position because of the transform.position updates when playing in full screen. barely visible in smaller resolution for some reason.

I have also tried using rigidbody.moveposition in the MoveThisEnemy function but this just means it doesnt get updated correctly as moveposition seems to be less precise than transform.position.

any feedback would be greatly appreciated.

thank you.

\$\endgroup\$
0
\$\begingroup\$

First of all, I might missunderstanded your question but it looks like your clients are updating the mobs position, this shouldn't happen. Game logic should be managed by the master server for several reasons from security (dont trust the client, ever) to math consistency (diferent platforms, different float precision)

About the smooth movement, a widely used approach is using movement prediction, checkpoints and interpolation.

Movement prediction

If object A that is in P point moves in V direction at S speed, you know that, in 10 frames, that object A will be 10*S units from P in V direction.

Knowing this, you can say from your server to your clients to move #12742 mob in (0.3, 1, 0.1) direction at speed 3 until point X is reached (f.e.), then, your clients can predict and update the position based on the server input.

Checkpoints

Your mob moves dumbly for a given values from server, but if your server keep sending position and movement updates every server tick the client can update the position and the movement stuff with the correct one.

Interpolation

This could lead to bumping, to fix it, you want to artificially lag a little the game and interpolate the position and movement between the last two recieved updates, by doing this and averaging with the last updates (and taking latency in mind) you can achieve smooth movement.

\$\endgroup\$
  • \$\begingroup\$ Hi and thanks for your input. In solution 1, I dont think I am allowing clients to determine NPC movement. all they are doing is positioning the NPC based on the information sent from the master client through the server. I understand that I could make player movement is a similar way by sending the "I am pressing down the move right key" to the master client and then simply have the server determine where they actually are in the world and then update it once they stop moving makeing the server authorative. I need a way to update the client with some smoothe movement for the NPCs. \$\endgroup\$ – Svp May 26 '17 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.