整理武器配置和重构
This commit is contained in:
@@ -8,51 +8,37 @@ using UnityGameFramework.Runtime;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponSlash : WeaponBase
|
||||
public class WeaponSlash : WeaponBase
|
||||
{
|
||||
#region Property
|
||||
|
||||
private WeaponSlashData _weaponData;
|
||||
|
||||
private Quaternion _cachedRotation;
|
||||
[SerializeField] private float _rotateSpeed = 4f;
|
||||
|
||||
private Sequence _attackSequence;
|
||||
private Vector3 _attackCenter;
|
||||
private Quaternion _cachedAttackRotation;
|
||||
private IWeaponAttackEffect _attackEffect;
|
||||
|
||||
[SerializeField] private float attackDuration = 0.4f;
|
||||
[SerializeField] private float returnDuration = 0.4f;
|
||||
[SerializeField] private float _attackDuration = 0.4f;
|
||||
[SerializeField] private float _returnDuration = 0.4f;
|
||||
[SerializeField] private float _swingAngleScale = 1f;
|
||||
|
||||
[SerializeField] private LayerMask _hitMask = ~0;
|
||||
[SerializeField] private int _maxHitColliders = 32;
|
||||
|
||||
private Collider[] _hitResults;
|
||||
private readonly HashSet<int> _hitEntityIds = new();
|
||||
|
||||
private float _attackRadius;
|
||||
private float _attackRadiusSqr;
|
||||
private float _sectorAngle;
|
||||
public float SectorAngle => WeaponData.GetParamFloat(ParamType.SectorAngle);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public override ImpactData GetImpactData()
|
||||
{
|
||||
return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat);
|
||||
}
|
||||
|
||||
protected override void BuildStates()
|
||||
{
|
||||
RegisterState(new IdleState());
|
||||
RegisterState(new CheckInRangeState());
|
||||
RegisterState(new CheckOutRangeState());
|
||||
RegisterState(new AttackState());
|
||||
RegisterState(new WeaponSlashIdleState());
|
||||
RegisterState(new WeaponSlashAimState());
|
||||
RegisterState(new WeaponSlashSeekState());
|
||||
RegisterState(new WeaponSlashAttackState());
|
||||
}
|
||||
|
||||
protected override void Attack()
|
||||
public override void Attack()
|
||||
{
|
||||
StopAttackTween(false);
|
||||
FaceTargetImmediately();
|
||||
@@ -61,20 +47,20 @@ namespace SepCore.Entity
|
||||
_attackCenter = CachedTransform.position;
|
||||
_cachedAttackRotation = CachedTransform.rotation;
|
||||
|
||||
float swingAngle = Mathf.Clamp(_sectorAngle * Mathf.Max(0.1f, _swingAngleScale), 15f, 170f);
|
||||
float swingAngle = Mathf.Clamp(SectorAngle * Mathf.Max(0.1f, _swingAngleScale), 15f, 170f);
|
||||
Quaternion startRotation = Quaternion.AngleAxis(-swingAngle * 0.5f, Vector3.up) * _cachedAttackRotation;
|
||||
Quaternion endRotation = Quaternion.AngleAxis(swingAngle * 0.5f, Vector3.up) * _cachedAttackRotation;
|
||||
CachedTransform.rotation = startRotation;
|
||||
|
||||
_attackSequence = DOTween.Sequence();
|
||||
_attackSequence.Append(
|
||||
CachedTransform.DORotateQuaternion(endRotation, attackDuration).SetEase(Ease.OutSine));
|
||||
_attackSequence.InsertCallback(attackDuration * 0.5f, () =>
|
||||
CachedTransform.DORotateQuaternion(endRotation, _attackDuration).SetEase(Ease.OutSine));
|
||||
_attackSequence.InsertCallback(_attackDuration * 0.5f, () =>
|
||||
{
|
||||
_attackEffect?.Play(this, _attackCenter, _target, _attackRadius);
|
||||
_attackEffect.Play(this, _attackCenter, _target, WeaponData.AttackRange);
|
||||
ApplySectorDamage();
|
||||
});
|
||||
_attackSequence.Append(CachedTransform.DORotateQuaternion(_cachedAttackRotation, returnDuration)
|
||||
_attackSequence.Append(CachedTransform.DORotateQuaternion(_cachedAttackRotation, _returnDuration)
|
||||
.SetEase(Ease.InSine));
|
||||
_attackSequence.AppendCallback(() =>
|
||||
{
|
||||
@@ -83,14 +69,10 @@ namespace SepCore.Entity
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Check()
|
||||
{
|
||||
_target = SelectTarget(_sqrRange);
|
||||
}
|
||||
|
||||
private void ApplySectorDamage()
|
||||
{
|
||||
if (_attackRadius <= 0f) return;
|
||||
float attackRadius = WeaponData.AttackRange;
|
||||
if (attackRadius <= 0f) return;
|
||||
|
||||
Vector3 forward = CachedTransform.forward;
|
||||
forward.y = 0f;
|
||||
@@ -100,19 +82,19 @@ namespace SepCore.Entity
|
||||
}
|
||||
|
||||
forward.Normalize();
|
||||
float halfAngle = _sectorAngle * 0.5f;
|
||||
if (TryQueueSectorCollisionQuery(_attackCenter, _attackRadius, in forward, halfAngle,
|
||||
float halfAngle = SectorAngle * 0.5f;
|
||||
if (TryQueueSectorCollisionQuery(_attackCenter, attackRadius, in forward, halfAngle,
|
||||
Mathf.Max(1, _maxHitColliders)))
|
||||
{
|
||||
_hitEntityIds.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hitResults == null || _hitResults.Length == 0) return;
|
||||
|
||||
int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, _attackRadius, _hitResults, _hitMask,
|
||||
int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, attackRadius, _hitResults, _hitMask,
|
||||
QueryTriggerInteraction.Collide);
|
||||
|
||||
float attackRadiusSqr = attackRadius * attackRadius;
|
||||
_hitEntityIds.Clear();
|
||||
for (int i = 0; i < hitCount; i++)
|
||||
{
|
||||
@@ -127,7 +109,7 @@ namespace SepCore.Entity
|
||||
toTarget.y = 0f;
|
||||
|
||||
float sqrDistance = toTarget.sqrMagnitude;
|
||||
if (sqrDistance <= Mathf.Epsilon || sqrDistance > _attackRadiusSqr) continue;
|
||||
if (sqrDistance <= Mathf.Epsilon || sqrDistance > attackRadiusSqr) continue;
|
||||
|
||||
float angle = Vector3.Angle(forward, toTarget.normalized);
|
||||
if (angle > halfAngle) continue;
|
||||
@@ -136,53 +118,11 @@ namespace SepCore.Entity
|
||||
}
|
||||
}
|
||||
|
||||
private void RotateToTarget(float elapseSeconds)
|
||||
{
|
||||
if (_target == null || !_target.Available) return;
|
||||
|
||||
Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position;
|
||||
directionToTarget.y = 0f;
|
||||
if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return;
|
||||
|
||||
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
||||
CachedTransform.rotation =
|
||||
Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds);
|
||||
}
|
||||
|
||||
private void RotateToOrigin(float elapseSeconds)
|
||||
{
|
||||
CachedTransform.rotation =
|
||||
Quaternion.Slerp(CachedTransform.rotation, _cachedRotation, _rotateSpeed * elapseSeconds);
|
||||
}
|
||||
|
||||
private void FaceTargetImmediately()
|
||||
{
|
||||
if (_target == null || !_target.Available) return;
|
||||
|
||||
Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position;
|
||||
directionToTarget.y = 0f;
|
||||
if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return;
|
||||
|
||||
CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override bool OnWeaponShow(object userData)
|
||||
{
|
||||
_weaponData = RequireWeaponData<WeaponSlashData>(userData);
|
||||
if (_weaponData == null) return false;
|
||||
WeaponData = _weaponData;
|
||||
|
||||
StartAttackCooldown(_weaponData.Cooldown);
|
||||
_sqrRange = _weaponData.AttackRange * _weaponData.AttackRange;
|
||||
_cachedRotation = CachedTransform.rotation;
|
||||
|
||||
_attackRadius = Mathf.Max(0.1f, _weaponData.AttackRange);
|
||||
_attackRadiusSqr = _attackRadius * _attackRadius;
|
||||
|
||||
float configuredSectorAngle = _weaponData.ParamsData != null ? _weaponData.ParamsData.SectorAngle : 0f;
|
||||
_sectorAngle = configuredSectorAngle > 0f ? Mathf.Clamp(configuredSectorAngle, 1f, 360f) : 90f;
|
||||
_cachedAttackRotation = _cachedRotation;
|
||||
|
||||
int capacity = Mathf.Max(1, _maxHitColliders);
|
||||
if (_hitResults == null || _hitResults.Length != capacity)
|
||||
@@ -191,37 +131,19 @@ namespace SepCore.Entity
|
||||
}
|
||||
|
||||
_attackEffect = new SlashSectorAttackEffect();
|
||||
|
||||
if (_weaponData.OwnerCamp == CampType.Player)
|
||||
{
|
||||
gameObject.layer = LayerMask.NameToLayer("PlayerWeapon");
|
||||
_hitMask = LayerMask.GetMask("Enemy");
|
||||
}
|
||||
else if (_weaponData.OwnerCamp == CampType.Enemy)
|
||||
{
|
||||
gameObject.layer = LayerMask.NameToLayer("EnemyWeapon");
|
||||
_hitMask = LayerMask.GetMask("Player");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnWeaponHide(object userData)
|
||||
{
|
||||
StopAttackTween(true);
|
||||
CancelAttackCooldown();
|
||||
_attackEffect = null;
|
||||
}
|
||||
|
||||
protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData)
|
||||
{
|
||||
BindAttackStatFromOwner(parentEntity);
|
||||
}
|
||||
|
||||
protected override void OnWeaponDetach(EntityLogic parentEntity, object userData)
|
||||
{
|
||||
StopAttackTween(true);
|
||||
ReleaseAttackStatSubscription();
|
||||
base.OnWeaponDetach(parentEntity, userData);
|
||||
}
|
||||
|
||||
protected override void OnEnabledChanged(bool enabled)
|
||||
@@ -234,7 +156,6 @@ namespace SepCore.Entity
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
private void StopAttackTween(bool resetTransform)
|
||||
{
|
||||
if (_attackSequence != null)
|
||||
@@ -252,7 +173,5 @@ namespace SepCore.Entity
|
||||
|
||||
_hitEntityIds.Clear();
|
||||
}
|
||||
|
||||
public float SectorAngle => _sectorAngle;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user