@
feat(enemy): E001 追击动画 Skill_Start/Loop/End 完整化,符合设计文档 依据 Docs/Game/Design/小怪设计-程序开发文档-01.md:感知→Skill_Start(张口,单次) →Skill_Loop(快速爬行追击,循环)→丢失目标→Skill_End(收招,单次)→Move_Patrol, E001 无警觉态。 原问题:ContactChaseAbility 的 loop/end clip 都空、无 start clip,追击全程无 动画;Approach 步态还错播 Move;有多余警觉态(Alert clip 也空)。 - ContactChaseAbility:加 _startClip;协程 Skill_Start(锁动画+等时长,不伤人)→ 开伤害+Approach+Skill_Loop(循环)→退出播 Skill_End。丢失目标(ExternalRequest 中断)播 Skill_End;受击/死亡硬打断不播。 - EnemyBase:加动画锁 LockAnim/IsAnimLocked——一次性招式动画期间步态不覆盖; PlayLocomotionClip 的 Approach 改为不驱动步态(追击动画归能力)。 - EnemyLocomotion:锁定期不算"已应用",解锁后重同步步态(避免卡在 Skill_End)。 - ENM_E001_Stats:HasAlertState=false(设计无警觉态)。 - prefab + 脚手架:ContactChaseAbility 接线 Skill_Start/Loop/End;新增 AssignClipTransition 助手(按名+路径定位同名 clip)。 PlayMode 验证:Skill_Start(locked/不伤人)→Skill_Loop(伤害开)→Skill_End (locked)→步态恢复 Move,全链符合设计。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> @
This commit is contained in:
@@ -519,6 +519,10 @@ namespace BaseGames.Editor
|
||||
|
||||
AssignAsset(chaseAbility, "_config", report, false, "ABL_E001_Chase");
|
||||
AssignReference(chaseAbility, "_contactDamage", bodyContact, report);
|
||||
// 追击动画:起手/循环/收招(设计文档 Skill_Start/Loop/End)
|
||||
AssignClipTransition(chaseAbility, "_startClip", "Skill_Start", "Enemies/E001", report);
|
||||
AssignClipTransition(chaseAbility, "_loopClip", "Skill_Loop", "Enemies/E001", report);
|
||||
AssignClipTransition(chaseAbility, "_endClip", "Skill_End", "Enemies/E001", report);
|
||||
|
||||
Object dmgSrc = FindFirstAsset("CMB_DS_EnemyBody");
|
||||
if (dmgSrc != null) AssignReference(contactHitBox, "_defaultSource", dmgSrc, report);
|
||||
@@ -2292,6 +2296,29 @@ namespace BaseGames.Editor
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给组件上的 Animancer <c>ClipTransition</c> 字段赋 AnimationClip(写嵌套 <c>_Clip</c>)。
|
||||
/// 按 clip 名 + 路径子串定位(同名 clip 各敌人各有一份,须用路径区分,如 "Enemies/E001")。
|
||||
/// </summary>
|
||||
private static void AssignClipTransition(Object target, string propName, string clipName, string pathContains, List<string> report)
|
||||
{
|
||||
AnimationClip clip = null;
|
||||
foreach (var g in AssetDatabase.FindAssets(clipName + " t:AnimationClip"))
|
||||
{
|
||||
var p = AssetDatabase.GUIDToAssetPath(g);
|
||||
if (System.IO.Path.GetFileNameWithoutExtension(p) == clipName && p.Contains(pathContains))
|
||||
{ clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(p); break; }
|
||||
}
|
||||
if (clip == null) { report?.Add($"★ 缺少动画 clip:{clipName}(路径含 {pathContains})"); return; }
|
||||
|
||||
var so = new SerializedObject(target);
|
||||
var sp = so.FindProperty(propName);
|
||||
var cp = sp?.FindPropertyRelative("_Clip");
|
||||
if (cp == null) { report?.Add($"{target.GetType().Name}.{propName}._Clip 字段不存在,跳过 clip 赋值。"); return; }
|
||||
cp.objectReferenceValue = clip;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
private static void AssignAsset(Object target, string propName, List<string> report, bool required, params string[] candidates)
|
||||
{
|
||||
Object asset = FindFirstAsset(candidates);
|
||||
|
||||
Reference in New Issue
Block a user