public sealed class SkinningSystemTurns each animated entity's pose into the bone palette GPU skinning reads.
No guide page documents this yet — the page shows what the code says about itself.
As a system
- Phase
- PreRender
Remarks
The other end of the arrangement SkinningRenderFeature describes. That feature owns the buffer, the upload and the push constant, and says explicitly that whoever fills the palettes is the animation system, because there is no callback of the renderer's between "animation finished" and "the first palette is written". This is the system it means.
In PreRender, after AnimationSystem has run in Animation and after any IK a pose processor did. Palettes are a per-frame thing — the feature's Begin resets the upload buffer and every skinned object writes its own again — so a frame in which this does not run is a frame in which nothing is skinned, rather than one that draws stale bones.
The join is RenderHandle, not a second component saying the same thing. ⚠ This used to query SkinnedRenderer, which nothing in the tree ever added to an entity — so the query matched no chunk in any scene the engine builds and Run walked nothing while every counter read healthy. MeshExtractionSystem already writes the entity → RenderObjectId join for everything else and MorphWeightSystem already reads it; a second component repeating it is a second thing that has to be filled in, and it was the one that was not. See .
Two features, tried in that order, and the order is forced. Virtualized is asked first because it is the only one of the two that can answer: VirtualGeometryRenderFeature.SetBones knows whether the object is one of its own, where SkinningRenderFeature.SetBones writes into a parallel array indexed by every object in the scene and cannot tell a mesh it draws from one it does not. MorphWeightSystem runs its fall-through the other way round for the same reason mirrored — there it is the classic feature that knows.
⚠ The virtualized branch is the one that is finished below this line. A page vertex carries four influences (MeshletPages.InfluenceOffset, twenty-four bytes a vertex, round-tripped by SkinnedClusterTests); MeshletBuilder splits a cluster on differing bone indices and records the [FirstBone, FirstBone + BoneCount) range a traversal expands a bound by; ClusterRaster.rvn and VisibilityResolve.rvn both blend the palette, gated on instance.firstBone != Cull.NoBones; and ModelImporter builds a hierarchy for skinned meshes on purpose, so an imported character is already extracted down that path.
⚠ The classic branch is not, and Feature is left here rather than used. SurfaceVertex — the interleaved vertex the suballocated mesh path uploads — carries no bone indices and no bone weights, so there is nothing per vertex for a palette to be blended against; and no shading pass in the library skins, since ForwardPlus.rvn declares no Skinned permutation. Worse than useless rather than merely absent: SkinningRenderFeature.ValueOf answers "skinned" from a non-zero bone count, and VertexSchema.Layout throws on an attribute a stage declares and the vertex format has no data for — which is exactly bones0/weights0 in the Skinned variant of ShadowCaster. So a host that sets Feature today buys a pipeline that refuses to build; it is wired here because the fall-through has to have a second half, and it stays inert because nothing constructs that feature.
⚠ And the shadow caster is deliberately not given a palette, where MorphWeightSystem does give one. A virtualized entity's caster (Caster) is an ordinary object drawn from MeshletMesh.Fallback through the suballocated path — so it is the classic branch, with the classic branch's missing influences, and writing a palette to it would turn the permutation on for a vertex format that cannot feed it. The consequence is real and is recorded rather than hidden: a skinned virtualized character's shadow is its bind pose until SurfaceVertex carries influences. That is #451's fourth link and #141's item (2), and it is the one thing here that cannot be closed by wiring.
⚠ Until #1221 this system was not in any game's loop at all, which was a link below the three #451 names: AnimationSystems.AddAnimation was called only by GizmoTests, and no animation system carries [GameSystem], so the generated registry added none of them and [UpdateInGroup] only orders a system something has already added. Widening a method nothing calls would have been a second finished thing nothing calls. That link is closed — #1221, Sample 13's Arena.Register and the editor's PlayAnimation contribution both call it.
⚠ What that does not settle is who hands the features over. Renderer and Virtualized have to be set by something that can see both this assembly and the renderer's, and Vixen.Engine.Renderer has no reference to Vixen.Animation — so WorldRenderer.Register cannot be that place and the application host has to be.
Matrices are computed into a rented buffer, not a per-entity one. A skeleton's palette is written and immediately copied into the feature's upload buffer, so it lives for the length of one call; holding one per character would be a hundred matrices of permanently resident memory per instance to save an ArrayPool rent.
Fields and properties (6)
public RenderSystem? RendererThe render system whose objects the palettes belong to.
public SkinningRenderFeature? FeatureThe feature that holds the palette buffer for suballocated meshes.
public VirtualGeometryRenderFeature? VirtualizedThe feature that draws virtualized meshes. Null is a harmless no-op.
public int SkinnedHow many objects were given a palette by the last run.
public int VirtualizedCountHow many of Skinned were virtualized rather than suballocated.
public SystemAccess AccessWhat this system reads and writes.
Methods (2)
public override JobHandle Update(in SystemContext context, JobHandle dependency)Runs the system.
public void Run(World world)Fills every skinned object's palette from its animator's pose.
Used by (4)
- AnimationSystemsVixen.Animation
- EcsIntegrationTestsVixen.Animation.Tests
- SkinningWiringTestsVixen.Animation.Tests
- AnimationWiringTestsVixen.Editor.App.Tests