"Components.Get misses a SkinnedModelRenderer on a child object"
▸ SYMPTOM
A component on the player root calls Components.Get<SkinnedModelRenderer>() and uses the result to drive animations (renderer.Set("param", value)). The code compiles, nothing throws, but combat gestures, attacks, and ability animations never play — the character stays in a T-pose or idle.
▸ CAUSE
Components.Get<T>() only searches the component's own GameObject, not children. When the player is composed with the citizen SkinnedModelRenderer on a "Body" child (the common pattern so that PlayerController drives locomotion on that child), any component on the root that does Components.Get<SkinnedModelRenderer>() gets null.
Because the anim calls are typically null-guarded (renderer?.Set(...)) they silently no-op instead of throwing — the bug is invisible at runtime.
The asymmetry is deceptive: if NPCs in the same project have the renderer on their own root object, their Components.Get<>() works fine — making the player-only failure look like a logic bug rather than a lookup scope issue.
▸ FIX
Resolve the child renderer explicitly. Prefer an assigned reference the factory already provides:
// If the player factory exposes the body renderer:
var renderer = _playerRef.BodyRenderer;
renderer.Set("b_attack", true);Or fall back to the tree-descending lookup:
var renderer = Components.GetInChildren<SkinnedModelRenderer>();
renderer?.Set("b_attack", true);Rule: any component reaching for a renderer or collider it doesn't own must use GetInChildren<T>() or a pre-assigned reference — never bare Get<T>().
▸ WHY IT WORKS
GetInChildren<T>() walks the full GameObject hierarchy downward, finding the renderer regardless of which child holds it. An explicit reference avoids the search entirely and is the cheapest option when the composition is known at build time.