Multiplayer Rotation and Animation help

Hi I am new and creating a multiplayer game. I forked the tutorial (could not get it to work without forking) and change it. I am trying to add it so “Other” has animation and Rotate to face different directions but I can’t seem to get it to work

Link >>> PlayCanvas 3D HTML5 Game Engine

Sever link >>> Glitch :・゚✧

Hello @Coder ,
You have forgot to update the updatePosition() function in network.js. It seems to not send the data.rot variable you are looking for. You also need to incorporate the data.rot variable into the movePlayer() function. as for animation, you’d probably need to send out the “state” that is happening as a string and play the animation on the other entity in the client side in code.

1 Like

Have not done the animation yet but i change what you said and it gives me the error

ReferenceError: data is not defined
at scriptType.Network.updatePosition (https://launch.playcanvas.com/api/assets/files/scripts/network.js?id=54058590&branchId=16d42686-bd2f-4abe-b2db-17257d4259d8:107:37)
at scriptType.Network.update (https://launch.playcanvas.com/api/assets/files/scripts/network.js?id=54058590&branchId=16d42686-bd2f-4abe-b2db-17257d4259d8:101:10)
at ScriptComponent._scriptMethod (https://code.playcanvas.com/playcanvas-stable.dbg.js:63497:19)
at ScriptComponent._onUpdate (https://code.playcanvas.com/playcanvas-stable.dbg.js:63545:11)
at ScriptComponentSystem._callComponentMethod (https://code.playcanvas.com/playcanvas-stable.dbg.js:64111:49)
at ScriptComponentSystem._onUpdate (https://code.playcanvas.com/playcanvas-stable.dbg.js:64128:9)
at Function._helper (https://code.playcanvas.com/playcanvas-stable.dbg.js:43302:12)
at Function.update (https://code.playcanvas.com/playcanvas-stable.dbg.js:43317:9)
at Application.update (https://code.playcanvas.com/playcanvas-stable.dbg.js:70447:20)
at https://code.playcanvas.com/playcanvas-stable.dbg.js:71152:16

Edit: If I delete the addons it works normally with out rotation

Hey @Coder, how did you try to send the data.rot variable? It seems from the error that data is not defined in the context that you have tried to call it in. Can you please send the script where you are trying to do this? It’ll help us find the issue a lot better.

Here

var Network = pc.createScript('network');

Network.attributes.add('playerEntity', { type: 'entity' });


// static variables
Network.id = null;
Network.socket = null;

// initialize code called once per entity
Network.prototype.initialize = function() {
    this.player = this.app.root.findByName('Player');
    this.other = this.app.root.findByName('Other');

    var socket = io.connect('https://relmsever.glitch.me'); // Glitch hosted server
    Network.socket = socket;
    
    socket.emit ('initialize');
    
    var onPlayerMove = function(direction) {
        console.log(direction);
    };

    // listen for the player:move event
    this.app.on('player:move', onPlayerMove);

    // remove player:move event listeners when script destroyed
    this.on('destroy', function() {
        this.app.off('player:move', onPlayerMove);
    });

    
    var self = this;
    socket.on ('playerData', function (data) {
        self.initializePlayers (data);
    });

    socket.on ('playerJoined', function (data) {
        self.addPlayer(data);
    });

    socket.on ('playerMoved', function (data) {
        self.movePlayer(data);
    });

    socket.on ('killPlayer', function (data) {
        self.removePlayer(data);
    });
    
};

Network.prototype.initializePlayers = function (data) {
    this.players = data.players;
    Network.id = data.id;

    for(var id in this.players){
        if(id != Network.id){
            this.players[id].entity = this.createPlayerEntity(this.players[id]);
        }
    }
    

    this.initialized = true;
    console.log('initialized');
};

Network.prototype.addPlayer = function (data) {
    this.players[data.id] = data;
    this.players[data.id].entity = this.createPlayerEntity(data);
};

Network.prototype.movePlayer = function (data) {
    if (this.initialized && !this.players[data.id].deleted) {
        this.players[data.id].entity.rigidbody.teleport(data.x, data.y, data.z);
        this.players[data.id].entity.findByName("Model").setLocalEulerAngles(0, data.rot + 180, 0);
    }
};

Network.prototype.removePlayer = function (data) {
    if (this.players[data].entity) {
        this.players[data].entity.destroy ();
        this.players[data].deleted = true;
    }
};

Network.prototype.createPlayerEntity = function (data) {
    var newPlayer = this.other.clone();
    newPlayer.enabled = true;

    this.other.getParent().addChild(newPlayer);

    if (data)
        newPlayer.rigidbody.teleport(data.x, data.y, data.z);
        newPlayer.findByName("Model").setLocalEulerAngles(0, data.rot + 180, 0);

    return newPlayer;
};

// update code called every frame
Network.prototype.update = function(dt) {
    this.updatePosition();
};

Network.prototype.updatePosition = function () {
    if (this.initialized) {    
        var pos = this.player.getPosition();
        var rotation = this.players[data.id].entity.findByName("Model").getEulerAngles().x;
        Network.socket.emit('positionUpdate', {id: Network.id, x: pos.x, y: pos.y, z: pos.z, rot: rotation});
    }
};

I assume you’re getting the error here -

var rotation = this.players[data.id].entity.findByName("Model").getEulerAngles().x;

? If that is the case, you can observe that in previous methods, data was passed as an argument. In updatePosition however, you are not passing any arguments. Therefore, the method does not know what data is. You should study the tutorial carefully in terms of how the position update is being handled, and then do something similar for rotation.

The tutorial does not teach you after the first part it just says copy and paste things and does not explain them.

I believe the following section can be very insightful for your current problem.


If there is something you don’t specifically understand in the code shown here, please ask :slightly_smiling_face:. But working with rotation the same way as has been done above with position should be moderately easy. Multiplayer isn’t the most basic concept in game development, but you should be able to achieve what you want to if you carefully study the tutorial and also the sample project.

Thank you I will ask if I don’t understand something.

1 Like

I got it working but it is weird it rotates the other player only when they have done a 180 degrees. Do you know how to fix that.

Updated Code

var Network = pc.createScript('network');

Network.attributes.add('playerEntity', { type: 'entity' });


// static variables
Network.id = null;
Network.socket = null;

// initialize code called once per entity
Network.prototype.initialize = function() {
    this.player = this.app.root.findByName('Player');
    this.other = this.app.root.findByName('Other');

    var socket = io.connect('https://relmsever.glitch.me'); // Glitch hosted server
    Network.socket = socket;
    
    socket.emit ('initialize');
    
    var onPlayerMove = function(direction) {
        console.log(direction);
    };

    // listen for the player:move event
    this.app.on('player:move', onPlayerMove);

    // remove player:move event listeners when script destroyed
    this.on('destroy', function() {
        this.app.off('player:move', onPlayerMove);
    });

    
    var self = this;
    socket.on ('playerData', function (data) {
        self.initializePlayers (data);
    });

    socket.on ('playerJoined', function (data) {
        self.addPlayer(data);
    });

    socket.on ('playerMoved', function (data) {
        self.movePlayer(data);
    });

    socket.on ('killPlayer', function (data) {
        self.removePlayer(data);
    });
    
};

Network.prototype.initializePlayers = function (data) {
    this.players = data.players;
    Network.id = data.id;

    for(var id in this.players){
        if(id != Network.id){
            this.players[id].entity = this.createPlayerEntity(this.players[id]);
        }
    }
    

    this.initialized = true;
    console.log('initialized');
};

Network.prototype.addPlayer = function (data) {
    this.players[data.id] = data;
    this.players[data.id].entity = this.createPlayerEntity(data);
};

Network.prototype.movePlayer = function (data) {
    if (this.initialized && !this.players[data.id].deleted) {
        this.players[data.id].entity.rigidbody.teleport(data.x, data.y, data.z, 0, data.rot, 0);

    }
};

Network.prototype.removePlayer = function (data) {
    if (this.players[data].entity) {
        this.players[data].entity.destroy ();
        this.players[data].deleted = true;
    }
};

Network.prototype.createPlayerEntity = function (data) {
    var newPlayer = this.other.clone();
    newPlayer.enabled = true;

    this.other.getParent().addChild(newPlayer);

    if (data)
        newPlayer.rigidbody.teleport(data.x, data.y, data.z, 0, data.rot, 0);

    return newPlayer;
};

// update code called every frame
Network.prototype.update = function(dt) {
    this.updatePosition();
};

Network.prototype.updatePosition = function () {
    if (this.initialized) {    
        var pos = this.player.getPosition();
        var Model = this.app.root.findByName("Model");
        var rotation = Model.getLocalEulerAngles().x;
        Network.socket.emit('positionUpdate', {id: Network.id, x: pos.x, y: pos.y, z: pos.z, rot: rotation});
    }
};

Could you please tell me how to reproduce the error in your project? When I launch it I just get an animation related error.

@DevilZ Sorry I did not see your reply I was messing with animations. I think I know how to do the rotation but i need some help Do you know how to do first person movement with mouse controls but use rotate instead of Eulerangles?

Is this to send the rotation via the multiplayer server? You seem to be sending the euler angles anyway via the server, I’m curious as to why you would want to do this?

Yeah i changed it trying to get it to work with Euler angle now but if you do know still please tell me.

@DevilZ do you know how to find the entity based on their data.id

I’m not entirely sure where you are assigning an “id” to a player. Is the ID just the unique name of the entity? Or does it denote something else?

According to the tutorial it is just a unique name

If it is indeed the name of an entity, you can get the associated entity by doing this.entity.findByName and searching by the ID. API Reference on findByName can be found here.

1 Like

Ok i got the name and put it in console and it works now I tried to update it but i tried to update it by using Euler angles but error

Uncaught TypeError: Cannot read property ‘setLocalEulerAngles’ of undefined

Network.prototype.movePlayer = function (data) {
    if (this.initialized && !this.players[data.id].deleted) {
        var OtherModel = this.app.root.findByName(data.id);
        console.log(OtherModel);
        this.players[data.id].entity.rigidbody.teleport(data.x, data.y, data.z);
        this.OtherModel.setLocalEulerAngles(0, data.rot, 0);              
    }
};

Everything works i just have to rotate or change Euler angles got any ideas.


I am pretty sure it is defined because it shows everything about it also it was two big to fit everything.
I know it is OtherModel is defined as well because when I change EulerAngles to rotate it works until you reach 360 degrees the instead of keeping on going it turns back around (i think this happens because rotate does not understand the number past 360).