Files
beyond/Assets/ThirdParty/PlayMaker/Actions/Transform/SmoothLookAtDirection.cs
2024-11-20 15:21:28 +01:00

139 lines
3.9 KiB
C#

// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.
using UnityEngine;
namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Transform)]
[Tooltip("Smoothly Rotates a Game Object so its forward vector points in the specified Direction. Lets you fire an event when minmagnitude is reached")]
public class SmoothLookAtDirection : FsmStateAction
{
[RequiredField]
[Tooltip("The GameObject to rotate.")]
public FsmOwnerDefault gameObject;
[RequiredField]
[Tooltip("The direction to smoothly rotate towards.")]
public FsmVector3 targetDirection;
[Tooltip("Only rotate if Target Direction Vector length is greater than this threshold.")]
public FsmFloat minMagnitude;
[Tooltip("Keep this vector pointing up as the GameObject rotates.")]
public FsmVector3 upVector;
[RequiredField]
[Tooltip("Eliminate any tilt up/down as the GameObject rotates.")]
public FsmBool keepVertical;
[RequiredField]
[HasFloatSlider(0.5f, 15)]
[Tooltip("How quickly to rotate.")]
public FsmFloat speed;
[Tooltip("Perform in LateUpdate. This can help eliminate jitters in some situations.")]
public bool lateUpdate;
[Tooltip("Event to send if the direction difference is less than Min Magnitude.")]
public FsmEvent finishEvent;
[Tooltip("Stop running the action if the direction difference is less than Min Magnitude.")]
public FsmBool finish;
GameObject previousGo; // track game object so we can re-initialize when it changes.
Quaternion lastRotation;
Quaternion desiredRotation;
public override void Reset()
{
gameObject = null;
targetDirection = new FsmVector3 { UseVariable = true };
minMagnitude = 0.1f;
upVector = new FsmVector3 { UseVariable = true };
keepVertical = true;
speed = 5;
lateUpdate = true;
finishEvent = null;
}
public override void OnPreprocess()
{
Fsm.HandleLateUpdate = true;
}
public override void OnEnter()
{
previousGo = null;
}
public override void OnUpdate()
{
if (!lateUpdate)
{
DoSmoothLookAtDirection();
}
}
public override void OnLateUpdate()
{
if (lateUpdate)
{
DoSmoothLookAtDirection();
}
}
void DoSmoothLookAtDirection()
{
if (targetDirection.IsNone)
{
return;
}
var go = Fsm.GetOwnerDefaultTarget(gameObject);
if (go == null)
{
return;
}
// re-initialize if game object has changed
if (previousGo != go)
{
lastRotation = go.transform.rotation;
desiredRotation = lastRotation;
previousGo = go;
}
// desired direction
var diff = targetDirection.Value;
if (keepVertical.Value)
{
diff.y = 0;
}
var reachedTarget = false;
if (diff.sqrMagnitude > minMagnitude.Value)
{
desiredRotation = Quaternion.LookRotation(diff, upVector.IsNone ? Vector3.up : upVector.Value);
}
else
{
reachedTarget = true;
}
lastRotation = Quaternion.Slerp(lastRotation, desiredRotation, speed.Value * Time.deltaTime);
go.transform.rotation = lastRotation;
if (reachedTarget)
{
Fsm.Event(finishEvent);
if (finish.Value)
{
Finish();
}
}
}
}
}