I’m not sure what is going on. I’ve searched around and found others with similar issues and their solution was to abandon c++ for blueprints. Hoping someone can help me solve this. I have a door that should rotate out of the way, in the code I am applying a rotator and a transform in a way that the distance traveled by the door is matched by a chord angle of 180deg. The code can also adjust the speed at which the door rotates out of the way. My first attempt was to use direct rotation and transforms applied to the door’s AActor object, Then I tried turning the rotation into a quaternion and then applying it. Both methods have the same result. The log output shows the Pitch angle correctly going from 0 to 90deg but then locks and jitters between 90 and 89.699326. The Roll and Yaw also seems to have a .000100 - .000010 jitter but is un-noticeable. Interestingly, once the pitch hits 90deg the roll will bounce between 90 and -89 while the yaw will bounce back and forth between 0.000100 and -179.99054. This almost looks like a gimble lock issue but that should not happen in quat space.
Video of issue: https://vimeo.com/168490381
Code using Quat:
void UDoorRotator::RotateOpenByQuat() {
LogDoorLocation();
if (!GetIsDoorOpen()) {
AActor* Door = GetOwner();
FVector DoorLocation = Door->GetActorLocation();
FQuat DoorQuatRotation = Door->GetActorQuat();
FRotator DoorRotation = Door->GetActorRotation();
if (GetDoorTravel() < DoorMaxRange) {
float DoorMaxRotation = 180.0f; // door will rotate 180 deg, used to get a delta rotation
float TimeToOpen = 5.0f;
float CurrentTime = GetWorld()->GetTimeSeconds();
float CurrentTick = GetWorld()->GetDeltaSeconds();
float CurrentPitch = Door->GetTransform().Rotator().Pitch;
float CurrentX = Door->GetTransform().GetLocation().X;
float DeltaRotation = (CurrentTick * (DoorMaxRotation / TimeToOpen)); //ammount to rotate pitch
float DeltaX = (CurrentTick * (DoorMaxRange / TimeToOpen)); //ammount to move door
SetDoorTravel(GetDoorTravel() + DeltaX);
DoorLocation = FVector(DoorLocation.X - DeltaX, DoorLocation.Y, DoorLocation.Z); //create new location vector
DoorQuatRotation = FRotator(DoorRotation.Pitch + DeltaRotation, DoorRotation.Yaw, DoorRotation.Roll).Quaternion(); // create quaternion from rotation
Door->SetActorLocationAndRotation(DoorLocation, DoorQuatRotation); //sets new location
}
else { SetIsDoorOpen(true); }
}
else { return; }
}
Code not using Quat
void UDoorRotator::RotateOpen() {
AActor* Door = GetOwner();
bool CurrentDoorState = GetIsDoorOpen();
if (!CurrentDoorState) {
LogDoorLocation();
float CurrentPitch = Door->GetTransform().Rotator().Pitch;
float CurrentRoll = Door->GetTransform().Rotator().Roll;
float CurrentYaw = Door->GetTransform().Rotator().Yaw;
float CurrentX = Door->GetTransform().GetLocation().X;
float CurrentY = Door->GetTransform().GetLocation().Y;
float CurrentZ = Door->GetTransform().GetLocation().Z;
float MaxRotation =180.0f;
float TimeToOpen = 5.0f;
float DoorRange = 0.0f;
if (GetDoorClosedPosition() < GetDoorOpenPosition()) {
float DoorRange = GetDoorClosedPosition() + GetDoorOpenPosition();
}
else {
float DoorRange = GetDoorClosedPosition() - GetDoorOpenPosition();
}
if (CurrentX > 3048.0f){
float CurrentTime = GetWorld()->GetTimeSeconds();
float CurrentTPS = GetWorld()->GetDeltaSeconds();
float CurrentPitch = Door->GetTransform().Rotator().Pitch;
float CurrentX = Door->GetTransform().GetLocation().X;
float DeltaRotation = (CurrentTPS * (MaxRotation / TimeToOpen));
float DeltaX = (CurrentTPS * (300.0 / TimeToOpen));
FRotator NewRotation = FRotator(CurrentPitch + DeltaRotation, CurrentYaw, CurrentRoll);
FVector NewTranslation = FVector(CurrentX - DeltaX, CurrentY, CurrentZ);
Door->SetActorRotation(NewRotation);
Door->SetActorLocation(NewTranslation);
LogDoorLocation();
}
else {
SetIsDoorOpen(true);
}
}
}