The Re-Inventing the Wheel Thread

As additional note, if you use constraints for spring + damper, this is not as critical as their forces will be updated by physx on each physics step already.

Checked the project - works really well and smooth. Tried with different maxFPS settings and it seams to behave stable all the time.
During last test I’ve changed amount of sub-steps to 16 and it started to crash somewhere in Tick(). Keeps crashing even if I set sub-stepping back to 6 as default. Works fine again after disabling sub-stepping. Kind of weird, before I’ve touched those setting it didn’t crash even ones.

Heh, well, I have no proper knownledge of the actual limitations, like how often you can call BP nodes so this all is highly experimental. To be honest, I was surprised that it even worked in the first place. Did you get the crash with draw debug trace setting on or without it? Because if it’s on, it’s almost expected to crash as some point. I kinda put that setting just to test it, but in real project you should do your own debug draws from tick instead.

I tried with that debug draw off, 16 substeps, max substep delta time at 0.005 (so set to calculate physics 200 times in a second) and maxFPS at 10. I couldn’t get it crash here. Can you tell where in the engine it crashed?

Ohh, you are right, debug was enabled. Silly me.
I’ve used 4.10.2 to open it.

I’ve tried enabling sub-stepping in my “tanks project” to see what kind of changes I get. Few things start to behave really weird, like all suspension becomes bouncy, I guess because there is no AddForce() call on substeps only on regular ticks. Another weird things was how constraints are much less reinforced, this was very surprising. Anyway, it’s clear that I should start moving to running physics with sub-stepping and switch to component based system.

I’m now wrapping this whole thing into a plugin so it can work in BP only projects. Found an interesting bug, when you enable sub-stepping and have a component in hierarchy which calls a normal Tick() event it crashes. I’ve reproduced bug using your code - as you more familiar with it.
https://www.dropbox.com/s/tdcs05mdvm5ueao/SubstepExample_Extended_Crashing.zip?dl=0
If you delete Tick() event from TestComponent (delete from the BP graph), then everything is working fine.
c8ac34b4cf4a3b30e6c4acce80da5374391325f1.jpeg

I’m not sure what is going on, perhaps component’s Tick() is invoking the same function in the pawn class. I could submit this as bug report but I’m not sure if Epic’s stuff is going to look at it as it’s a custom C++ code…

According to documentation USceneComponent doesn’t have it’s own Tick() neither it overrides it, it’s inherited from UActorComponent which does have a tick component.
Perhaps Tick() call from component causes an additional Tick() on Root, as it’s higher in hierarchy, but that would only execute RootBodyInstance->AddCustomPhysics(OnCalculateCustomPhysics); second time.

0lento, do you mind if I post your code in the Bug Reports? Maybe someone from Epic can take a look at it.

But I can call PhysicsTick() instead of normal Tick() just fine, even with sub-stepping enabled, setting location of objects and AddForce() works and as expected it crashes on DrawDebugLine(), so at least I know it’s being called with proper frequency.

I was looking if I can overload GetWorldLocation() and similar methods but apparently those BP nodes are defined in EditorEngine.h so we have to go with custom methods for sub-step friendly queries.

We can run project side plugins on BP only project nowadays? I thought we still had limitation for having to use at least a dummy c++ file so it gets treated as a code project. If you have to run it as c++ project, you could use a pawn or regular c++ component for it and it would work the same. I’m mainly using regular project side pawns and components myself for vehicles because I never really saw the need for making it a plugin and it also seemed more straight forward to debug regular code projects.

I’ll check it and report back.

Since this is really hacky approach and definitely not how the engine is designed to be used, I wouldn’t submit a bug report about this (unless your issue can be reproduced without this substepping hack).

I use Tick override on my own components which are inherited from USceneComponent (in c++) and haven’t had any issues with that. Only things I can think of right now is to make sure that your component itself is properly activated and it can tick (have PrimaryComponentTick.bCanEverTick = true; on constructor). You also need to use TickComponent instead of regular Tick. I’ll check these when I start looking at that project.

edit-> forget about the last paragraph, was thinking about c++ instead of BP :slight_smile:

I could reproduce this. It only crashes if you have your component set to tick During Physics (default setting). I’ve always set mine to Pre or Post Physics. I tested all the possible settings and only during physics made it crash.

tick_group.png

Not yet, but fix might arrive soon. This is more for the people who prefer to use BP, most of the “sub-step friendly” components will be done in BP and then I’ll move some of them into c++ as part of the plugin. I do agree that reading and debug c++ is easier but for someone who doesn’t have much experience with it its rather a steep wall to climb.

Thank you! This is an easy fix. In this case I could add a basic component into a plugin and enforce TickGroup from the code. But for other pre-build components this would be a requirement to handle in editor.

