[OPEN SOURCE] Multiplayer 3D RPG Using Colyseus

Thanks @sebavan

I naively started integrating VAT/instances into my project and realized I cannot assign material to instances… After thinking a while, I was wondering if I could do something like this? (pseudo code)

entitydata = [];
for each race
    merge mesh and skeleton
    create vat manager
    for each race material
        clone merged mesh
        assign vat manager
        clonedMeshes[materialIndex] = cloneMesh
    endfor    
    load vat texture into vat manager
    entitydata[race] = [
        clonedMeshes,
        vat,
    ]
endfor

and then for each entity i can do thensomething like this

entitydata[race]clonedMeshes[materialIndex].createInstance()

Hopefully, that makes sense :slight_smile:

EDIT 1: actually tried and it worked :stuck_out_tongue: I have to work on the equipment now.

3 Likes

Hi @sebavan,

I’m so close, i’m just struggling to find a way to prevent a animation from looping like the death animation:

// this.targetFrame is the last frame of the animation range ()
instanceMesh.instancedBuffers.bakedVertexAnimationSettingsInstanced.set(this.targetFrame, this.targetFrame, 0, 0);

You can see my current iteration here, it’s quite basic. It feels like it should work… :slight_smile:

I basically just I play the animation once, and then set the animation to play the last frame on the corresponding animation ranges (as seen in code above).

Any idea how I could get about this?

Thanks,

I am sorry @oriongu, I will have to summon @Evgeni_Popov on this one as he is the animation guru :slight_smile:

I agree it looks like it should work :frowning: Is there a way to repro in the playground without the rest of the code ?

Please, bear with him as he ll be back next Tuesday after his break.

1 Like

Haha that’s fine,

Here is a quick PG showing how I do things, hopefully that helps. I stripped away anyhting that is irrelevant to this.

Note: Click left to change animation

Looks like you’re not using animation groups, so dunno if this is helpful, but here’s how i do it:

    CharacterController.prototype.doDeath = function() {
        this.mlog.log('CharacterController-doDeath', {}, 6);
        this.isAlive = false;
        //set time dead
        this.timeDead = new Date().getTime();

        for (const property in this.agMap) {
            //console.log(this.agMap[property])
            if (property != 'death'){
                this.agMap[property].pause()
            }
        }
        this.agMap['death'].play(false);
    }
1 Like

The vat.time counter is used to compute the current frame of animation, so, when switching animation, if you want the new animation to start from the first frame, you should reset the vat counter to 0 (or to a multiple of the animation duration):

2 Likes

Hi there,

Sorry for the late answer as I was travelling,

Thanks, that seems to do the trick just fine.

I’ve setup a dev branch demo ( it’ll probably be broken when you visit ): https://t5c-debug.onrender.com/

Next step, woking on adding the equipment :slight_smile:

Getting close, but it’s always fun to see stuff like this :slight_smile:

3 Likes

Hi all,

Quick update on implementing baked animation to the project:

VAT was reasonably easy to implement however adding the equipment is turning to be rather complex but there is progress,

