Sim-eth-es Troubleshootings

Treat single player as a local multiplayer if this is really a concern. Just use the loopback address. That’s what I do.

90% of apps states is for visuals. You drag along a ton of stupid shit just to execute something once a frame. Moreover, that code will never be usable anywhere else outside of a JME application.

It makes more sense to go the other way, adapt systems to states. AppStates are kind of a broken design. They are supposed to let you ‘extend through composition’ a JME application but then they don’t even fully support that. (Just like Controls are only a partial solution for Spatials.) GameSystems are way simpler because their only job is to execute game code and hook you up with other systems. No weird update delay, no preRender, postNosePick, postRender, preUpdate, postUpdate, stateAttached, stateDetached garbage.

So I guess it’s the examples you are criticizing? They may have lost something in trying to be simple. As I develop the moss stuff I’m trying to be more modular and clearly spell out client, server, and common… but in the end I think that only makes your problem worse maybe.

This code will always be far and away from a giant Main.java class. We can probably argue over the decomposition but there will always be some kind of decomposition.

1 Like

Yes, I didn’t test jBullet yet because I think it’s easier for us to switch to impulses / setting the linear Velocity directly.

Sure, so:

The problem is that Jaime isn’t in-line (vertically speaking) with the numbers, even though it should be due to the layout (I tried multiple). For some reason the offset / translation I set, is ignored by lemur.

Not really criticizing, rather posting them as a list to myself and maybe to see/discuss whether this is possible/reasonable. And I’m not a fan of a giant Main class, it’s rather that I don’t know sometimes if I’m on the client or the server.

I don’t have too much time at the moment… but something to remember is that Jaime is 0,0,0 at his feet and Lemur GUI elements grow down.

1 Like

Another way I am using (which is common for most RPGs) is that I send the target point to server (when player clicks on a walkable object) and in server I find a path for player to follow using a server side NavigationSystem and using a PathFollowSteerBehavior I fed the calculated force into bullet physic.
So player movement is treated like a npc.

1 Like

So, the Lemur Problem is fixed, it was just moving the “Jaime” Node instead of the container out of it’s parent, but the bullet issue still baffles me, especially because I didn’t notice it until changing a line, I really feel like reverting the commit…

I’ve tried impulses, forces and setting the velocity directly this time, nothing works. The only thing which worked half way was applying the desiredVelocity as force, that way the character bugged a bit and was able to accelerate (however the velocity wasn’t capped there).

After some fiddling (I now set the desiredVelocity as LinearVelocity), I had this beautiful thing in my log which correlated to my impression:

SET: (0.0, -0.6666667, -5.0)
vTemp: (0.0, -0.6666667, -2500.0)

I can’t tell why and what is wrong there, but I’ve also found that the Z value was always half the desired value (even when applying a force), this time it’s not half the value, but 50 times the value, that’s probably due to the mass of the character being 50. Not sure why it multiplies the setLocalVelocity with the mass though, or reports it like this…
Everyone is appreciated to check out Monake and edit the CharInputDriver :slightly_smiling_face:

I’m telling you… you should really try to build SiO2’s bullet form source and just pass a fixed timestep to bullet. For native bullet this will clear up 1000 weird things.

Like, change this line:
pSpace.update(t);

to:
pSpace.update(1/60f);

…and see if your weird problems magically go away.

1 Like

For me when setting body.setPhysicsRotation directly cause the body to have a buggy rotation. It is very noticeable when he is not moving and standing in place.

In following code

 // Kill any non-yaw orientation
        qTemp.toAngles(angles);
        if( angles[0] != 0 || angles[2] != 0 ) {
            angles[0] = 0;
            angles[2] = 0;
            body.setPhysicsRotation(qTemp.fromAngles(angles));
        }

I also see this behavior in SiO2’s bullet example but it is hard to notice it.

I am going to replace it with torque based rotation to see if it fix. I need to find a way to calculate torque force from desired rotation. You know I suck at Math ! :blush:

btw I am going to test idea of fixed timestep, Paul thanks for the idea :+1:

This is probably the source of your other problem, too.

