所有敌人默认常驻身体接触伤害:存活即开、死亡时经 PerformDeath 统一关碰撞体停止。 - ContactChaseAbility/AnimatedCeilingDropAbility 移除对 BodyContactDamage 的开关引用 - BodyContactDamage 语义改为常驻(更新注释) - 脚手架 SetupHurtAndContactBoxes 去掉 contactEnabled 参数恒为 true,并把 ContactDamageZone 的 HitBox._targetLayers 限定为 PlayerHurtBox(避免常驻后敌人互相误伤) - 7 个敌人预制体:E001 启用 BodyContactDamage;E002/E004/E005/ChaoFeng 补齐 ContactDamageZone(镜像 HurtBox 身体碰撞体);全部 _targetLayers 收敛为 PlayerHurtBox - 更新 Docs/Guides/02 敌人搭建指南 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
74 lines
2.6 KiB
C#
74 lines
2.6 KiB
C#
using System.Collections;
|
|
using Animancer;
|
|
using BaseGames.AI;
|
|
using UnityEngine;
|
|
|
|
namespace BaseGames.Enemies.Abilities
|
|
{
|
|
/// <summary>
|
|
/// 带动画的天花板跌落能力:播放 Fall 动画 + 切换物理体为 Dynamic 自由下落,落地后恢复巡逻。
|
|
/// 取代 sealed 的 CeilingDropAbility,动画所有权完整封装在本能力中。
|
|
/// 可复用于任何需要从天花板落下的敌人。
|
|
/// 身体接触伤害与本能力解耦:由常驻的 <see cref="BodyContactDamage"/> 全程负责,本能力不再开关它。
|
|
/// </summary>
|
|
[RequireComponent(typeof(Rigidbody2D))]
|
|
public class AnimatedCeilingDropAbility : EnemyAbilityBase
|
|
{
|
|
private AnimatedCeilingDropAbilitySO _cfg;
|
|
private Rigidbody2D _rb;
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
_cfg = ResolveConfig<AnimatedCeilingDropAbilitySO>();
|
|
_rb = GetComponentInParent<Rigidbody2D>();
|
|
}
|
|
|
|
protected override IEnumerator ExecuteCoroutine()
|
|
{
|
|
if (_cfg == null) yield break;
|
|
|
|
Phase = AbilityRunState.Active;
|
|
|
|
// 播放下落动画(能力脚本负责动画所有权)
|
|
if (_cfg.fallLoopClip.Clip != null)
|
|
_animancer.Play(_cfg.fallLoopClip);
|
|
|
|
// 切换物理:Kinematic → Dynamic + 重力
|
|
var origBodyType = _rb.bodyType;
|
|
var origGravScale = _rb.gravityScale;
|
|
_rb.bodyType = RigidbodyType2D.Dynamic;
|
|
_rb.gravityScale = _cfg.fallGravityScale;
|
|
_rb.velocity = Vector2.zero;
|
|
|
|
// 等待落地(超时保护)
|
|
float elapsed = 0f;
|
|
while (elapsed < _cfg.maxFallTime)
|
|
{
|
|
elapsed += Time.fixedDeltaTime;
|
|
yield return new WaitForFixedUpdate();
|
|
if (elapsed > 0.05f && IsGrounded()) break;
|
|
}
|
|
_rb.velocity = Vector2.zero;
|
|
|
|
// 身体接触伤害由常驻 BodyContactDamage 全程负责,落地无需在此开启。
|
|
yield return EnemyAbilityWaits.Get(_cfg.recoveryTime);
|
|
|
|
// PlayLocomotionClip(Patrol) 播放 AnimConfig.Walk(地面移动动画)
|
|
_enemy.PlayLocomotionClip(LocomotionMode.Patrol);
|
|
}
|
|
|
|
private bool IsGrounded()
|
|
{
|
|
var hit = Physics2D.Raycast(_rb.position, Vector2.down, 0.6f, _cfg.groundMask);
|
|
return hit.collider != null;
|
|
}
|
|
|
|
protected override void OnInterrupted(InterruptReason reason)
|
|
{
|
|
if (_rb != null)
|
|
_rb.velocity = Vector2.zero;
|
|
}
|
|
}
|
|
}
|