I’m struggling to implement a simple solution for FindLookAtRotation
I’ve written this type of code many times before in Unreal and Unity, but I can’t get it to work quite right in UEFN
Basically ObjectA’s forward rotation needs to constantly rotate toward ObjectB (Z axis only)
I’ve tested my algorithms externally and they seem to provide correct values. Perhaps a keen eye can help me see my issue.
My attempts usually have 4 different outputs:
- The creative_prop rotates 180 degrees in the opposite direction
- The creative_prop rotates away from the player (player moves right, enemy rotates to the right–instead of to the left to follow the player)
- It rotates correctly, but constant snaps back 180 degrees and then snaps back to the correct rotation on alternating loop intervals
- My rotation gets really close to working, but has a 30-40 degree offset in either direction (never fully rotating toward ObjectB)
# Code to rotate enemy's local forward toward player
# Have tried various speeds and with/without delta time
RotateEnemy(Enemy : creative_prop, Player : player)<suspends>:void=
var PreviousTime : float = GetSimulationElapsedTime()
Speed := 5.0
loop:
Sleep(0.00)
CurrentTime := GetSimulationElapsedTime()
DeltaTime := CurrentTime - PreviousTime
set PreviousTime = CurrentTime
DeltaSpeed := Speed * DeltaTime
if (Enemy.IsValid[]):
EnemyTransform := Enemy.GetTransform()
var PlayerTransform : transform = transform{}
if (Agent := agent[Player], FortChar := Agent.GetFortCharacter[], set PlayerTransform = FortChar.GetTransform()) {}
EnemyLocation := EnemyTransform.Translation
PlayerLocation := PlayerTransform.Translation
# This is likely where our issue begins
LookRotation := MathExt.FindLookAtRotation(EnemyTransform, PlayerTransform)
ShortestRotation := MakeShortestRotationBetween(EnemyTransform.Rotation, LookRotation)
if (SlerpRotation := Slerp[EnemyTransform.Rotation, LookRotation, DeltaSpeed], Enemy.TeleportTo[EnemyLocation, SlerpRotation]) {}
else:
break
FindLookAtRotation Attempt A
# WORKS THE BEST SO FAR. Rotates properly, though choppy, but always keeps
# A strange offset (never perfectly facing player) around 30 degrees in either direction
FindLookAtRotation(LookFromTransform: transform, LookToTransform: transform): rotation =
var LookFromForward: vector3 = LookFromTransform.Rotation.GetLocalUp()
var LookToPosition: vector3 = LookToTransform.Translation
var LookFromPosition: vector3 = LookFromTransform.Translation
var LookDirection: vector3 = Normalize(LookToPosition - LookFromPosition)
var LookAngle: float = Atan2(-LookDirection.Y, -LookDirection.X)
var LookRotation: rotation = MakeRotation(vector3{X := 0.0, Y := 0.0, Z := 1.0}, LookAngle)
var TargetDirection: vector3 = LookRotation.RotateVector(LookFromForward)
var Dot: float = DotProduct(LookDirection, TargetDirection)
if (Abs(Dot) < 1.0 - 0.0001):
var Cross: vector3 = CrossProduct(TargetDirection, LookDirection)
var CrossMagnitude: float = Magnitude(Cross)
if (CrossMagnitude > 0.0001):
var RotationAxis: vector3 = vector3{X := 0.0, Y := 0.0, Z := 1.0}
var RotationAngle: float = ArcCos(Dot)
var RotationDelta: float = RotationAngle * Sgn(Dot) / 2.0
var DeltaRotation: rotation = MakeRotation(RotationAxis, RotationDelta)
set LookRotation = ComposeQuat(LookRotation, DeltaRotation)
return LookRotation
FindLookAtRotation Attempt B
# Flips the ObjectA transform to 180 and basically rotates from a backward direction
# And in the wrong left and right rotations
FindLookAtRotation(ObjectA : transform, ObjectB : transform) : rotation=
# Calculate the direction vector from ObjectA to ObjectB
var DirVec : vector3 = ObjectB.Translation - ObjectA.Translation
set DirVec = vector3{ X := DirVec.X, Y := DirVec.Y, Z := 0.0}
# Normalize the direction vector
Normalized := DirVec / DirVec.Length()
# Calculate the angle between the direction vector and the positive X axis
var Angle : float = ArcCos(DirVec.X)
# If the direction vector's Y component is negative, flip the angle
if (Normalized.Y < 0.0):
set Angle = -Angle
# Construct a rotation around the Z axis by the calculated angle
return MakeRotation(vector3{X := 0.0, Y:= 0.0, Z := 1.0}, Angle)