Prevent mesh rotation/repositioning on specific axes

I’m trying to create a infinite runner game, just like the no-internet google dino game, here’s the playground.

Currently the character is the cylinder, using the space bar we can jump but I’m dealing with a issue that the cylinder moves to some directions after a couple of jumps, also, sometimes we can see that the cylinder kind fit on its position again, like a ball rolling on a semi-circle.

On the lines 73 and 74 I’m trying to force the mesh to keep on the same x and z, just like I’ve done with rotation but for some reason the mesh keeps repositioning itself after jump

Also, after I lock the rotation I got a strange bug that the mesh sometimes go inside the ground, commenting line 69 it don’t go inside the ground anymore, but the mesh starts to rotate after a couple of jumps, falling from the ground. This makes me think that could be a better way to prevent mesh to rotate.

So, I have two doubts:
How can I properly prevent my mesh from keep repositioning on x and z?
How can I properly prevent my mesh from rotate on x, y and z?

Maybe @Cedric will be able to help as it is probably related to physics (maybe a precision problem when computing intersections).

Some suggestions/things you should try:
Mixing forces/impulses and settting body position and orientation at the same time is a bad idea. Physics engine internal states get mad after a while and you’ll get weird results after a while. It can become incontrollable and I think it’s the case here.
You should try ammojs. It’s more supported than cannon and overall, I think the resolution quality is much better. And you’ll get more controls.
Do not try to constain a body position by setting a new position. Instead, favor changing its angular or linear velocity. Like this:

var vel = player.physicsImpostor.getLinearVelocity();
player.physicsImpostor.setLinearVelocity(new BABYLON.Vector3(vel.x, vel.y, 0));

For angular velocity, set all angular speed to 0 so the mesh will not rotate. Ammojs provides

setAngularFactor

that you can call on ammojs rigid body.Or a more ‘manual’ way is to setAngularVelocity to (0,0,0) each frame.

4 Likes

I already provided the “solution” badge cause this just work! Thank you again @Cedric!

But what you mean by “call ammojs rigid body”? Its something like call this outside the player? I did with the “manual” way, but I would like to understand this other way

And one more thing, I try to use Ammojs but when I replace Cannonjs to Ammojs the project crashed with some errors:

I’m loading the plugin through the babylon CDN https://preview.babylonjs.com/ammo.js and initializing it with scene.enablePhysics(null, new AmmoJSPlugin());. am I doing something wrong?

I think you need to await ammo() before using it

1 Like

When you ask this I made a couple of searches and figure out that I’m not even calling the ammo.js

But now I’m it says that I don’t have any camera defined

Is there any other update on the code that I need to make to use Ammo.js?

nope normally as long as you await ammo(); before creating the plugin it should be all good. This is exactly what we do in the playground.

The other error means you are trying to render the scene before creating a camera.

1 Like

But I don’t change anything when change from cannon to ammo…

I’ll try to figure out what’s happening :thinking:

Thank you @sebavan :grin:

1 Like

I had to change a couple of things when switch to Ammo.js

Basically I don’t need to import the CDN anymore with this package importing it as this: import * as Ammo from 'ammo.js';

The othe change I have to made was on the Ammo().then I had to make it on the index.js of the react (where are the ReactDOM.render) wrapping everything inside the .then, as follow:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
import reportWebVitals from './reportWebVitals';

import * as Ammo from 'ammo.js';

Ammo().then(() => {
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById('root')
  );
  // If you want your app to work offline and load faster, you can change
  // unregister() to register() below. Note this comes with some pitfalls.
  // Learn more about service workers: https://cra.link/PWA
  serviceWorkerRegistration.unregister();
  
  // If you want to start measuring performance in your app, pass a function
  // to log results (for example: reportWebVitals(console.log))
  // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
  reportWebVitals();
});