I’m trying 2 different approaches with very similar performance:

  1. with retargeting
    I’ve got this working and the last thing to implement is to add a separate skeleton for each item as explained by @Evgeni_Popov (Baked Texture Animations with Animation Groups? - #34 by Evgeni_Popov)
    Current Perf: 200 entities / 40 fps / 2 items per entity

  2. by bone weight (the easiest to implement)
    explanation here, thanks @Alexander_Sosnovskiy : [OPEN SOURCE] Multiplayer 3D RPG Using Colyseus - #256 by Alexander_Sosnovskiy
    I’ve got this working too, but I still have a few item animation desync issues/weird rotations to resolve.
    Current Perf: 200 entities / 30-40 fps / 2 items per entity

Performance without vat: 10 fps for 200 entities / 2 items per entity
Performance with vat no equipment: 40fps for 200 entities

It looks like neither implementation seem to be hurting performance too much so I’m guessing looking into my vat implementation is where I should look to improve performance.

Here is the bone weight version in action:

1 Like

Hi All,

Today is this project 1st aniversary, time flies :slight_smile:

Ok, weird one here, while testing trying to improve performance for the vat/instances, I found a random thing that boost the performance alot. If I stop parenting my player mesh to my collider and just move that mesh within the game loop to match the collider position, the FPS jumps to a nearly steady ~50 (versus ~30). I can even bump the max entities to 400 without too much difference.

How could parenting a mesh affect performance this much?

I’ve update the debug link to showcase it: https://t5c-vatboneweight.onrender.com

2 Likes

@Evgeni_Popov anything we could use to improve the scene graph from this finding ?

I guess it’s related to world matrix computation?

So, maybe freezing world matrix computation could help?

I see this in Performance Tab(Chrome)

@oriongu seems like you need to optimise evaluation of active meshes. Another issue - texImage2d. I think it depends on UI labels(mobs’ names).

1 Like

Ok, Thanks for the advice,

Ok, after adding an aggressive lod (includind relevant UI elements), I’m getting a steady ~60 fps now (except for the startup as my spawn controller spawns everything in one go which needs to be improved).

There is still tons of weird things I dont fully understand:

  1. when player dies, a random amount of other entities seems to play the same death animation…
  2. at each run, the helm for example would be misaligned in some different way
  3. somethimes the items do not play any animations (the previous run would play fine)

Damit, I think I may be chewing on a bone too big for my size :slight_smile:

1 Like

Seems that Coroutines are just what you need here - Babylon.js docs

1 Like

My answer here may help:

Thats probably it. The 2d renderer uses canvas 2d so its going to be very slow. Rather unfortunate. It may be counter intuitive that drawing 3d objects will be much much faster.

Some non html options ive considered are pixi or small webgpu frameworks. pixi uses gl context , but that would get complicated switching to webgpu. Its possible use webgpu and copy the texture it into a webgl context, similar to how you do can do with imgui framebuffers. Maybe for native, Vulkan has an extension so you can do it without copy. But…idk prob just dont bother.

Ultimately, i think the answer is use bjs geometry/textures for everything that moves in 3d such as healthbars and nameplates then use react for the menus, windows, cooldown bar, etc. flagship games do it that way, no reason to make gui stuff harder on yourself when youre already rendering on the web. Maybe a hot take, but I view bjs gui lib as convenient svg and texture creator, not actually a gui framework.

4 Likes

Hi all,

I was having issues of animation synchro between player mesh and equipment so after having a chat with @Evgeni_Popov & @sebavan, the easiest way to get this sorted is with a PG that replicated my core game loop and iterate from there.

So I finally got my core game loop game loop in a PG so we can improve it together: https://playground.babylonjs.com/#3NIXCL#368
UPDATE FIX SHIELD: https://playground.babylonjs.com/#3NIXCL#395
UPDATE WITH BASIC MOVEMENT: https://playground.babylonjs.com/#3NIXCL#472
UPDATE ADDED RAT + BETTER CAMERA FOLLOW: https://playground.babylonjs.com/#3NIXCL#486

left click will make one random entity to start walking

The “good” thing is that we have similar animation desync in the playground versus my local so it should help the debugging process.

What would be great to achieve:

  1. Fix any desync between equipment and player mesh (knowing both could be rotated/scaled/offset to “fix” any placement issue)
  2. It would be great to be able to desync randomly each instance so as to prevent every instance playing at the same time (if that makes any sense)
  3. Any optimization you guys could think of

Please note:

  1. Not sure why the shield is not correctly placed
  2. We should probably baked in realtime to make sure my vat texture json is not corrupted

UPDATE 1 (1/12/2023 11am):
Looks like only the knight model is desynchronized, the other 2 models seems to be working well and the equipment is synchronized just fine for (idle, walk, attack) (still have not resolve the death animation yet).

4 Likes

You rock my dude!!

1 Like