Essentially, I’ve found that setting anything on the rigid body in the drivers has inconsistent results if you don’t use a fixed time step… for native bullet. I’ve tried moving the running of drivers to the prephysics tick, the post-physics tick, etc… as I recall the only thing I accomplished was more consistent failure. It doesn’t make sense to me and I lost the will to live while trying to track the issue down in the C code.

2 Likes

Unfortunately the fixed time step didn’t fix it for me, note that pSpace.update() is still called at variable times but made to believe it’s 1/60 (so I want to say I did it as you suggested but that doesn’t change when/how often update is called).

What I got when doing this is quicksand, the character slowly bugs through the floor, falling down. What I don’t get is why it used to work in the SiO2 Example Code like just without adding this line calculating run/walk, must’ve been a very lucky circumstance.

Regarding the questions of code organization, I thought I would mention something about this now that I understand it’s the sim-eth examples you are talking about.

I fully expect that a real game would split its own code up in a more development-friendly way. The sim-eth examples are monolithic examples and so keep code together in one project. I do that in other simple cases also mostly because I don’t use an IDE and it’s easier for my to navigate around.

However, for SpaceBugs I developed it as a “real game” and so the code is separated into three projects:

  • server
  • common
  • client

The “server” project contains all of the GameServer code, the sim package, all of the game systems, etc… Anything “game logic” lives here.

The “common” project contains the shared stuff that both client and server need to communicate. So this would be the game constants and the RMI interfaces that the client and server classes implement. For example, in the sim-eth examples this would be where things like AccountSession and AccountSessionListener lived. GameSession, GameSessionListener, etc… net.server impls live in the ‘server’ project and net.client impls live in the client project.

For an ES based app, this is also where the components live.

With just those two projects, I could create a command-line server only application… with no visuals. Aside from jme-math and probably a few utility classes, it wouldn’t even really need anything from JME-core. That’s the ideal server, really.

The ‘client’ project is where the JME UI lives along with the client impls of common’s interfaces. No ‘sim’ code lives here.

For my single player games, I autowire a server and client together an auto-login, too… it may not be the most efficient way but with a loopback connector it’s going to behave exactly like the networked version. (At some future time, maybe it’s possible to wire the client interfaces directly to server implementations… but that’s a project for a future date when the game is done and you’re bored.)

…it also makes it super easy to text the network code because I don’t have to do 20 steps every time. Just launch and click “single player”. :slight_smile:

1 Like

It’s not about how often update is called. I experimented with a lot of things.

The issue was that when the tpf passed to update was VERY CLOSE to the actual time elapsed… but not exactly like it. (Or maybe it was when it was exactly like it.) Things like applied torques/impulses would not show up or be so small as to be irrelevant. Jaime would move like in quick sand if he moved at all. Or like 1/100th speed.

I don’t have time to resurrect which version worked and I have a lot of commented out attempts so I’m not sure what state I left my local code before rolling it back to push releases in November.

Here is the code verbatim in case it matters:

        float t = 1 / 60f;
        //float t = 0.99f / 60f;
        //float t = 2f / 60f;
        //float t = 0.016666781f; //(float)(time.getTpf() * speed);
        //float t = (float)(time.getTpf() * speed);
