Friction
There are couple of things we need for track friction. A set of “Track Anisotropic Friction” components, one per each roadwheel, sprocket and idler. The rotation and position of these components is important, in local space of the tank, their Y coordinate should be exactly in the middle of the track and X and Z coordinates should match the center of the roadwheel/sprocket/idler. The easiest way to achieve this is by making Track Anisotropic Friction component a child of the roadwheel/sprocket/idler and set their position to zero, with some offset in Y coordinate in case if pivot of the roadwheel/sprocket/idler is not centered to the track. In case if roadwheel/sprocket/idler were turned around 180 degrees (placing right element on the left side for example) then Track Anisotropic Friction component should be rotated locally 180 degree, so it’s X axis matches with the tank’s X axis. Example of such positioning and settings for the friction are following:
On a screenshot, component is a child of RoadWheelPhysicsLeft03 static mesh, which is used for collision of the track with the ground. Friction parameters MuX/MuY Static and MuX/MuY dynamic are symmetrical indicating that track will have the same friction regardless if it’s sliding sideways or not. But it’s common for tracks to have a higher coefficient in X axis than Y as they can have “grabber” element which improve traction of the track on a soft ground. “Effected component name” variable is the name of the root component or a body to which friction should be applied.
To process friction we need two auxiliary functions to glue the logic. One is “Reset Friction Points” which is called by a first OnComponentHit event of any collision mesh of roadwheel/sprocket/idler. When we use physics sub-stepping a number of collisions and OnComponentHit events will happen for each collision mesh. These events are not send per sub-step but rather per tick. For this reason, data that we capture on each OnComponentHit event is stored in array in each appropriate TrackAnisotropicFriction component. The purpose of the ResetFrictionPoints function is to make sure that on every tick, all arrays of data in TrackAnisotropicFriction components are empty, as sometimes more OnComponentHit events will happen than there are physics sub-steps to process them.
Typical implementation of ResetFrictionPoints function is following:
and this is how collision data is captured on example of a single collision body:
Each collision event with call ResetFrictionPoints, but only first one will empty arrays from left over data of previous frame. RegisterFrictionPoint is a member function of TrackAnisotropicFriction component that will store new collision data into array, to process it later on UpdateFriction cycle which will actually calculate and apply friction force.
In the next step we will look into second auxiliary function - UpdateFriction.
[to be continued]