[WIP] Open Worlds App

Hi guys,

So I decided to start sharing my progress on the app I’m working on in my spare time. The goal is huuuuge - to make an MMORPG that runs in the browser and where players can create their own models + skins and use them in the game. Some things are possible as I’ve tested them already. But I know nothing at all about writing MMOs :rofl::rofl::rofl: So… I don’t know how it’ll turn out.

This project is a continuation of a hackathon I took a part in recently. Here is the post of the hackathon submission, but I decided to create a new topic for WIP - Work In Progress. Some things were working, some not. Now I’m trying to build everything from scratch using TypeScript, to gain some skills… So maybe, just maybe, one day I might get a job as a developer - currently I work as a 3D Artist.

But thanks to my experience in 3D at least I know how to prepare all the assets and how to do the look development. However I’m planning to mostly use bought assets. I got some from Unity Asset Store earlier this week.

So here’s my first update:

  • proper character
  • proper starting screen
  • imported all animations (unity > blender > mixamo > blender again > babylon app)
  • blended animations (‘combo’ animation)

TODOS (for the next week):

  • add at least 3 more characters
  • have different ground for each character
  • play some ‘combo’ animation when the player picks a different character.
  • add some description about: race/class/specs

11 Likes

Super cool to see this project going on! I’ll be waiting for each update with excitement :smiley:

3 Likes

Leeeeeeeeeeroy jenkins

5 Likes

[UPDATE]

So I was on vacation all week but I managed to do a little work. Also I got a new, very interesting job and it looks like starting next month I will have much more time to work on this project! I’m sooo excited!

So here’s the small update:

  • added 3 more characters
  • character animations are played when you switch the character
  • a bit different enviro per character
  • some description about characters

TODOS (for the next week):

  • create button creates the character and puts it into the game scene
  • figure out character movement (with animations)

3 Likes

So… I’m back to the project! After one year of doing completely different things. I had a job that took most of my time and in the end I was laid off anyways so… No more stupid jobs like that. I want to have my stuff done too.

I had to go through again the animation and 3d assets export pipeline again… Which was painful! But at least now how it should be done. Maybe not fully automated, but there’s no mess.

So this time I’m building it from the right angle. So player movement, camera, surface follow (which was easier to do then I thought - or maybe I got better at design patterns?).

Anyways, here’s the progress:

2 Likes

looks way too nice :slight_smile:

1 Like

Ooooh the lighting is very nice!

1 Like

It looks way too nice because the assets are not mine. I bought them a year ago, btw its https://www.syntystudios.com/. Animations of course from Mixamo. Their rigs are fully compatible.

Also the camera in the video is controlled by the player, there is no collision detection yet. I guess that might be the next step.

So it’s been a while. And recently I got back to the project.

And for the past year or so I was trying different things. Mostly trying out the backend things. I really didn’t want to use with any JavaScript on the backend, so I had to try new languages. And I ended up with I guess my own game engine in Go. I tried using some “out of the box” solutions (like Raylib), but then I had problems with loading GLBs. So I also wrote my own geometry loader (for the backend). I just like writing everything from scratch.

The game runs on the server, BabylonJS is just used as a client renderer. As you can see the character animation needs fixing, but overall I think I’m on a right track. And I think I can start implementing the combat now.

I do have a nice entry zone prepared, but this is just a testing scene for character movement etc.

6 Likes

Hello again!

So I’ve build a new main player character movement system, based on physics.

Before I used just a cross product of the surface normal with a limit on a dot product (between the surface normal and a up vector). This is a nice solution that gives you constant speed no matter the “slope angle” - unless you multiple it by the dot product (that gives you a natural feel that the speed is lower with higher slope). Also the character won’t even fall off and is somehow stuck to the surface.

When I started building my starting zone, it turned out dealing with collisions with this solution is very annoying. Also I really want for my character to be able to jump over the obstacles, and the “surface follow” method don’t allow you to do that.

So I introduced physics this time. Still the jump doesn’t work (the character shoots out in space on jump) so I need to spend more time on that. But I have to keep on going, jumping can wait, I have to do the combat system now.

This is a starting zone I prepared few weeks ago. But I don’t like it anymore. I will completely scrape it and I’m building a new one. Just saving this for a record.

6 Likes

Hey this is really good. You should add it to our 8.0 announcement video list!!

1 Like

@Deltakosh I think I will. I was planning on releasing a first official video end of February. Just need to rebuild the world, add combat system (melee & ranged), death and res, character selection, character name plates, game UI… I might just make it in time :rofl: Especially that I’m unemployed so I have nothing better to do…

1 Like

Hi @Jozef_Plata

Would You be so nice to explain a little bit how this movement on 3D map is working? what client is responsible for? what’s the responsibility of the server? do You have system for hacks prevention?

@Maiu So for the movement I’m using PhysicsCharacterController. I played a bit with the values to get the result I like the most.

            this._physicsController = new PhysicsCharacterController(position, {
                capsuleHeight: PLAYER_SETTINGS.CAPSULE_HEIGHT,
                capsuleRadius: PLAYER_SETTINGS.CAPSULE_RADIUS,
            }, scene)
            this._physicsController.keepContactTolerance = 0.01
            this._physicsController.keepDistance = 0.005
            this._physicsController.maxSlopeCosine = 0.9

