[Video] Physics Programmers --- Help :(

I’m having a really strange behaviour occur with my objects’ physics. I’m attempting to set the rotational velocity of my object, but only on two of it’s local axes, to make it self-right depending on it’s rotation relative to a given normal.

This is much easier to describe with a video, so here it is:

Notice the odd behaviour, if the craft is facing either the positive-X or negative-X direction, the craft behaves as it should, righting itself to follow the normal of the terrain below it. However, as soon as the craft starts facing more towards Positive-Y or Negative-Y, it starts getting madly out of control, until it starts to face positive/negative-X again and returns to the proper behaviour. For some reason as it starts to line up with the Y-axis, it starts going mental. I’ve posted the psuedo-logic below and the video does the same thing in Blueprint.

I’ve done the same logic for the craft in both C++ and in Blueprints, and experienced the same behaviour with both. I’ve tried rotating the Normal and the ‘Alpha’ force around various rotations and still had no luck. I’m convinced it must be something wrong with the way the logic is being conducted, but can’t for the life of me figure out what it is, and I’m following the logic of another game that works perfectly with this technique (according to reliable sources). Can anybody highlight where I’m going wrong?

I have also tried using Physics Forces (AddTorque), but that yields the same problem, and later down the line will be harder to replicate anyway, so ideally I want to set the rotational velocity directly.


Omega  = Angular Velocity (Local-Space)
Alpha = Angular Acceleration
Normal = World-Space Normal of Terrain Beneath Vehicle (From Line Trace)
Alpha Damp = Damping Value.
Alpha Track = Speed at which it tries to right itself.

Pitch and roll damping:
alpha.x = -alphaDamp * omega.x
alpha.y = -alphaDamp * omega.y

Terrain Normal Tracking:
trackNormal = Normalize( ( normal.x, normal.y, normal.z + 2) )
scaledTrack = alphaTrack * heightRatio
alpha.x -= scaledTrack * DotProduct(trackNormal, ForwardVector)
alpha.y += scaledTrack * DotProduct(trackNormal, RightVector)

Omega += alpha * deltaSeconds

Convert 'Omega' To World-Space

Mesh->SetPhysicsAngularVelocity(Omega, false)

sorry i’m not the one to help but that was so much fun amazing^^ i’m still laughing

Haha I got excited to see a reply then, when you’ve been slaving over the problem for weeks it’s not funny anymore :p!

Hard to say without hands-on experience, but I notice you’re not doing any damping on alpha.y - is that intentional, or maybe the source of the problem?

Sorry, that’s a typo, should be Y!

Ah, that’s settled then. Thinking continues…

Sorry I can’t delve into it more deeply at the moment but it seems to me like one of your vectors is either in local where it should be world (or vise versa) or you have a vector somewhere that is rotated strange, like 90 degrees on Y axis or something. Have you tried adding an Arrow component to things to make sure your assumptions match reality? I would also make 100% sure the XYZ axis of the model matches what you think it is, as well as any components of the model you are applying forces to. Make sure there are no weird relative rotations.

Thanks Sinoth for looking,

The XYZ of the model is okay, it’s the root component of the actor and there aren’t any other components inside the version you’re seeing in the video (it’s just a static mesh), so it doesn’t seem to be a model-related issue. When converting Angular Velocity to local space (and then back again at the very end of the function when it’s set on the mesh), I’ve tried both ‘RotateVector’ (using the meshes world rotation), and the ‘Inverse Vector Transform Location / Direction’ in code, neither of which seem to fix the problem.

I think it might be something more to do with the maths of the way it’s done. I’m using the Dot-Product of the Surface Normal and the Vehicles Forward/Right vectors to work out the strength of the force, but at some point I think those vectors might flip in relation to something… not sure. I might have to switch to using a series of cross products or something. Logically it should work, I think.

Well, the dot product between two normalized vectors is 1 if they’re pointing the same exact direction, going to 0 when they’re perpendicular, to -1 when they’re pointing in exactly opposite directions. Could that be the cause of the problem here?

Another thought, have you tried using a “Make Rot from ZX” (that’s what it’s called in BP) from the terrain normal and vehicle forward vector? That’ll give you a rotation (which you can then convert to a vector) perpendicular to the detected terrain normal, pointing where the forward vector of the vehicle should go. Would that help at all?

instead of one trace and calculate how much you should rotate and balance, how about doing 4 trace at each corner and apply force to them so they try to keep away from surface at specific distance?
It would be a simpler calculation and more robust for different terrain situations.

Problem is that quadruples the amount of traces I have to do, and also means the craft won’t ‘Perch’ on edges, it’ll just fall straight off the front and potentially get stuck. Not only that but it’ll be much harder to network reliably this way, and I want to be able to simulate a couple of hundred of these objects over a network fairly reliably too.

The single-line trace is based on a force atm similarly to how you said, but using a simple spring-physics calculation.

No offence!! I think he needs to perform exorcism on Y axis!! :slight_smile:

EDIT: Nope - Still have the Z-Rotation problem :@

I DID IT. You have no idea how happy I am. I hope this post helps anybody meeting this issue in future!

A few problems with my old method, was that I was trying to generate my normal axes from three cross products, but actually i only need two, one for the ‘Uprightness’, and then another to force the orthogonality (Direction). Using a ‘Make Rot From ZY’, this enabled me to get the rotation in world-space of the normal impact, and then rotate it locally according to the Vehicles rotation, thusly:


So using this, I can forcibly set the world-rotation of my object, and add local rotation on the Z-Axis. The object will then align itself correctly to the surface and it can rotate around the arbitrary Z-axis. This would be fine if I was using Rotators directly to ‘set’ the rotation, but naturally I had to push the boat out and use physics to drive it, by setting angular velocity directly (as opposed to torque).

Following the psuedo-code example above, I can work out the required ‘strength’ AND direction of the force properly, doing this. The key stage is the ‘Unrotate Vector’, that prevents it from being world-rotation dependant and again allows it to rotate around an arbitrary axis. As a massive bonus, it makes sure that the craft can’t ever settle when it’s upside-down, and will forcibly stay upright! ‘Nrm’ is the same surface normal, and ‘Rot’ is the rotation I generated above!


Now… to C++!

not sure if you already consider it, but the dot product can not distinguish between eg 170deg to 180deg and 190deg to 170deg. Both give the same dot product. So by default the dot product is only good up to 180deg. At higher angles say 190deg you get a disambiguity.

If you pass the 180deg mark with your vehicle, then you have to create a ‘if pass 180, then make 360deg minus the dot product result’ logic to actually achieve for example 190degs.

Yeah I knew that, luckily because I’m matching the right-vector, it knows when it’s upside down, so the countering force is applied. Otherwise if I placed it perfectly upside-down, it wouldn’t right at all but in this case it does :slight_smile:

That is awesome!