调整部分数据表配置,优化 SpriteCache 功能
This commit is contained in:
+25
@@ -0,0 +1,25 @@
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponHandgun
|
||||
{
|
||||
private class AttackState : WeaponStateBase
|
||||
{
|
||||
private WeaponHandgun _weapon;
|
||||
public override WeaponStateType State => WeaponStateType.Attack;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
_weapon.ResetAttackCooldown(_weapon._weaponData.Cooldown);
|
||||
_weapon.Attack();
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Check_InRange);
|
||||
}
|
||||
|
||||
public override void OnLeave() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e72df067466464fa3be92bfd049dd0d
|
||||
timeCreated: 1771579220
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponHandgun
|
||||
{
|
||||
private class CheckInRangeState : WeaponStateBase
|
||||
{
|
||||
private WeaponHandgun _weapon;
|
||||
public override WeaponStateType State => WeaponStateType.Check_InRange;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun;
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
if (_weapon._canAttack)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToTarget(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._canAttack)
|
||||
{
|
||||
_weapon.TransitionTo(WeaponStateType.Attack);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLeave() { }
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bfd76c0fb7284ceaa28f78c702f595da
|
||||
timeCreated: 1771579231
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponHandgun
|
||||
{
|
||||
private class CheckOutRangeState : WeaponStateBase
|
||||
{
|
||||
private WeaponHandgun _weapon;
|
||||
public override WeaponStateType State => WeaponStateType.Check_OutRange;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun;
|
||||
public override void OnEnter() { }
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToTarget(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: 3a9f936d3c8643f7bf632734548f800c
|
||||
timeCreated: 1771579241
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponHandgun
|
||||
{
|
||||
private class IdleState : WeaponStateBase
|
||||
{
|
||||
private WeaponHandgun _weapon;
|
||||
public override WeaponStateType State => WeaponStateType.Idle;
|
||||
public override void OnInit(WeaponBase weapon) => _weapon = weapon as WeaponHandgun;
|
||||
public override void OnEnter() { }
|
||||
|
||||
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
|
||||
{
|
||||
_weapon.Check();
|
||||
_weapon.RotateToOrigin(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: 9c5341944d1a467b8553d31bc3d81d5b
|
||||
timeCreated: 1771579252
|
||||
@@ -0,0 +1,169 @@
|
||||
using SepCore.Definition;
|
||||
using SepCore.CustomUtility;
|
||||
using UnityEngine;
|
||||
using UnityGameFramework.Runtime;
|
||||
|
||||
namespace SepCore.Entity
|
||||
{
|
||||
public partial class WeaponHandgun : WeaponBase
|
||||
{
|
||||
#region Property
|
||||
|
||||
private WeaponHandgunData _weaponData;
|
||||
|
||||
private Quaternion _cachedRotation;
|
||||
|
||||
[SerializeField] private float _rotateSpeed = 6f;
|
||||
[SerializeField] private LayerMask _hitMask = ~0;
|
||||
[SerializeField] private Vector3 _fireOriginOffset = Vector3.zero;
|
||||
|
||||
[SerializeField] private float _hitMarkerSize = 0.2f;
|
||||
[SerializeField] private float _hitMarkerYOffset = 1.2f;
|
||||
[SerializeField] private float _hitMarkerDuration = 0.15f;
|
||||
[SerializeField] private Color _hitMarkerColor = new(1f, 0f, 0f, 0.95f);
|
||||
|
||||
private IWeaponAttackEffect _attackEffect;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public override ImpactData GetImpactData()
|
||||
{
|
||||
return new ImpactData(_weaponData.OwnerCamp, _weaponData.Attack, AttackStat);
|
||||
}
|
||||
|
||||
protected override void BuildStates()
|
||||
{
|
||||
RegisterState(new IdleState());
|
||||
RegisterState(new CheckOutRangeState());
|
||||
RegisterState(new CheckInRangeState());
|
||||
RegisterState(new AttackState());
|
||||
}
|
||||
|
||||
protected override void Attack()
|
||||
{
|
||||
FaceTargetImmediately();
|
||||
|
||||
if (!TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_attackEffect?.Play(this, hitPosition, targetable, 0f);
|
||||
_isAttacking = true;
|
||||
AIUtility.PerformCollision(targetable, this);
|
||||
_isAttacking = false;
|
||||
}
|
||||
|
||||
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).normalized;
|
||||
Quaternion targetRotation = Quaternion.LookRotation(directionToTarget, 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;
|
||||
if (directionToTarget.sqrMagnitude <= Mathf.Epsilon) return;
|
||||
|
||||
CachedTransform.rotation = Quaternion.LookRotation(directionToTarget.normalized, Vector3.up);
|
||||
}
|
||||
|
||||
private bool TryResolveAttackTarget(out TargetableObject targetable, out Vector3 hitPosition)
|
||||
{
|
||||
targetable = _target as TargetableObject;
|
||||
hitPosition = CachedTransform.position;
|
||||
if (targetable == null || !targetable.Available || targetable.IsDead)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Transform targetTransform = targetable.CachedTransform;
|
||||
if (targetTransform == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hitPosition = targetTransform.position;
|
||||
|
||||
Vector3 fireOrigin = CachedTransform.TransformPoint(_fireOriginOffset);
|
||||
Vector3 directionToTarget = targetTransform.position - fireOrigin;
|
||||
float maxDistance = Mathf.Max(0.1f, _weaponData.AttackRange);
|
||||
if (directionToTarget.sqrMagnitude > Mathf.Epsilon &&
|
||||
Physics.Raycast(fireOrigin, directionToTarget.normalized, out RaycastHit hit, maxDistance, _hitMask,
|
||||
QueryTriggerInteraction.Collide))
|
||||
{
|
||||
TargetableObject raycastTarget = hit.collider.GetComponentInParent<TargetableObject>();
|
||||
if (raycastTarget == targetable)
|
||||
{
|
||||
hitPosition = hit.point;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
protected override bool OnWeaponShow(object userData)
|
||||
{
|
||||
_weaponData = RequireWeaponData<WeaponHandgunData>(userData);
|
||||
if (_weaponData == null) return false;
|
||||
|
||||
WeaponData = _weaponData;
|
||||
StartAttackCooldown(_weaponData.Cooldown);
|
||||
_sqrRange = _weaponData.AttackRange * _weaponData.AttackRange;
|
||||
_cachedRotation = CachedTransform.rotation;
|
||||
_attackEffect = new HandgunHitMarkerAttackEffect(_hitMarkerSize, _hitMarkerYOffset, _hitMarkerDuration,
|
||||
_hitMarkerColor);
|
||||
|
||||
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)
|
||||
{
|
||||
CancelAttackCooldown();
|
||||
_attackEffect = null;
|
||||
}
|
||||
|
||||
protected override void OnWeaponAttach(EntityLogic parentEntity, Transform parentTransform, object userData)
|
||||
{
|
||||
BindAttackStatFromOwner(parentEntity);
|
||||
}
|
||||
|
||||
protected override void OnWeaponDetach(EntityLogic parentEntity, object userData)
|
||||
{
|
||||
ReleaseAttackStatSubscription();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44ae1bdd1d43e274980743df21658730
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user