Implementing 3D Character Skinning and Animation in CocosCreator 3.0
This guide details how to implement 3D character skinning and multi‑part animation in CocosCreator 3.0 by splitting FBX models into separate prefab components, addressing material, mesh, and simultaneous animation challenges, and provides key TypeScript code for part replacement.
Background
Company plans to develop a 3D community‑style English learning app with CocosCreator 3.0, allowing users to dress and change skins of their avatar while playing lip‑sync and body animations. This article presents a feasible solution for skinning and combined animation playback.
3D Model
CocosCreator supports FBX and glTF; the team chose FBX. FBX files contain textures, materials, meshes, skeletal animation and bone data.
FBX Model Structure
Describes the resource file and prefab hierarchy, showing that the clothes node uses cc.SkinnedMeshRenderer with Materials, Mesh and Skeleton components bound to resources.
Problems
Changing only Materials only alters color, not style.
Replacing Mesh affects the whole model binding.
Playing a second animation stops the first; multiple animations cannot play simultaneously.
Solution
Idea
The core idea is to split the original single‑model node into multiple independent model nodes for each replaceable part, keeping identical skeleton data across parts and controlling hierarchy to achieve the same visual result.
Implementation Steps
Define the avatar structure, separate parts (cloth, hair, face, etc.) into separate FBX prefabs, and attach them under placeholder nodes.
Key Code
Role.ts component that stores root nodes and prefab arrays and provides changePart method to instantiate and replace a part.
import { _decorator, Component, Node, Prefab, instantiate } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('Role')
export class Role extends Component {
@property(Node) totalRoot!: Node;
@property(Node) clothRoot!: Node;
@property(Node) hairRoot!: Node;
@property(Node) faceRoot!: Node;
@property({ type: [Prefab] }) clothPrefabs: Prefab[] = [];
@property({ type: [Prefab] }) hairPrefabs: Prefab[] = [];
@property({ type: [Prefab] }) facePrefabs: Prefab[] = [];
clothIdx = 0;
hairIdx = 0;
faceIdx = 0;
start () { /* ... */ }
changePart(partPrefabs: Prefab[], partName: string, partRoot: Node) {
let partIdx = 0;
if (partName === 'cloth') { this.clothIdx += 1; partIdx = this.clothIdx; }
if (partName === 'hair') { this.hairIdx += 1; partIdx = this.hairIdx; }
if (partName === 'face') { this.faceIdx += 1; partIdx = this.faceIdx; }
const partNode = instantiate(partPrefabs[partIdx % partPrefabs.length]);
partRoot.removeAllChildren();
partRoot.addChild(partNode);
}
}Other Notes
All split parts must share identical bone information; the approach enables simultaneous animation of multiple parts but does not solve the limitation of playing two animations on the same model.
Resource Size Analysis
Splitting adds a separate FBX prefab per part, each containing the same skeleton, so overall resource size is comparable to a single unsplit model.
Summary
Initial research assumed simple material/mesh replacement would work; practical issues led to the split‑model solution.
The method resulted from collaboration between developers and designers.
CocosCreator 3.0’s improved 3D support is appreciated.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