Hi there,
so I’ve opened plugin to public, I know you guys don’t like blueprints that much but perhaps you’ll find it interesting:

0lento raised several good concerns regarding performance and perhaps it’s a good idea to move some of the heavier components to c++. It makes sense to move even lighter one like AirDrag, not only for performance but usability as well, as some sort of visual interface can be added to setup it’s variables. Or other c++ components can be extended to have both visual and functional representation. I’m planning to add all kinds of things, like wheels, tracks, airfoil, pretty much all prototypes which were build so far. Feel free to join, it’s an open source project.

Hi, first of all I would like to thank the work you did on the script and everyone contributions.

I have looked over the code in the script and I have found a few errors, the first error I found was in the rotation of the visual wheels, where the rotation keeps being accumulated and it will eventually reach a float limit, when that happens the wheel will ofc stop visually rotating, although that should take quite a while to happen depending on the application and so on.


WheelArray**->SetRelativeRotation(FRotator(CurrentWheelPitch**, CurrentAngle**, 0.0f));

I haven’t fixed this yet but it’s just a question of not doing the rotation in an accumulated fashion.

The second error I found was


FVector DragForce = -Vel * SpeedKPH * AirResistance;

Where there is a multiplication of a cm/s value with a km/h value, now this does not result in any error that affects gameplay, since in the end it’s all being multiplied by another value, but it’s technically incorrect, it should be multiplied by cm/s, or ofc Vel changed to km/h too.

The next error I found was here:


if (!bOnGround[Index]) {PreviousPosition[Index] = SpringPosition;}

This is incorrect because if it was not on the ground it means that previous position was the TraceLength not the current position, in my case I just eliminated the entire if and passed the assignment of previous position to the else



			else {
				bOnGround[Index] = false;
				SpringLengthArray[Index] = TraceLength;
				/*Much Like SpringPosition, PreviousPosition is not the position but the length*/
				PreviousPosition[Index] = TraceLength;
			}


Although I would change the if to be !Hit.bBlockingHit to change the order of things so the code is clearer to read, but that’s a matter of taste. The results of this fix will barely be noticeable since it only happens during the tick where the wheel touches the ground, it is still incorrect.

The next piece of incorrect code I found was this:


FVector TotalForce = Hit.ImpactNormal * FVector::DotProduct(Hit.ImpactNormal, SpringForce * BodyUpVector);

This creates a problem in extreme angles between the car the ground, where the total force that ends up being applied is far lower than it should have been, and for this to be correct it would also mean that the very way in which the traces are made would be incorrect, since the angle in which they are made should at least in a simple model like this represent the way in which the forces are applied.
The correction I believe is this


FVector TotalForce = BodyUpVector * SpringForce;

The next mistake I found is the cause of the car just launching into the air and for it to get a speed boost after flipping over:


float GripMultiplier = FMath::Max(TraceLength/SpringLengthArray[Index], MaxGrip);

That line is incorrect, MaxGrip in this case would actually be MinGrip, since the FMath::Max as it’s name implies chooses the maximum value of the two, so MaxGrip is actually selected only when it’s the bigger value of the two, not when it’s the smallest, to actual get a max limit the function to use is FMath::Min since this one will select the smallest of two values and that means you can always be sure that you will never get a value larger than MaxGrip.
So in short the correct line would be


float GripMultiplier = FMath::Min(TraceLength / SpringLengthArray[Index], MaxGrip);

This change eliminates the car flying and the boosts the car got after rolling over.
There is the same error inside AddDrive, although given the configuration of the default car and the fact the value of AddDrive is clamped this problem doesn’t really show itself there (still needs to be fixed ofc).

Found some minor errors in AddDrive and AddLatGrip where FVector Dir was not being used and BodyLocation being created but not used aswell.

Finally I believe the AntiRoll model is not correctly done, I haven’t done proper testing on it since it was the last part I checked so take it with a grain of salt, but I believe the assignment of AntiRollForceF should take zeroed FVector(0.0f , 0.0f , 0.0f) instead of FVector() since from the quick test I did it would seem FVector() does not assign a 0 value vector, but instead the current position of the object or something (once again didn’t test it properly).
The entire model also seems to be incorrect if the model that I believe inspired it http://forum.unity3d.com/threads/how-to-make-a-physically-real-stable-car-with-wheelcolliders.50643/ is to be believed, the original model doesn’t use forces and does things all around differently.



		float AntiRollForceF = ((SpringLengthArray[0] / TraceLength) - (SpringLengthArray[1] / TraceLength)) * AntiRollFront;
		float AntiRollForceB = ((SpringLengthArray[2] / TraceLength) - (SpringLengthArray[3] / TraceLength)) * AntiRollBack;

		if (bOnGround[0]) {
			SpringForceArray[0] += BodyUpVector * -AntiRollForceF;
			BodyInstance->AddForceAtPosition(SpringForceArray[0], SuspForceLocation[0], false);
		}
		if (bOnGround[1]) {
			SpringForceArray[1] += BodyUpVector * AntiRollForceF;
			BodyInstance->AddForceAtPosition(SpringForceArray[1], SuspForceLocation[1], false);
		}
		//back
		if (bOnGround[2]) {
			SpringForceArray[2] += BodyUpVector * -AntiRollForceB;
			BodyInstance->AddForceAtPosition(SpringForceArray[2], SuspForceLocation[2], false);
		}
		if (bOnGround[3]) {
			SpringForceArray[3] += BodyUpVector * AntiRollForceB;
			BodyInstance->AddForceAtPosition(SpringForceArray[3], SuspForceLocation[3], false);
		}


