'Scaling rolling ball controls with it's size

I am editing the rollingball example map from Unreal (in Unreal Engine). I changed it so my ball you grow and melt (it's a snowball), gaining and losing size and mass.

My problem is the control of it. The example map moves the ball by adding torque. My problem is that my mass changes a lot, so I need a torque the changes depending on the size of my ball (not 1:1 as a bigger snowball should still moves slower).

My problem is that my ball seems to accumulate torque and spins a lot (I added a lot of friction to the ball, it did not helped, it just moved the problem a bit). As an example, if I press left for a while, it's gonna go left. Then if I press right, it goes right. But when I stop pressing right, it spins and goes left again.

This is my current code:

void ASnowballBall::MoveRight(float Val)
{
    const FVector Torque = FVector(-1.f * getNewTorque(Val), 0.f, 0.f);
    Ball->AddTorque(SpringArm->GetComponentRotation().RotateVector(Torque));
}

void ASnowballBall::MoveForward(float Val)
{
    const FVector Torque = FVector(0.f, getNewTorque(Val), 0.f);
    Ball->AddTorque(SpringArm->GetComponentRotation().RotateVector(Torque));
}

float ASnowballBall::getNewTorque(float Val)
{
    return (Val * RollTorque * (log2(Ball->GetMass()))) / 10000;
}

Note: The log was a test to increase the torque slowly with the mass. It's not working well at all. Right now I am using return Val * RollTorque instead, but it's almost as bad.

The control is horrible and I would like to get an idea on how to fix it. If removing the torque would be better, I will change it. I simply want a responsive control that is fun, and where the player still have a sense of the size of the ball (slower when big compared to small).

PS: My original mass is about 500 kg and can go up to 20 000 kg (it's a puzzle game). I did not set the original mass, it's set by Unreal relative to it's size. I could change the mass scale though.



Solution 1:[1]

You could try using AddForce instead of AddTorque. So the speed of the ball is modified every tick like this:

void APlayerBallBearing::Tick(float deltaSeconds)
{
    Super::Tick(deltaSeconds);
    
    BallMesh->AddForce(FVector(InputLongitude, InputLatitude, 0.0f) * ControllerForce * BallMesh->GetMass());
}

InputLongitude and InputLatitude are the values that are put in by the user in the current frame for movement in cardinal directions, they correspond to your MoveForward and MoveRight values I reckon.

The controller force is something you need to tweak in order to find the right value for your ball movement. With a value of at least 600.0f I started getting "decent" behaviour.

I cannot help you with the mass though you would need to try that out yourself, the default mass of the ball mesh I used was ~110.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tyler2P