Download

Rookie Question: Rolling a cube

Hello, everyone, can anyone give me a mathematical explanation on how to a roll a cube in x and y-direction with 90 degrees. I tried using FRotator and it didn’t work. It seems I am having a difficult time with vectors math.

You want to just rotate it? (In which case calling SetActorRotation with an FRotator should absolutely work - although since its a cube it will be hard to see a change unless you have a way to see what side is where), or you want it to move + rotate (e.g. the player pushed the block over in a direction)?

Player control the cube. The move will roll 90 degrees every in the x direction.



FVector CubeOrigin; // Not really needed in this case
FVector CubeExtents;
Cube->GetActorBounds(CubeOrigin, CubeExtents);

FVector NewLocation = Cube->GetActorLocation() + Cube->GetActorForwardVector() * CubeExtents.X;
FRotator NewRotation = Cube->GetActorRotation() + FRotator(90.0f, 0.0f, 0.0f);

// You can then use those values to create an FTransform or what not and Lerp over a frame or so (depending on how quick you want the cube to move). If you want to move in another direction just swap GetActorForwardVector for GetActorRightVector (or subtract rather than add to move backwards/left).


Thank you ExtraLifeMatt, I will give it a shot

I tried it and is not working the way I want it. It translates the object and rotates 90 one frame. https://youtube.com/watch?v=FToE_wszlN4

I am trying to achieve what is in the video. I am asking about the math behind it, I am currently learning Vector math.

FVector CubeOrgin;
FVector CubExtents;
GetActorBounds(false, CubeOrgin, CubExtents);
FVector NewLocation = GetActorLocation() + Box->GetForwardVector()*CubExtents.X;
FRotator NewRotation = GetActorRotation() + FRotator(90.0f, 0.0f, 0.0f);

FTransform newTans = FTransform(NewRotation, NewLocation);
FTransform Trans = FTransform(NewRotation);
Box->AddLocalTransform(newTans);

Correct, because you aren’t doing a Lerp (Linear Interpolation) to control the transition.




// These would all need to be class members.

// Store your current Transform.
FTransform OldTransform = GetActorTransform();

// Now, create a Target Transform
FTransform TargetTransform = /* All the math you already have */

float SecondsToTransitionOver = 1.0f; // Let's assume you want it to rotate/translate over a second.
float CurrentRatio = 0.0f;
float TotalSeconds = 0.0f;

// In your Tick method:

if (FMath::IsNearlyEqual(CurrentRatio, 1.0f, KINDA_SMALL_NUMBER)) // It's generally not safe to compare floating point numbers directly since float point error can make it difficult to hit an "exact" value.
{
   CurrentRatio = Clamp((TotalSeconds + DeltaTime) / SecondsToTransitionOver, 0.0f, 1.0f); // This gives us a value of 0 - 1.0, 1 meaning we should be completely set to our target transform.
   SetActorTransform(Lerp<FTransform>(OldTransform, TargetTransform, CurrentRatio); // If Lerp doesn't work with FTransform, you can use FTransform::Blend
} 



Thank you, I change some of your code.UKismetMathLibrary::Clamp((TotalSeconds + DeltaTime) / secondsTransitionover, 0.0f, 1.0f);
I use UKismetMathLibrary for Clamp,
SetActorTransform, the compiler is complaining SetActorTransform(FMath::Lerp<FTransform>(OldTransform, TargetTransform, currentRatio)); Got a runtime error, it seems it take const reference of Transform and const Alpha. How exactly are you calling Lerp, what function? I don’t see the function that matches the parameters you wrote.

I haven’t written this out, just going from my memory so it’s not perfect code. :slight_smile:

You should be able to use FTransform Blend:



FTransform BlendedTransform;
BlendedTransform.Blend(OldTransform, TargetTransform, CurrentRatio);
SetActorTransform(BlendedTransform);


Thank you, I will try it now.

It seems your if statement condition is always false. Thank you. Anyone else wants to help me.

Whoops, yea, that should be:



if (!FMath::IsNearlyEqual(CurrentRatio, 1.0f, KINDA_SMALL_NUMBER)) // It's generally not safe to compare floating point numbers directly since float point error can make it difficult to hit an "exact" value.
{
  // ...
}


You’ll need to reset CurrentRatio to 0.0f any time there is a new move to make.

EDIT: Also don’t just copy and paste in code without understanding it. It’ll just frustrate you when you run into the next issue (and there will always be a next issue).

got it, well, the condition is false at the begin. I did change the value of current ratio at the begin.