I believe the code above would be the correct implementation of the other model in UE4, but once again haven’t really tested it properly so could be wrong, and if I am please do correct me on it, also for this to work it requires the “PreviousPosition[Index] = TraceLength;” on else change to have been made.

Thank you.

Hi HunterPT,

since some of the points you’ve mentioned are based on my code snippets, I’ll try to explain the reasoning behind them. Do note that I haven’t fully read all the code of this plugin so can’t comment other parts of the correctness of it.

That’s something I put into my initial substepping example here: The Re-Inventing the Wheel Thread - Community & Industry Discussion - Epic Developer Community Forums
To be honest. I’m not quite sure why I put it there. Basically only thing it does on it’s original form is that it prevents damper to counteract when you return to ground at that specific moment but that’s about it. I’m sure there was some logic behind it but I really can’t remember it anymore. Anyway, removing it should be just fine.

I suggested TegLeg to try that dotproduct there. You are right about it not being fully correct but just using UpVector * SpringForce isn’t either. What I suggested there is a compromize that works most of the time well and I didn’t find any bad side-effects for it.

I’m explain this bit further:

For example, if you just do BodyUpVector * SpringForce and have your vehicle aligned so that front of the body is lower/higher than it’s rear., then that force will actually push the vehicle slightly forward/backward as well, also sideways if body is leaning left or right. On inclined surfaces, this is correct, but if your wheels are on even surfaces (think about stairs or any steps for example where the tires itself are on flat even surface) your vehicle should stay still and not move at all.

If you calculate suspension force by multiplying it by linetrace’s hit.normal like I did on my original code snippet (which wasn’t meant to be used as vehicle suspension as is), then it would work on that stair example right, but it would mean spring actually acts in all directions instead of just up.

So the compromize I suggested was to use that but for only the part of the force that can act in vehicles up direction (assumption that springs move directly up and down in this case), it’s kind of combination for those both but in extreme angles it just gives you too low values. Again this isn’t fully correct way to do it, but if you want to do it right, you have to take a lot more forces into account for the wheels themselves.

I’ve made that same point earlier on this thread too. There is force involved as AntirollCoeff though (its 5000 N/m on that Unity example). In vehicle dynamics literature, antiroll bar is sometimes approximated in form of ForceARB = AntiRollCoeff * (SuspensionPos1 - SuspensionPos2) which is essentially what you are doing there. You may normalize the values to tracelength like you do there, but you’d just need to use bigger Coeff force then. By the way, there are ways to calculate that force coeff from ARB dimensions as well but in the end, since this is still a very rough estimate, you’d just find a good value that keeps your vehicle from tipping over too easily.

If you want to share your version of the fixed code, it would probably help others the most :slight_smile: As a side note, I think that if people want to build a community based vehicle model, it should probably be in github etc place where it would be easier to manage and get people’s pull requests and forks handled better.

That being said, you may also want to check BoredEngineers MMT-plugin ( [OPEN-SOURCE] Machinery Modelling Toolkit - World Creation - Epic Developer Community Forums ) as he’s done lots of vehicle related things there as well. MMT is still missing 4-wheeled vehicle example but I think if people concentrated on one community based open source solution, it would benefit all. Most of the actual content there is implemented in BPs but it shouldn’t be that hard to convert those into c++ or eventually build both c++ and BP examples for different types of vehicles.

If you have any further questions / thoughts about vehicle physics, feel free to ask here or come join us at UnrealSlackers or #unrealengine IRC-channel @freenode. :slight_smile:

Thanks for the reply,

I saw your motive for that dotproduct a few pages ago, but I completely misunderstood what you meant at that time, now I understand and yeah I tested it and definitely a problem on stairs, had completely missed it so thanks for pointing that out.
It does however have one advantage in what concerns the tegleg 0.4v, in that if you put the car in some stairs with the dotproduct the car won’t go down the stairs on it’s own, while with the bodyupvector it will, now it’s obviously going down the stairs for all the wrong reasons, since that kind of force shouldn’t be coming from the suspension but it still leads to a more realistic looking behavior in this very specific case, although you can’t put the car backwards on stairs as in some positions (not always) it will try and climb the stairs on it’s own, which safe to say is not a realistic behavior.

