121 lines
3.6 KiB
C#
121 lines
3.6 KiB
C#
using UnityEngine;
|
|
|
|
namespace Components
|
|
{
|
|
[DisallowMultipleComponent]
|
|
public class BasicBearingComp : MonoBehaviour
|
|
{
|
|
[SerializeField] [Min(1f)] private float _rotateSpeed = 180f;
|
|
|
|
[SerializeField] [Min(0.1f)] private float _attackRange = 5f;
|
|
|
|
[SerializeField] [Min(0.1f)] private float _aimToleranceAngle = 2f;
|
|
|
|
[SerializeField] private Transform _rotateRoot;
|
|
|
|
[SerializeField] private SpriteRenderer _renderer;
|
|
|
|
public float RotateSpeed => _rotateSpeed;
|
|
public float AttackRange => _attackRange;
|
|
public float AimToleranceAngle => _aimToleranceAngle;
|
|
|
|
public void OnInit(float rotateSpeed, float attackRange = 5f)
|
|
{
|
|
_rotateSpeed = Mathf.Max(1f, rotateSpeed);
|
|
_attackRange = Mathf.Max(0.1f, attackRange);
|
|
}
|
|
|
|
public void OnReset()
|
|
{
|
|
_rotateSpeed = 1f;
|
|
_attackRange = 5f;
|
|
}
|
|
|
|
public void SetColor(Color color)
|
|
{
|
|
if (_renderer != null)
|
|
{
|
|
_renderer.color = color;
|
|
}
|
|
}
|
|
|
|
public bool IsTargetInRange(Transform target, Transform origin = null)
|
|
{
|
|
if (target == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Transform originTransform = origin != null ? origin : transform;
|
|
Vector3 delta = target.position - originTransform.position;
|
|
return delta.sqrMagnitude <= _attackRange * _attackRange;
|
|
}
|
|
|
|
public bool TrackTarget(Transform target, float deltaTime)
|
|
{
|
|
if (target == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Transform rotateRoot = _rotateRoot != null ? _rotateRoot : transform;
|
|
Vector2 toTarget = (Vector2)(target.position - rotateRoot.position);
|
|
|
|
if (toTarget.sqrMagnitude <= Mathf.Epsilon)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
float targetZAngle = Vector2.SignedAngle(Vector2.up, toTarget);
|
|
float currentZAngle = rotateRoot.eulerAngles.z;
|
|
float maxStep = _rotateSpeed * Mathf.Max(0f, deltaTime);
|
|
float angleDelta = Mathf.DeltaAngle(currentZAngle, targetZAngle);
|
|
float nextZAngle = currentZAngle + Mathf.Clamp(angleDelta, -maxStep, maxStep);
|
|
rotateRoot.rotation = Quaternion.Euler(0f, 0f, nextZAngle);
|
|
return IsTargetAligned(target);
|
|
}
|
|
|
|
public bool IsTargetAligned(Transform target)
|
|
{
|
|
if (target == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
Transform rotateRoot = _rotateRoot != null ? _rotateRoot : transform;
|
|
Vector2 toTarget = (Vector2)(target.position - rotateRoot.position);
|
|
|
|
if (toTarget.sqrMagnitude <= Mathf.Epsilon)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
float targetZAngle = Vector2.SignedAngle(Vector2.up, toTarget);
|
|
float currentZAngle = rotateRoot.eulerAngles.z;
|
|
float angle = Mathf.Abs(Mathf.DeltaAngle(currentZAngle, targetZAngle));
|
|
return angle <= _aimToleranceAngle;
|
|
}
|
|
|
|
public bool TryAttack(ShooterMuzzleComp shooterMuzzleComp, Transform target, float deltaTime)
|
|
{
|
|
if (shooterMuzzleComp == null || target == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!IsTargetInRange(target))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool isAligned = TrackTarget(target, deltaTime);
|
|
if (!isAligned)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return shooterMuzzleComp.Attack(target);
|
|
}
|
|
}
|
|
}
|