I also have to calculate the movement direction based on the keyboard input. And at the end I also make sure that the movement vector is always following the surface.

                const ray = new Ray(this._player.positionNode!.position, Vector3.Down(), 0.5)
                const info = PickWithRay(scene, ray, (mesh) => {
                    return (mesh.layerMask & LayerMask.GROUND) !== 0
                }, false)
                if (info?.hit && info.pickedPoint) {
                    const up = info.getNormal(true)
                    if (up) {
                        // I don't really need the surface normal, but I set it for debugging
                        this._player.contactSurfaceNormal = up
                        const right = up.cross(dir)
                        dir = right.normalize().cross(up.normalize())
                    }
                }

                // scale is just a multiplier for each direction (forward, backward, etc.)
                this._player.velocity = dir.scale(scale).scale(PLAYER_SETTINGS.MOVEMENT_VECTOR_SCALE)

'm also doing some calculations if the character is grounded or not:

        scene.onBeforeRenderObservable.add(() => {
            let isGrounded: boolean[] = []
            this._groundingNodes.forEach((node) => {
                const ray = new Ray(node.absolutePosition, Vector3.Down(), PLAYER_SETTINGS.CONTACT_GROUNDED)
                const info = PickWithRay(scene, ray, (mesh) => {
                    return (mesh.layerMask & LayerMask.GROUND) !== 0
                }, false)
                if (info) {
                    const normal = info.getNormal(true)
                    if (normal) {
                        const dot = normal.dot(Vector3.Up())
                        if (Math.abs(dot) < 0.75) {
                            // fall off
                            this._isGrounded = false
                            return
                        }
                    }
                    isGrounded.push(info.hit)
                }
            })

            this._isGrounded = isGrounded.some(value => value)
        })

And then I can set the actual velocity of the PhysicsCharacterController:

        scene.onBeforePhysicsObservable.add(() => {
            // save current position
            const wasPos = this.positionNode!.position.clone()
            const dt = GameManager.Inst.engine.getDeltaTime()

            // accumulate time when falling (for acceleration)
            if (!this._isGrounded) { this._timeNotGrounded += dt * 0.5 } else { this._timeNotGrounded = 0 }
            // this is the velocity vector that was set with keyboard input
            const outputVelocity = this._velocity.clone()
            // add the gravity (when not grounded)
            outputVelocity.addInPlace(Vector3.Down().scale(
               PLAYER_SETTINGS.MOVEMENT_FALLING_MULTIPLIER * this._timeNotGrounded
            ))
            // setting the velocity directly, I didn't like the helper method
            this._physicsController.setVelocity(outputVelocity)
            // you just have to do this
            const support = this._physicsController.checkSupport(dt, Vector3.Down())
            this._physicsController.integrate(dt, support, Vector3.Down().scale(10))

            // and finally set the position
            // the actual character position is 1 unit below the physics controller
            this.positionNode!.position = this._physicsController.getPosition().clone().add(Vector3.Down())

            // I had big issues when just parenting the camera to the character
            // so I need this to move the camera.
            const dP = this.positionNode!.position.clone().subtract(wasPos)
            this._camera.target = this.positionNode!.position.clone().add(Vector3.Up())
            this._camera.position = this.camera.position.clone().add(dP)
        })

I had to play a lot with the settings, as the PhysicsCharacterController is not perfect, but at least I can implement jumping in the future.

Currently the client sends updates to the server, and there’s no validation yet (like if the position is incorrect, or the velocity is way too big). But I guess I’m just going to “clamp” to maximum values, and then force them on the client.

I’m still stuck on NPCs movement and combat. So I’m not sure how to handle hacks. Maybe I will just ignore them? If there’s no actual money involved in the game (no in-game store, etc.) maybe it’s not even worth handling the hacks?

1 Like

Thanks a lot :slight_smile:
I think it’s not worth to invest time at this point in hack prevention - I wouldn’t. It can be done in several different ways (even async by analysing movement data), not sure how it’s done in commercial games.

So I was busy with different things and I didn’t manage to create a submission for Babylon 8.0 release. Well… maybe next year.

Anyways during building the new map I realized that I need to start optimizing the game. It turned out that I cannot update at once too many characters on the client. The server is just fine handling 500 npcs, but it’s way too much on the client.

So now I’m only passing to the client updates of neighboring cells to the cell containing the player (so that’s 9 cells in total). When receiving an update one of three things can happen:

  1. the character is instantiated if it doesn’t exist,
  2. update the movement, save time of the update
  3. if time of last update exceeds some threshold, delete the character and all it’s observers.

This way I can just reuse what I already have on the backend (with some minor teaks). But might cause weird behaviors with connection latency issues…

But the good news is that instantiating character is super fast, there seem to be a minor frame drop with instantiating many characters at once, but I think I can further optimize that.

Anyways, here’s a test with 300 npcs (you can’t see them, they are all on the backend server) and closest 9 cells (white lines are boundaries of each cell).

1 Like

Pretty good!