21a4c71413
- KnockbackUtil.Stamp: shared knockback-stamp used by AbilityFireSystem + MeleeComboSystem (guard + planar normalize + write; speed passed in). - BakerStructureExt: AddPlacedStructure/AddDamageable extensions on Baker<T>; rewired Turret/Structure/Harvester/Conveyor/Fabricator bakers (baked data + serialized fields unchanged). - EnemyPrefabBakeExt.AddEnemyPrefabPool: shared prefab-buffer bake for ZoneEnemyDirector/WaveDirector authoring (fields stay flat — no serialization change). - Editor AnimRigUtil (HasParam + root-yaw overlay clip) shared by PlayerRigTools/EnemyRigTools; EnemyRigTools.MakeMat now GUID-preserving (CopySerialized over existing) — the composite AnimatorController copy left as-is with a caveat comment. 466/466 EditMode tests pass, 0 warnings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
46 lines
2.3 KiB
C#
46 lines
2.3 KiB
C#
using UnityEditor;
|
|
using UnityEditor.Animations;
|
|
using UnityEngine;
|
|
|
|
namespace ProjectM.EditorTools
|
|
{
|
|
/// <summary>
|
|
/// Shared editor-only helpers for the player/enemy Rukhanka rig tools (PlayerRigTools / EnemyRigTools):
|
|
/// AnimatorController parameter probing + the "overlay clip = full idle pose (every bone keyed, minus Root)
|
|
/// plus a Root-yaw twist" build. A Root-ONLY clip makes Rukhanka collapse every un-keyed bone to identity for
|
|
/// the state's duration -> the body sinks into the floor (writeDefaultValues does NOT prevent it), so both the
|
|
/// player swing and the enemy attack-windup base their clip on idle and drive only the Root yaw. The twist
|
|
/// keyframes differ per clip, so they are passed in.
|
|
/// </summary>
|
|
public static class AnimRigUtil
|
|
{
|
|
/// <summary>True if the controller already declares a parameter named <paramref name="name"/>.</summary>
|
|
public static bool HasParam(AnimatorController ac, string name)
|
|
{
|
|
foreach (var p in ac.parameters) if (p.name == name) return true;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Rebuild <paramref name="clip"/> as the full <paramref name="idle"/> pose (all bindings except Root) with
|
|
/// the supplied Root localEulerAnglesRaw.y <paramref name="rootYaw"/> curve on top; sets loopTime=false and
|
|
/// saves. Height-preserving (avoids the un-keyed-bone collapse).
|
|
/// </summary>
|
|
public static void BuildRootYawOverlayClip(AnimationClip clip, AnimationClip idle, AnimationCurve rootYaw)
|
|
{
|
|
clip.ClearCurves();
|
|
foreach (var b in AnimationUtility.GetCurveBindings(idle))
|
|
{
|
|
if (b.path == "Root") continue; // the Root is driven below
|
|
AnimationUtility.SetEditorCurve(clip, b, AnimationUtility.GetEditorCurve(idle, b));
|
|
}
|
|
AnimationUtility.SetEditorCurve(clip, EditorCurveBinding.FloatCurve("Root", typeof(Transform), "localEulerAnglesRaw.y"), rootYaw);
|
|
var s = AnimationUtility.GetAnimationClipSettings(clip);
|
|
s.loopTime = false;
|
|
AnimationUtility.SetAnimationClipSettings(clip, s);
|
|
EditorUtility.SetDirty(clip);
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
}
|
|
}
|