Thanks that did the trick!
Ohh, I see now. Apology for confusion. What I was trying to say is that if you have for example two gearboxes, which are connected to two separate tracks. Each track would have to find a “proper” gearbox. As you will be providing input into left or right gearbox depending on the direction of steering.
Components which require the most of manual name references right now are track friction points. For them I could do a simple fix where you have to provide only name of the “effected” component (which would be root static or skeletal mesh) and for reference component it can automatically pickup its parent. But this might not be explicit enough, especially with the way how hierarchy is presented right now in editor GUI - just by name indent, where it could draw a bit of lines, as a ts done in Unity I don’t think.
At the same time, there are other unrelated to tank components which won’t work like that.
Long term solution is to start moving components into c++ implementation. Then they can include both logic and necessary meshes inside of a single component.
Update
Found a very simple but powerful fix for the friction simulation. Previously it was difficult to settle simulation when vehicle was standing still. It comes from the fact that simulation of the friction force is done in reactive way, meaning that friction force is created after some change in velocity was detected. That’s unfortunate limitation of how we can work with PhysX engine without going deep into a source code:
https://answers.unrealengine.com/questions/303525/feature-request-is-it-possible-to-get-force.html
When vehicle is driving, reactive friction works just fine. The problems start when vehicle is standing still on the ground and we get a little bit of velocity from the suspension pushing wheels around. Just a small amount of such velocity leads to a friction force pushing wheel back into place, which creates velocity by itself, to which friction reacts again but now in opposite direction. So we end up with friction forces indefinitely pushing wheels left and right, which leads to a jittering of the vehicle and prevents it from setting physics objects to sleep:
Pink vectors are friction forces. One of the fixes to this, is to rely on build-in friction model on very low speeds. For this, all collision objects that need to simulate anisotropic friction (wheels/sprockets/ski) are given physics material with very low coefficient of friction, instead of “no-friction” material as it was before. now we just need to disable our custom anisotropic friction when relative velocity between wheel and ground is very low (like less than 1cm/s) and build-in physics friction will stop vehicle completely and put physics to sleep. Unfortunately this doesn’t work because of mentioned earlier issue with settling forces. Forces shown earlier on the screenshot, create relative velocity of about 10 cm/s for that specific vehicle, which is significant amount for this particular application. When tank is moving full speed ahead, it’s tracks can have almost zero relative velocity with the ground if they are moving in opposite direction almost as fast as tank itself. So disabling custom friction calculation at small relative velocity can take away important physics simulation when tank is in motion. So by trying to fix a “standing still” issue with brake dynamic case of simulation which is obviously more important.
Solution to all this is rather simple - average relative velocity of the friction point over last two updates. This almost completely removes any reaction of friction force to jittering of the vehicle (springs and physics constraints can have small barely visible vibration even with good damping settings, this is more related to collision detection and respecting of constraints). This is how the same situation looks like after averaging relative velocity:
Together with addition of very small velocity threshold and “small friction” physics material, vehicles will now stop properly and get into sleep state. Which is great for performance and ability to find you car in the same spot as you have parked it
I’m still working on drive train:
Got most of the code done for simulation of engine, gearbox, clutch and a simple wheel. Drive train components are modular, so you can just add as many of them as you want and describe how they should be connected to each other. The rest is done automatically - how much torque, angular velocity or moment of inertia you have at specific parts of drive train. The wiring of components is minimized to calling two types of update functions, it can look like a train of nodes in real drive train but practically you can always just copy paste it from one car into another. Right now I have some issues with the settings of parts of drive train, clutch force is too large and moment of inertia on wheel is too high. I’ll do a proper update when this is finished
this just keeps getting better and better.
Finally done with a 2 month assignment so can pick this up again…
One thing I really need to start looking into now is if this works in multiplayer and if no… why not and what needs changing.
Good question. I would add it out of the box if I knew how. I think @Dealman managed to make it work in multiplayer.
So if someone know what need to be done, I can add it into the project by default. For example, if we are looking for the simplest case of running physics on client with client authority.
All I did was set the hull to replicate, it seems to have worked for the basic testing I wanted to do. I’m not sure whether that tries to simulate the physics altogether or just the velocities. It did behave a bit odd when slowing down, acceleration seemed pretty smooth though. :rolleyes:
Might be interesting to run some crash tests in multiplayer
Since this uses custom physics, I wonder if this would work with other UE4 projects that involve physics, like the OceanProject
Sure, what is meant by custom physics, in the first post, is not using PhysX template for the vehicles but doing calculations directly in game code. PhysX is still used to handle rigid body collision and process forces. The way it works, for example with friction: we measure relative velocity, calculate necessary friction force and apply it to vehicle using AddForceAtLocation(). From there, physics engine will handle changes in velocity linear and angular velocity, rotation and position.
Not sure if I understood it correctly. In a nutshell, the difference between MMT and normal physics in UE4 is that you update your physics positions/forces/impulses during each substep, while ‘normal’ physics in UE4 updates only at the end of a full substeps cycle. That’s the novelty here as far as I understood.
This per-substep updating is only active for your nodes that you created and use in MMT and it does not mess around with the other physics in the project, right?
What plugin does is provides you “MMT Physics Tick” event to run almost any kind of code during physics sub-stepping. It uses the same AddForce() functions, as BP is using, but with extra parameter that is not exposed. That parameter tells if AddForce(), AddTorque() and etc. are called from the physics sub-step or from regular tick. So all this works just as any other physics code works, just with ability to utilize sub-stepping.
Just want to highlight that per-substep updating is active for almost everything that you call from “MMT Physics Tick” event. I’m highlighting almost because practically, code invoked by such event is running in parallel thread, so you can’t call regular draw debug commands or print string (I’ve build separate components for that, which are “thread safe”). Other than that you can do pretty much anything. In some cases this might even improve performance as your “simulation” code runs in a parallel to the game thread (as long as it’s not so heavy that you stall physics thread).
You can mix this with any other code that you have, as long as you are ok with Pawn (I’ll add physics sub-stepping Actor too) having a Pre-Physics tick group, as otherwise you can’t get “custom physics” delegate on c++ side.
Actors would be interesting to see. That would enable more things than just the standard pawn based Unreal Engine project.
I wonder how joints would be affected by updating after each substep. Basically how would a ragdoll composed of actors (static meshes) and joints or joint motors behave…
With actors, you could also set up a side by side project with identical actors: one with substepping updates and one without. That would be interesting to see the difference.
It would behave the same way as if you are using standard physics constraints as physics constraints do use sub-stepping when it’s enabled. I’ll add actors then, it’s literally just copy/paste of Pawn code with a different base parent.
no need for the actors, we can do it ourselves at some point. We just want to collect infos.
How about collision? They write they only collect collision at the end of a full substeps cycle for performance reasons, but it sounds as if you could well do it after each substep, even if it is more expensive.
Do you have a rough idea how easy/difficult it is to change code to do collision per substep?
@0lento did mention in one of our conversations that it’s possible to receive collision event between sub-steps, but it did involved modifying engine code. The way solved this for light tank is by adding results of collision events into array in each TrackAnisotropicFriction component and then removing them after processing. Which might be not too accurate at low fps but works in general.
The line mentioned here is this:
https://github.com/EpicGames/UnrealEngine/blob/4.11/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysScene.cpp#L1356
DispatchPhysNotifications_AssumesLocked() gets called at end of full physics frame. I haven’t modified the engine myself to make that happen on each substep but it shouldn’t need more than just placing that line where each substep ends.
What you can do without modifying engine though is copy/paste this for loop and use it as a separate function on your own project and call the function at start of each physics tick:
https://github.com/EpicGames/UnrealEngine/blob/4.11/Engine/Source/Runtime/Engine/Private/PhysicsEngine/PhysScene.cpp#L1124
I also needed to handle SwapContactOrders() manually there, but you can trace back that code as well from sources. This is quite hacky though, so if you can just modify the engine it would be a lot cleaner way.
I think doing it without modifying the engine is better, unless it is done with support from Epic.
It might be paranoid thinking, but when something breaks your game and it only appears after you published, then you can lean back and finger point at Epic when they torch you on the Steam forums and in the reviews.
Like with the one game where it turned out UE4 has problems with AMD sound drivers (I seem to remember). They just threw the ball into Epic’s court (where it belongs in such cases) because they used the Engine out of the box. Had they tinkered with the engine, the problem would have been much bigger, also in terms of actually resolving it.
If you modify something yourself, it is a bit like destroying the warranty.
The bad part of this is that since that code that would need to be included on project is actual engine code, it can’t be included on open source project that is freely available to all. So even if wanted to include that on MMT, license technically doesn’t allow it on it’s current distribution form (only possible way to work around that would be to fork full UE4 github repo and include the plugin with it, this is how Allegorithmic does this for substance plugin).
Nothing is stopping you on the other hand from doing it yourself and using on that on your own projects as long as you don’t share engine code yourself to other than verified UE4 licensees.
Update: Modular Drive Train [work in progress]
In this update I’ve added basic components for modelling behavior of the drive train. Small video to demonstrate current features:
A lot of credit for this system goes to 0lento as it wouldn’t be possible to implement this without his help!
Each component of the drive train is build to be used as replaceable module. The main motivation for this is rather simple - to avoid writing custom implementation for each configuration of the drive train. Let me show you what I mean by this.
This is a typical configuration of the car’s drive train:
If you are building a car racing game, most likely you will be implementing such drive train in one way or another. When you start to add features, such as ability to stall engine, engine drag, locking collar of gear box to gears and etc. you might find yourselves re-writing quite a lot of code as each new feature might require different implementation of other features. Still, it’s not too bad as long as general configuration of the drive train stays the same. For example, A_Tracked_Vehicle uses similar configuration with a bit of a trick to enable neutral turn.
When configuration changes, you can get into a bit of the trouble as certain assumptions that were true before, such as integrating velocities only at wheels and engine, are not true anymore and integration of velocity have to be done in more places. This is the case with old British and Russian tanks:
What they did, is installed clutch for each track in addition to main clutch between engine and gearbox. Driver would have two levers, one for each track, by pulling the lever half way he would control locking of the clutch. Un-clutched track would naturally slow down and tank will start rotating as other track is rotating with full power. By pulling lever even further, it would enable track brake and turn would happen even more rapidly. Mechanically, this wasn’t very efficient but very simple system and was quite common on early tanks of WW2. To implement such configuration, we need to integrate velocities in multiple places. The main problem is that we can easily get into combination madness of levers position and how and where torque should be transmitted.
To make it even worse, let’s look at next exhibit:
As far as I know, such system was used on quite a few tanks of WW2, as it was more energy efficient than clutch-brake system and provided driver with a combination of turning radii by switching each steering gearbox into a different position. This is the first practical system which allowed neutral steering where each track would rotate in different direction.
Practically, you might not need more than a first configuration, unless you are building more of a simulator and want to highlight differences in vehicles performance and steering. But even in such case, you can have cars with automatic or manual gear box, 4WD or RWD, or even switchable between them as on many SUVs. Modular system will allow you to just change your components and don’t bother with a custom logic for each configuration.
How it works?
[to be continued]
How modular drive train works
Each component of the modular drive train needs to implement “DriveTrainModuleComm” interface which has 4 methods:
- DTUpdateFromSourceToApplication
- DTUpdateFromApplicationToSource
- DTReceiveDataFromSourceSide
- DTReceiveDataFromApplicationSide
“Source” means side of the drive train with the engine and “Application” means side with wheels/tracks.
The idea is that on each Tick (or physics sub-step Tick) each component is “updated” twice and each “update” ends with sending resulting data to next component up (or down) the chain:
So if engine is connected to a clutch and clutch is connected with gearbox. We start with updating engine using “DTUpdateFromSourceToApplication” function call, which sends data to the clutch using “DTReceiveDataFromSourceSide” function at the end of the update.
Now as clutch received data from the engine, it does it’s own update in “DTUpdateFromSourceToApplication” and sends data to gearbox. In this example, gearbox is the last component and there is no data to send further. As we reached the end of the chain, we start to update components in the backwards direction - gearbox->clutch->engine. For this we use “DTUpdateFromApplicationToSource” functions and “DTReceiveDataFromApplicationSide” to pass data.
This way each drive train component can do it’s own calculations as a “black box” and the rest don’t need to know anything about it. For example, engine doesn’t need to know if clutch is locked or not. When clutch is unlocked (completely released and not slipping) clutch will just pass back the same angular velocity to the engine as it received from the engine. When clutch is completely locked (not slipping) it will pass angular velocity received from the engine to the next component, which decides on it’s own what should be done with it.
The only other consideration is regarding components that can integrate velocity, meaning that they apply torque to change angular velocity on their update. Such components are engine, clutch, gearbox and track sprocket or wheel hub. Not all of them integrate velocity all the time, only when their logic requires to do so. For example, engine integrates velocity on every tick as final engine torque changes with RPM and throttle position. Clutch integrates velocity only when not completely locked as clutch plates will produce friction force. Gearbox integrates velocity when you shift gears and synchro produces friction force to match velocity of lay and drive shafts. Wheels or tracks, integrate velocity from the reaction force as the result of friction with the ground. The pattern is pretty clear: each component that creates or receives torque from outside of the drive train or can “disconnect” drive train - will integrate angular velocity.
When components “disconnect” drive train, such as clutch or gear box, they integrate velocity on their “application” side of the shaft. The “source” shaft is considered as responsibility of the component previously in the chain.
In feature posts I’ll describe each of the implemented components.