Add WeaponFeedback component and AddressableManagerWindow meta file
- Implemented WeaponFeedback class for handling weapon-related feedbacks such as hit effects and attack sounds. - Added meta file for AddressableManagerWindow to manage addressable assets. - Included a new jump.data file for profiler data.
This commit is contained in:
@@ -142,8 +142,8 @@ namespace BaseGames.Combat
|
||||
bool isRivalHitBoxLayer = (_rivalHitBoxMask.value & (1 << otherLayer)) != 0;
|
||||
if (isRivalHitBoxLayer && CanClash)
|
||||
{
|
||||
var rivalHitBox = other.GetComponent<HitBox>();
|
||||
if (rivalHitBox != null && rivalHitBox.IsActive && rivalHitBox.CanClash)
|
||||
if (other.TryGetComponent<HitBox>(out var rivalHitBox) &&
|
||||
rivalHitBox.IsActive && rivalHitBox.CanClash)
|
||||
{
|
||||
_clashService?.ResolveClash(this, rivalHitBox);
|
||||
return; // 拼刀,中止伤害流水线
|
||||
@@ -151,8 +151,7 @@ namespace BaseGames.Combat
|
||||
}
|
||||
|
||||
// ② 命中 HurtBox
|
||||
var hurtBox = other.GetComponent<HurtBox>();
|
||||
if (hurtBox != null)
|
||||
if (other.TryGetComponent<HurtBox>(out var hurtBox))
|
||||
{
|
||||
// 用 HitBox 自身碰撞盒中心在 HurtBox 表面上的最近点作为受击位置。
|
||||
// 对大体积/长条形受击体(如地刺),此点远比 HurtBox 节点中心更准确。
|
||||
@@ -163,7 +162,8 @@ namespace BaseGames.Combat
|
||||
}
|
||||
|
||||
// ③ 命中 IBreakable(机关/障碍物)
|
||||
other.GetComponent<IBreakable>()?.TryInteract(info);
|
||||
if (other.TryGetComponent<IBreakable>(out var breakable))
|
||||
breakable.TryInteract(info);
|
||||
}
|
||||
|
||||
// ── 当前激活期已命中目标集合(防止复合子 Collider 导致同帧多次命中)────────────
|
||||
|
||||
@@ -18,6 +18,8 @@ namespace BaseGames.Combat
|
||||
protected Rigidbody2D _rb;
|
||||
protected HitBox _hitBox;
|
||||
protected float _aliveTimer;
|
||||
// Lifetime 在 Initialize 时缓存,避免 Update 每帧访问 SO 成员并做 null check
|
||||
private float _lifetime = float.MaxValue;
|
||||
|
||||
private PooledObject _pooledObject;
|
||||
|
||||
@@ -32,6 +34,7 @@ namespace BaseGames.Combat
|
||||
public virtual void Initialize(ProjectileConfigSO config, DamageInfo damageInfo, Vector2 direction, int ownerLayer = 0)
|
||||
{
|
||||
_config = config;
|
||||
_lifetime = config.Lifetime;
|
||||
DamageInfo = damageInfo;
|
||||
Direction = direction.normalized;
|
||||
_aliveTimer = 0f;
|
||||
@@ -75,7 +78,7 @@ namespace BaseGames.Combat
|
||||
protected virtual void Update()
|
||||
{
|
||||
_aliveTimer += Time.deltaTime;
|
||||
if (_config != null && _aliveTimer >= _config.Lifetime)
|
||||
if (_aliveTimer >= _lifetime)
|
||||
ReturnToPool();
|
||||
}
|
||||
|
||||
@@ -91,6 +94,7 @@ namespace BaseGames.Combat
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
_aliveTimer = 0f;
|
||||
_lifetime = float.MaxValue; // 归还对象池后重置,防止未初始化时自毁
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace BaseGames.Combat
|
||||
|
||||
public event System.Action<DamageInfo> OnHitConfirmed;
|
||||
|
||||
private Coroutine _returnCoroutine;
|
||||
// 按 duration 缓存 WaitForSeconds,同一技能复用无 GC 分配
|
||||
private WaitForSeconds _cachedWait;
|
||||
private float _cachedWaitDuration = float.NaN;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
foreach (var hb in _hitBoxes)
|
||||
@@ -35,7 +40,31 @@ namespace BaseGames.Combat
|
||||
hb?.Activate(source, attacker);
|
||||
}
|
||||
|
||||
/// <summary>duration 秒后自动销毁此 GameObject。</summary>
|
||||
/// <summary>
|
||||
/// duration 秒后归还对象池(SetActive false)。
|
||||
/// 由 SkillManager 对象池调用;替代旧版 Destroy 流程。
|
||||
/// </summary>
|
||||
public void AutoReturnAfter(float duration)
|
||||
{
|
||||
if (!Mathf.Approximately(_cachedWaitDuration, duration))
|
||||
{
|
||||
_cachedWaitDuration = duration;
|
||||
_cachedWait = new WaitForSeconds(duration);
|
||||
}
|
||||
if (_returnCoroutine != null) StopCoroutine(_returnCoroutine);
|
||||
_returnCoroutine = StartCoroutine(ReturnCoroutine());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator ReturnCoroutine()
|
||||
{
|
||||
yield return _cachedWait;
|
||||
foreach (var hb in _hitBoxes)
|
||||
hb?.Deactivate();
|
||||
_returnCoroutine = null;
|
||||
gameObject.SetActive(false); // 触发对象池回收
|
||||
}
|
||||
|
||||
/// <summary>duration 秒后销毁(非池化路径,保留向后兼容)。</summary>
|
||||
public void AutoDestroyAfter(float duration)
|
||||
=> Destroy(gameObject, Mathf.Max(0f, duration));
|
||||
|
||||
|
||||
@@ -11,8 +11,9 @@ namespace BaseGames.Combat.StatusEffects
|
||||
|
||||
public override StatusEffectType EffectType => StatusEffectType.Fire;
|
||||
public override int MaxStacks => 1;
|
||||
private static readonly StatusEffectType[] s_MutualExclusions = { StatusEffectType.Freeze };
|
||||
/// <summary>施加燃烧时移除冻结(火冰互斥)。</summary>
|
||||
public override StatusEffectType[] MutualExclusions => new[] { StatusEffectType.Freeze };
|
||||
public override StatusEffectType[] MutualExclusions => s_MutualExclusions;
|
||||
|
||||
public FireEffect()
|
||||
{
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace BaseGames.Combat.StatusEffects
|
||||
// ── Shader 渲染(MaterialPropertyBlock,不修改共享材质)─────────
|
||||
private SpriteRenderer _renderer;
|
||||
private MaterialPropertyBlock _propBlock;
|
||||
// 缓存 Shader 属性 ID,避免每次调用 SetShaderParam 都做字符串哈希查找
|
||||
private readonly Dictionary<string, int> _shaderPropIds = new();
|
||||
|
||||
// ── DoT 伤害代理(由 StatusEffect.OnTick 通过 Owner 调用)──────────
|
||||
private IDamageable _damageable;
|
||||
@@ -135,8 +137,13 @@ namespace BaseGames.Combat.StatusEffects
|
||||
public void SetShaderParam(string param, float value)
|
||||
{
|
||||
if (_renderer == null) return;
|
||||
if (!_shaderPropIds.TryGetValue(param, out int propId))
|
||||
{
|
||||
propId = Shader.PropertyToID(param);
|
||||
_shaderPropIds[param] = propId;
|
||||
}
|
||||
_renderer.GetPropertyBlock(_propBlock);
|
||||
_propBlock.SetFloat(param, value);
|
||||
_propBlock.SetFloat(propId, value);
|
||||
_renderer.SetPropertyBlock(_propBlock);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user