System.out.println("-----t:" + t + "  ------------- " + time.getTime() );
        if( t != 0 ) {

//            for( EntityRigidBody b : driverBodies.getArray() ) {
//                b.getControlDriver().update(time, b);
//            }

            //pSpace.update(t);//, 2);
            //pSpace.update(t, 0);
            //pSpace.update(t, 1);
            pSpace.update(t, 2);
System.out.println(" distribute events");
            pSpace.distributeEvents();

I think the update(t, 0) one is the right one, thinking back.

1 Like

OH! did not know it can take a second argument called maxSubSteps.
Searched the web for it … and …

old doc says :

maxSubSteps: Should generally stay at one so Bullet interpolates current values on its own. A value of zero implies a variable tick rate, meaning Bullet advances the simulation exactly timeStep seconds instead of interpolating.


new doc says:

It is perfectly fine to stepSimulation(1/120 , 0) to get a fixed timestep of 120 Hertz for example.


It mentions you can safely use maxSubSteps = 0 with a fixed timeStep. In our case t=1/60.

1 Like

Finally fixed it. I’ve increased maxSubSteps to 8 in the physicsspace settings before but that didn’t help.
Now with update(t, 0); everything works as expected (okay well the character is moving with 9.75 instead of 10, but that’s my fault). GREAT!

I’m not sure why those two quotes are telling different things:

but that’s bullet :smiley:

Edit: Just tested it, it even works with update(t, 0) (so t being the variable time from SiO2, not 1/60f constant)!

1 Like

Sorry not mentioned it clearly enough.

The first quote was from an old doc was saying do not us maxSubSteps=0.
In the the second one author mentions it was and out-of-date doc and you are pretty much safe to use maxSubSteps=0 for fixed time step.
this is the link to ref Setting maxSubSteps = 0 - Real-Time Physics Simulation Forum

Edit:

Edit 2:
And a nice reading

More over I believe maxSubSteps=0 is very reasonable on server side because we do not need interpolation on server side. It is just a wasting ? SimEtheral can interpolate it smoothly in client side.
Paul much more thanks. I got to know great info today due to you. :slightly_smiling_face:

I am exactly using this way except that I do not call it server client.

for example for combat mechanics I have three modules :
combat: for server side
combat-common: for RMI api and components.
combat-view: for client side

maxSubSteps=0 means that if for some reason your update loop is slow then your physics will also slow down.

Also, using a variable tpf with maxSubSteps=0 is super dangerous as you might have a HUGE tpf and then all of your objects might teleport I guess.

From my reading of the code, if you have bullet configured for 1/60th of a second but call update(1f, 8) then it will internally run its update loop 8 times trying to get as close to that 1/60th of a second as it can.

Likewise, running update(1f, 0) would run the integration for all objects/contacts/etc. with t=1 second… which is probably not what you want… which is why variable tpf is bad here.

I mean, you can try it but I think if you are going to pass (t, 0) then t should probably be a fixed and reasonable size (1/60 if you want 60 hz updates).

re: the problem in case someone who knows bullet code better than me looks into this…
At first I thought the issue was that these make up frames were clearing the state and so the stuff we set in the control driver was getting cleared for the second makeup frame. But that didn’t appear to be the case for two reasons:

  1. tweaking the code to pass a t very close to the real tpf (like within a fraction) would cause different behavior than simply passing the exact tpf (and I don’t remember which one failed but either should have caused one frame to run).
  2. moving the control driver stuff to either the prephysics tick or post physics tick (which are run even on the makeup frames) didn’t fix the problem. (This is what makes me think that the issue was when tpf exactly aligned with real time passing.)

Anyway, the only downside of update(t, 0) is that physics will slow down if the real update rate slows down. For example if your game is really busy and so the update loop is only running at 30 hz then physics will look like it is running in half-time slow speed.

Personally, I’m ok with this for a couple reasons. 1) it’s likely physics that is killing the update rate anyway… so makeup frames may not fix anything, 2) I’d rather have physics run a little slow for a bit than have objects start warping through walls.

2 Likes

Sorry for the next stupid question but when I add a Ghost Component to an entity it disappears from the screen for some reason I was unable to debug yet. Everything else is the same., but I also don’t see any update packets moving it away or something and indeed the client is loading the Spatial and moving it in place. The only thing which could be the problem is that the ZoneNetworkSystem’s PhysicsObserver is skipping them, but that’s only relevant for physically moved objects anyway

My first thought was “A Ghost component should make an object invisible, no?” and then I remembered it can be linked to another object. So I’m not 100% sure what you mean and it’s probably worth seeing code.

The rigid body with the ghost child should be unaffected by having a ghost child. But the ghost is server-side only as there is no reason to have it on the client.

Well in my case it doesnt have a parental rigid body as I wanted to do item pickups by walking over the items so I have an objectType and a Ghost which is triggered upon Walking over it. I guess you would suggest two different entities for that then?