Compare commits

...
Author SHA1 Message Date
adminandClaude Opus 4.6 8479197684 Fix snake animation by using original controller with state name overrides
Instead of replacing the Viper's animator controller (which broke bone
bindings for cross-FBX Generic animations), keep the original
Viper_anim_controller and add configurable state name overrides to
AnimalEffect. SnakeEffect now maps walk→glide and eat→hiss so the
Viper's native state names are used without controller replacement.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 16:35:13 -07:00
adminandClaude Opus 4.6 caf334208e Fix snake animation by adding SnakeMapAnims controller
The Viper model's built-in animator controller uses non-standard state
names (glide/hiss instead of walk/eat) and has auto-transitions that
conflict with AnimalEffect's direct Animator.Play() calls. Create a
SnakeMapAnims controller mapping the standard state names to the correct
Viper clips: idle->Viper_Idle, walk->Viper_Glide, eat->Viper_Hissing,
attack->Viper_Attack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 16:10:32 -07:00
2 changed files with 22 additions and 5 deletions
@@ -27,6 +27,12 @@ namespace eagle {
"Per-prefab controller overrides (index matches animalPrefabs); takes priority over animatorController")]
public RuntimeAnimatorController[] animatorControllers;
[Header("State Name Overrides")]
[Tooltip("Override walk state name for prefabs with non-standard names (e.g. 'glide')")]
public string walkStateName;
[Tooltip("Override eat state name for prefabs with non-standard names (e.g. 'hiss')")]
public string eatStateName;
[Header("Behavior Timing")]
public float minIdleDuration = 1f;
public float maxIdleDuration = 3f;
@@ -53,7 +59,16 @@ namespace eagle {
private static readonly int AttackHash = Animator.StringToHash("attack");
private static readonly int DieHash = Animator.StringToHash("die");
void Start() { SpawnAnimals(); }
private int _walkHash;
private int _eatHash;
void Start() {
_walkHash = string.IsNullOrEmpty(walkStateName) ? WalkHash
: Animator.StringToHash(walkStateName);
_eatHash = string.IsNullOrEmpty(eatStateName) ? EatHash
: Animator.StringToHash(eatStateName);
SpawnAnimals();
}
private void SpawnAnimals() {
if (animalPrefabs == null || animalPrefabs.Length == 0) { return; }
@@ -177,7 +192,7 @@ namespace eagle {
animal.targetPosition = RandomWanderPoint();
animal.state = AnimalStateType.Walking;
if (animal.animator != null) { animal.animator.Play(WalkHash); }
if (animal.animator != null) { animal.animator.Play(_walkHash); }
UpdateFacing(animal);
}
@@ -196,7 +211,7 @@ namespace eagle {
animal.state = AnimalStateType.Action;
animal.timer = actionDuration;
if (animal.animator != null) {
var actionHash = Random.value < 0.5f ? EatHash : AttackHash;
var actionHash = Random.value < 0.5f ? _eatHash : AttackHash;
animal.animator.Play(actionHash);
}
} else {
@@ -233,10 +248,10 @@ namespace eagle {
public void TestAllIdle() { ForEachAnimal(a => a.animator?.Play(IdleHash)); }
[ContextMenu("Test: All Walk")]
public void TestAllWalk() { ForEachAnimal(a => a.animator?.Play(WalkHash)); }
public void TestAllWalk() { ForEachAnimal(a => a.animator?.Play(_walkHash)); }
[ContextMenu("Test: All Eat")]
public void TestAllEat() { ForEachAnimal(a => a.animator?.Play(EatHash)); }
public void TestAllEat() { ForEachAnimal(a => a.animator?.Play(_eatHash)); }
[ContextMenu("Test: All Attack")]
public void TestAllAttack() { ForEachAnimal(a => a.animator?.Play(AttackHash)); }
@@ -54,6 +54,8 @@ MonoBehaviour:
wanderRadius: 25
moveSpeed: 15
animalScale: 15
walkStateName: glide
eatStateName: hiss
minIdleDuration: 1
maxIdleDuration: 3
actionChance: 0.3