[SOLVED] Multiplayer animation with PlayCanvas and Photon

I’m still having difficulty with this.
If I try something like this, I get an error.

const { x, y, z } = content.position;
    const player = this.entity.findByName(actorNr);

    let curPosition = player.getPosition().clone();

    if(content.position != curPosition){
        if(content.position.x != curPosition.x){
            this.player.anim.setBoolean('walk', true);
        } else{
            this.player.anim.setBoolean("walk", false);
        }
    }

    player.setPosition(x, y, z);

I can’t set the boolean of player, it gives me an error.
Do I need to add an anim component to player in this game-room.js or what is the best way.

“Yes this also could be another route. This attribute could be broadcast from player.js script and added to the data structure passed.”
Would this be the easier method? If so how would I go about it?

Yes, you try to set a boolean of the anim component so you have to make sure this exist.

You send the animation like you send for example the new position and then you apply this animation.

How would I send the animation like I am sending position, what would the code look like?

Is it applied then in game-room so it is broadcasted to all players?

There a different ways to do this. You can send for example an integer like 1 and 2, where 1 is your idle animation and 2 is your move animation. I didn’t do this myself before, so you have to find out the exact way yourself.

Another option is to apply the animation without transitions. Then you can do something like my post below.

1 Like

How would I set the animation to an integer. What is the code you use to declare that. My animations are now in glb format and not json.

I suggest to try my last option first, because this is easier to achieve.

@Albertos Is this the suggestion? I can try to show the Photon version.

Yes, is it very different?

1 Like

@Albertos No and I will try here to whip up an example. Your understanding is correct I was just making sure which above you were referring to.

@Alexis_Shaju So the example post above is a good example of what @Albertos suggested as the best path for getting you to your solution. But, this example is using glitch server and socket.io. Photon is not that much different other than the way it sends messages. We can take a look at player.js again.

Player.prototype.raiseEvent = function () {
    if (!this.tmpVec.x || !this.tmpVec.y || !this.tmpVec.z) return;
    const data = {
        position: {
            x: this.tmpVec.x,
            y: this.tmpVec.y,
            z: this.tmpVec.z,
        },
        player: {
            name: this.app.loadBalancing.myActor().name,
            playerMat: this.app.loadBalancing.myActor().getCustomProperty('Mat'),
            playerAnim: this.entity.anim.baseLayer.activeState 
        }

    };

    this.app.loadBalancing.raiseEvent(0, data);
};

So I added another value to pass in with the data which is broadcast from the player. You can see the that we are getting the current animation state of the entity’s animation state graph.

On the game-room.js side…

GameRoom.prototype.updatePlayerPosition = function (content, actorNr) {

    const { x, y, z } = content.position;
    const playerData = content.player;
    const player = this.entity.findByName(actorNr);
    const playerMat = this.app.assets.find(playerData.playerMat);

    // Display Actor
    this.playerName = player.findByName('State').element;
    this.playerName.text = playerData.name;

    // Map Color material
    player.render.material = playerMat.resource;

    // Set player animation
    player.anim.baseLayer.play(playerData.playerAnim);

    // Set the position
    player.setPosition(x, y, z);

};

So your instantiated temple representing the other players in your game view must have the same animation state graph attached to it as your local player in order to recreate the other players in the rooms animations. There may be corrections to the above depending on the current state of your project but I am not sure.

@Albertos can verify if I captured his idea.

1 Like

Yes, I think this is the easiest way. Make sure the local player animations works correctly. Also make sure the other player has an anim component with an anim state graph that has all animation states and no transitions between the states.

1 Like

@Tirk182 When I try the code you suggested, I get the error of reading baselayer, here it is


image

What could be the cause of this? Like Albertos said I should, I added an anim component and animstategraph to other player template, with no transitions between animations.

That was an error on my part, the main player didn’t have the anim component attached to it, so it works now.

The code now sort of works, except without the transitions I get something quite wierd. When I press w to move on other player, I see like little spasms in the player playing the walk animation. It is never fully carried out if that makes sense. It just spasms for a few seconds between idle and walk and then returns to idle.

Is there any way to ensure that the player plays the walk animation as long as the key is pressed?

When I try with transitions, it seems to work, I don’t know why, still glitchy and needs work on animations but the general gist is there. When enemy moves, their movement animation is somewhat now reproduced to viewing user.

My bad, you need to prevent the same animation is applied repeatedly.

So how do I prevent these repeated animations?

Based on line 16 of the example of @Tirk182 above, that will be something like below.

if (player.anim.baseLayer.activeState != playerData.playerAnim) {
    player.anim.baseLayer.play(playerData.playerAnim);
}

@Tirk182 @Albertos Thanks a lot to both of you for all your help on this.
Finally tweaking some numbers in the animstategraph to make it look better, but the animations from enemy player have finally come through without a problem to current player.

2 Likes