I’m working on a multiplayer antigravity racing game, a la Wipeout. I’ve got 2 C++ classes to do this: UHoverComponent is replicated 4 times to line-cast down into the ground, and UHoverManagerComponent calculates forces based on those 4.
void UHoverManagerComponent::TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction )
{
Super::TickComponent( DeltaTime, TickType, ThisTickFunction );
FVector frontHit = FVector();
FVector backHit = FVector();
FVector leftHit = FVector();
FVector rightHit = FVector();
// first, do a line trace down from each hover component
FHitResult hit = FHitResult();
if (LineTrace(FrontHover, hit))
{
frontHit = hit.Location;
}
if (LineTrace(BackHover, hit))
{
backHit = hit.Location;
}
if (LineTrace(LeftHover, hit))
{
leftHit = hit.Location;
}
if (LineTrace(RightHover, hit))
{
rightHit = hit.Location;
}
if (bDrawDebug)
{
DrawDebugLine(World, frontHit, backHit, FColor(0, 255, 0), false, -1.0F, (uint8)'\000', 2.0F);
DrawDebugLine(World, leftHit, rightHit, FColor(0, 255, 0), false, -1.0F, (uint8)'\000', 2.0F);
}
if (IsOnGround())
{
FVector groundPitch = frontHit - backHit;
FVector groundRoll = rightHit - leftHit;
// TODO: Add torque to make the rotation match the track beneath
// Once we've rotated to the ground, fix the height
float averageHeight = (FrontHover->DistanceToGround + BackHover->DistanceToGround + RightHover->DistanceToGround + LeftHover->DistanceToGround) / 4.0f;
// Add a force to the mesh inversely proportional to the distance
float compression = averageHeight / ThrustLength;
float forceStrength = FMath::Lerp(ThrustStrength, 0.0f, compression);
ParentMesh->AddForce(ParentMesh->GetUpVector() * forceStrength);
}
// Gravity pushes us "down" towards the track
ParentMesh->AddForce(ParentMesh->GetUpVector() * -1 * ThrustStrength * 0.5f);
}
The hovering works, however my problem is that rotating the mesh to match the ground does not. I’ve tried mimicking the spring physics with the pitch and roll, but it ended up being unstable and rolling around like a top. I based most of this on Z-Enzyme’s blueprint (https://forums.unrealengine.com/showthread.php?5388-U-Racer-(Working-Title)&p=58643&viewfull=1#post58643), but I’m unsure how they manipulate the rotation. Any suggestions would be appreciated.
EDIT:
Found a solution to the rotation problem:
FVector groundPitch = frontHit - backHit;
FVector groundRoll = rightHit - leftHit;
FVector normal = (FVector::CrossProduct(groundRoll, groundPitch)) * -1.0f;
normal.Normalize();
if (bDrawDebug)
{
FVector normalStart = FVector(((frontHit + backHit) * 0.5f).X, ((rightHit + leftHit) * 0.5f).Y, ((frontHit + backHit) * 0.5f).Z);
DrawDebugDirectionalArrow(World, normalStart, normalStart + (normal * 50.0f), 10.0f, FColor(0, 0, 255));
}
FVector torque = FVector::CrossProduct(normal, ParentMesh->GetUpVector() * -1.0f) * TorqueStrength;
ParentMesh->AddTorque(torque);