第一批重构,主要是物理迁移脚本和部分命名空间的调整
- 结构上迁移文件,将脚本分成 Base/Runtime/Presentation/Procedure/Editor 五大文件夹 - 调整 DataTable 和 Definition 下脚本的命名空间 - 依据 UI-5层架构设计规范 拆分原先的 UI 到 Runtime 和 Presentation 下
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
||||
namespace Entity.Weapon
|
||||
{
|
||||
public partial class WeaponKnife
|
||||
{
|
||||
private class AttackState : WeaponStateBase
|
||||
{
|
||||
private WeaponKnife _weapon;
|
||||
|
||||
public override WeaponStateType State => WeaponStateType.Attack;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
_weapon._currAttackTimer = 0f;
|
||||
_weapon.Attack();
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
if (!_weapon._isAttacking)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Check_InRange);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeave()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417516ffe5574e0c998105fcaa073de7
|
||||
timeCreated: 1771578955
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
namespace Entity.Weapon
|
||||
{
|
||||
public partial class WeaponKnife
|
||||
{
|
||||
private class CheckInRangeState : WeaponStateBase
|
||||
{
|
||||
private WeaponKnife _weapon;
|
||||
|
||||
public override WeaponStateType State => WeaponStateType.Check_InRange;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (_weapon._currAttackTimer >= _weapon._weaponData.Cooldown)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToTarget(elapseSeconds);
|
||||
_weapon._currAttackTimer += elapseSeconds;
|
||||
|
||||
if (_weapon._target == null || !_weapon._target.Available)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Idle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_weapon.IsInRange(_weapon._target, _weapon._sqrRange))
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Check_OutRange);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_weapon._currAttackTimer >= _weapon._weaponData.Cooldown)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeave()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 59644093364644768c26261b24bdb820
|
||||
timeCreated: 1771578916
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
namespace Entity.Weapon
|
||||
{
|
||||
public partial class WeaponKnife
|
||||
{
|
||||
private class CheckOutRangeState : WeaponStateBase
|
||||
{
|
||||
private WeaponKnife _weapon;
|
||||
|
||||
public override WeaponStateType State => WeaponStateType.Check_OutRange;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToTarget(elapseSeconds);
|
||||
_weapon._currAttackTimer += elapseSeconds;
|
||||
|
||||
if (_weapon._target == null || !_weapon._target.Available)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Idle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_weapon.IsInRange(_weapon._target, _weapon._sqrRange))
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Check_InRange);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeave()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d9e1a63869694e72a360afe29cc94cfb
|
||||
timeCreated: 1771578994
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
namespace Entity.Weapon
|
||||
{
|
||||
public partial class WeaponKnife
|
||||
{
|
||||
public class IdleState : WeaponStateBase
|
||||
{
|
||||
private WeaponKnife _weapon;
|
||||
|
||||
public override WeaponStateType State => WeaponStateType.Idle;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponKnife;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToOrigin(elapseSeconds);
|
||||
_weapon._currAttackTimer += elapseSeconds;
|
||||
|
||||
if (_weapon._target != null && _weapon._target.Available)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Check_OutRange);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeave()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4d66ec44b064640aa95c6aa71ff3846
|
||||
timeCreated: 1771578662
|
||||
@@ -0,0 +1,228 @@
|
||||
using System.Collections.Generic;
|
||||
using CustomUtility;
|
||||
using SepCore.Definition;
|
||||
using DG.Tweening;
|
||||
using Entity.EntityData;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace Entity.Weapon
|
||||
{
|
||||
public partial class WeaponKnife : WeaponBase
|
||||
{
|
||||
private WeaponKnifeData _weaponData;
|
||||
|
||||
private Quaternion _cachedRotation;
|
||||
[SerializeField] private float _rotateSpeed = 4f;
|
||||
|
||||
private Sequence _attackSequence;
|
||||
private Transform _attackParent;
|
||||
private Vector3 _attackCenter;
|
||||
|
||||
[SerializeField] private float attackDuration = 0.15f;
|
||||
[SerializeField] private float returnDuration = 0.2f;
|
||||
|
||||
[SerializeField] private LayerMask _hitMask = ~0;
|
||||
[SerializeField] private int _maxHitColliders = 32;
|
||||
|
||||
private IWeaponAttackEffect _attackEffect;
|
||||
private Collider[] _hitResults;
|
||||
private readonly HashSet<int> _hitEntityIds = new();
|
||||
|
||||
private float _hitRadius;
|
||||
private float _hitRadiusSqr;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
protected override void Attack()
|
||||
{
|
||||
StopAttackTween(false);
|
||||
FaceTargetImmediately();
|
||||
|
||||
_isAttacking = true;
|
||||
Transform parentTransform = CachedTransform.parent;
|
||||
_attackParent = parentTransform;
|
||||
_attackCenter = _target != null ? _target.CachedTransform.position : CachedTransform.position;
|
||||
CachedTransform.SetParent(null);
|
||||
|
||||
Vector3 targetPos = CachedTransform.position + CachedTransform.forward * _weaponData.AttackRange;
|
||||
_attackSequence = DOTween.Sequence();
|
||||
_attackSequence.Append(CachedTransform.DOMove(targetPos, attackDuration).SetEase(Ease.OutQuad));
|
||||
_attackSequence.AppendCallback(() =>
|
||||
{
|
||||
_attackEffect?.Play(this, _attackCenter, null, _hitRadius);
|
||||
ApplyGroundAreaDamage();
|
||||
if (_attackParent != null)
|
||||
{
|
||||
CachedTransform.SetParent(_attackParent);
|
||||
}
|
||||
});
|
||||
_attackSequence.Append(
|
||||
CachedTransform.DOLocalMove(Vector3.zero, returnDuration * 0.5f).SetEase(Ease.InQuad));
|
||||
_attackSequence.AppendCallback(() =>
|
||||
{
|
||||
_isAttacking = false;
|
||||
_attackSequence = null;
|
||||
_attackParent = null;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Check()
|
||||
{
|
||||
_target = SelectTarget(_sqrRange);
|
||||
}
|
||||
|
||||
private void RotateToTarget(float elapseSeconds)
|
||||
{
|
||||
if (_target == null || !_target.Available) return;
|
||||
|
||||
Vector3 directionToTarget = _target.CachedTransform.position - CachedTransform.position;
|
||||
if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return;
|
||||
|
||||
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
||||
CachedTransform.rotation =
|
||||
Quaternion.Slerp(CachedTransform.rotation, targetRotation, _rotateSpeed * elapseSeconds);
|
||||
}
|
||||
|
||||
public 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;
|
||||
if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return;
|
||||
|
||||
CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
||||
}
|
||||
|
||||
private void ApplyGroundAreaDamage()
|
||||
{
|
||||
if (_hitRadius <= 0f) return;
|
||||
|
||||
if (TryQueueAreaCollisionQuery(_attackCenter, _hitRadius, Mathf.Max(1, _maxHitColliders)))
|
||||
{
|
||||
_hitEntityIds.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_hitResults == null || _hitResults.Length == 0) return;
|
||||
|
||||
int hitCount = Physics.OverlapSphereNonAlloc(_attackCenter, _hitRadius, _hitResults, _hitMask,
|
||||
QueryTriggerInteraction.Collide);
|
||||
|
||||
_hitEntityIds.Clear();
|
||||
for (int i = 0; i < hitCount; i++)
|
||||
{
|
||||
Collider collider = _hitResults[i];
|
||||
if (collider == null) continue;
|
||||
|
||||
TargetableObject targetable = collider.GetComponentInParent<TargetableObject>();
|
||||
if (targetable == null || !targetable.Available || targetable.IsDead) continue;
|
||||
if (!_hitEntityIds.Add(targetable.Id)) continue;
|
||||
|
||||
Vector3 delta = targetable.CachedTransform.position - _attackCenter;
|
||||
delta.y = 0f;
|
||||
if (delta.sqrMagnitude > _hitRadiusSqr) continue;
|
||||
|
||||
AIUtility.PerformCollision(targetable, this);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnWeaponShow(object userData)
|
||||
{
|
||||
_weaponData = RequireWeaponData<WeaponKnifeData>(userData);
|
||||
if (_weaponData == null) return false;
|
||||
WeaponData = _weaponData;
|
||||
|
||||
_currAttackTimer = 0f;
|
||||
_sqrRange = _weaponData.AttackRange * _weaponData.AttackRange;
|
||||
_cachedRotation = CachedTransform.rotation;
|
||||
|
||||
float configuredHitRadius = _weaponData.ParamsData != null ? _weaponData.ParamsData.HitRadius : 0f;
|
||||
_hitRadius = configuredHitRadius > 0f ? Mathf.Max(0.1f, configuredHitRadius) : _weaponData.AttackRange;
|
||||
|
||||
_hitRadiusSqr = _hitRadius * _hitRadius;
|
||||
_attackEffect = new KnifeRangeAttackEffect();
|
||||
|
||||
int colliderCapacity = Mathf.Max(1, _maxHitColliders);
|
||||
if (_hitResults == null || _hitResults.Length != colliderCapacity)
|
||||
{
|
||||
_hitResults = new Collider[colliderCapacity];
|
||||
}
|
||||
|
||||
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);
|
||||
_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();
|
||||
}
|
||||
|
||||
protected override void OnEnabledChanged(bool enabled)
|
||||
{
|
||||
if (!enabled)
|
||||
{
|
||||
StopAttackTween(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void StopAttackTween(bool resetTransform)
|
||||
{
|
||||
if (_attackSequence != null)
|
||||
{
|
||||
_attackSequence.Kill();
|
||||
_attackSequence = null;
|
||||
}
|
||||
|
||||
_isAttacking = false;
|
||||
|
||||
if (resetTransform && _attackParent != null)
|
||||
{
|
||||
CachedTransform.SetParent(_attackParent);
|
||||
CachedTransform.localPosition = Vector3.zero;
|
||||
}
|
||||
|
||||
_attackParent = null;
|
||||
_hitEntityIds.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbf2e0cccf970934e82f8006d5be7846
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user