Anyway at this moment not quite sure what the correct solution to the problem is, although there is one very hackish yet likely effective solution to the problem, which is to use your dotproduct solution then check the vector magnitude with .Size() compare it to springforce and if it deviates by an X amount it applies the bodyupvector solution instead, since if it deviates by a good amount it means the situations is one where the BodyUpVector is more correct.

BTW testing out the stairs situation I did run into another possible bug, but haven’t check to see where it comes from, the bug is that if one removes the suspension calculations, which effectively puts the car completely on the ground, when turning the car is able to make a full turn on one side, but on the other side it only turns so far, this might not be a bug with the code, it is possible that it’s the collision mesh that is non symmetrical and causes this issue, and ofc it’s something that won’t happen in a realistic use case scenario, but it might be indicative of some incorrect piece of code.

As for the anti roll bar yeah prefer to input the values manually for that, they aren’t all that hard to tweak, and for my specific case I will only have 1 vehicle so the extra work is minimal.

Unfortunately don’t have any more code to share, I mean I could share the entirety of my code, but everything that I didn’t already share is the same as the tegleg 0.4v so it’s not of much value, anyway going to start my own implementation of vehicle physics, just used tegleg to get a grasp on how to use substepping, UE4 physics and so on, since I had never programmed in c++ or used UE4 before, although I won’t be able to share that one, not that it would be of much use to most people anyway since it’s going to be for a somewhat unusual vehicle.

Boredengineer work looks quite good, had seen it before, he was actually featured on the unreal engine sequencer twitch stream yesterday.

Since you are offering to answer questions I do have one question, I saw this article http://www.aclockworkberry.com/unreal-engine-substepping/#Fixed_Frame_Rate and in it he mentions the following:

“Finally I’m defining some utility inline functions to get position, rotation, velocities directly from the rigid body. This because body transformations aren’t updated until the end of physics tick, so you have to read them from PhysX rigid bodies to get the updated values from the last substep.”

Basically unless I’m missing something he seems to be dealing directly with the Physx objects, and I’m not quite sure why he is doing that, he says that you need to do that to get the updated transform values from the last substep, but doesn’t using the FBodyInstance* BodyInstance give the same results, I have setup a counter and logged both the counter and the body location after having heavily decreased the Max Substep Delta Time, and unless I have done something wrong the FBodyInstance* BodyInstance was reporting an updated position of the BodyLocation in each substep.

Thank you.

Thanks for the link, I haven’t seen that one before. He is basically doing the same thing as we are doing with using BodyInstance but he does it directly from Physx scene. You can do it directly with physx and it’ll remove some overhead from the process. FBodyInstance is really a wrapper that does those same things under hood to get data from physx scene to unreals world.

I’ve used physx directly on my own prototypes as well but using BodyInstance for reading the values is easier as you don’t need to include physx stuff on your build settings and includes + it takes care of some safety aspects like thread locking and getting the values correctly.

That being said, if you don’t use BodyInstance directly and try to use Unreal’s regular getters for world space location for actors and components, their rotations etc, they only get updated right before each tick and that’s probably the thing he was trying to avoid.

Forgot to mention another problem that anyone that intends to use this needs to fix at some point, which is the particles not being deleted, this eventually leads to the editor crashing, haven’t bothered to fix it so can’t present code, but shouldn’t be too hard.

Thanks for the reply, I now see when to use Physx directly.

One other reason to use physx directly is to get some helper functions that are not exposed to UE4 physics natively. For example these can help you as you can add forces directly in local space etc:
http://docs.nvidia.com/gameworks/content/gameworkslibrary/physx/apireference/files/classPxRigidBodyExt.html

You can move between local and world space fairly while using UE4 physics though, those physx functions just take away the need for you to do the conversion manually. Since I mentioned this, those conversions can be done easily by using FTransforms TranfromVector & InverseTransformVector for forces and TransformPosition & InverseTransformPosition for locations if you prefer to stay on UE4 api.

Does the plugin work in 4.13 or 4.14?

hi! I tried to do skid marks like your’s using a ribbon emmiter particle and was almost successfull, altho it is far from beign smooth enough, would you mind pointing me in the right direction? thanks :slight_smile:

Yes and now for some reason I get this problem in 4.14 with new physics and Epic Don’t provide a fix and don’t find the problem 4.14 Nvidia update physics/traces broken - World Creation - Epic Developer Community Forums to some users work without problem to other like me give problems. But is not a problem with this vehicle rater looks like a problem with the new PhysX lib…

This is UE4.15 even worst

https://dl.dropboxusercontent.com/u/28070491/GIFShit.gif