Files
TheVVaS-Assets/RPGCore.Movement/Runtime/ObjectModules/UnitMovement/Actions/RotateAction.cs
T
2026-04-25 23:37:10 +02:00

121 lines
3.9 KiB
C#

using System.Collections;
using RPGCore.ObjectModules.ActionObjectModule;
using RPGCore.StatusEffect.ObjectModules.StatusObjectModule;
using UnityEngine;
namespace RPGCore.Movement.ObjectModules.UnitMovement.Actions
{
public class RotateAction : BaseActionParallel
{
private Coroutine _rotateCoroutine;
private readonly bool _isEndless;
private float _targetYaw;
private readonly float _rotationSpeed;
private readonly bool _isForced;
public RotateAction(float rotationSpeed = 0)
{
_isEndless = true;
_rotationSpeed = rotationSpeed;
}
public RotateAction(float targetYaw, float rotationSpeed = 0, bool isForced = false)
{
_targetYaw = targetYaw;
_rotationSpeed = rotationSpeed;
_isForced = isForced;
}
public RotateAction(Vector3 lookAt, float rotationSpeed = 0, bool isForced = false)
{
_targetYaw = Quaternion.LookRotation(lookAt - unit.transform.position).eulerAngles.y;
_rotationSpeed = rotationSpeed;
_isForced = isForced;
}
public void SetYaw(float targetYaw)
{
if (!_isEndless)
{
Debug.LogWarning($"Usage {nameof(SetYaw)} available only when rotating is endless.");
return;
}
_targetYaw = targetYaw;
}
public override bool IsInRange() => true;
public override void CanDoIt()
{
Check(
_isForced || unit.GetComponent<StatusModule>().IsControllable(),
UnitIsBusyMessage);
}
protected override void OnDoIt()
{
BeforePerform();
// Instant rotation
if (_rotationSpeed <= 0)
{
Rotate(_targetYaw);
AfterPerform();
EndIt();
return;
}
// Endless rotation
if (_isEndless)
{
_rotateCoroutine = unit.StartCoroutine(RotationEndlessCoroutine());
return;
}
// Simple rotation to given yaw
_rotateCoroutine = unit.StartCoroutine(RotationCoroutine());
}
private IEnumerator RotationCoroutine()
{
while (Mathf.Approximately(unit.transform.rotation.eulerAngles.y, _targetYaw) == false)
{
var deltaYaw = Mathf.DeltaAngle(unit.rigidbody.rotation.eulerAngles.y, _targetYaw);
var deltaYawClamped = Mathf.Sign(deltaYaw) * Mathf.Clamp(Mathf.Abs(deltaYaw), 0, Time.fixedDeltaTime * _rotationSpeed);
Rotate(unit.rigidbody.rotation.eulerAngles.y + deltaYawClamped);
yield return new WaitForFixedUpdate();
}
AfterPerform();
EndIt();
}
private IEnumerator RotationEndlessCoroutine()
{
while (state is ActionState.Running)
{
var deltaYaw = Mathf.DeltaAngle(unit.rigidbody.rotation.eulerAngles.y, _targetYaw);
var deltaYawClamped = Mathf.Sign(deltaYaw) * Mathf.Clamp(Mathf.Abs(deltaYaw), 0, Time.fixedDeltaTime * _rotationSpeed);
Rotate(unit.rigidbody.rotation.eulerAngles.y + deltaYawClamped);
yield return new WaitForFixedUpdate();
}
}
private void Rotate(float yaw)
{
var targetRotation = unit.transform.rotation.eulerAngles;
targetRotation.y = yaw;
unit.rigidbody.MoveRotation(Quaternion.Euler(targetRotation));
}
protected override void OnEndIt() { }
protected override void OnCancelIt()
{
if (_rotateCoroutine != null) unit.StopCoroutine(_rotateCoroutine);
}
}
}