BipedPlus
Ep.18 — Customizing 03: 네이밍 & 팀 템플릿
마크다운 다운로드 이미지 포함 다운로드스튜디오 네이밍으로 고친 뒤, 한 번만 만들고 common 템플릿으로 재사용하는 방법을 정리한 문서입니다.
1. 왜 필요한가
BipedPlus 기본 네이밍(Skin_*, Ctrl_*, Bip001)이 팀 규칙과 다르면 막히는 경우가 많습니다.
팀 규칙으로 바꿀 수 있고, 매번 Rename을 반복하지 않도록 템플릿으로 저장하는 것이 핵심입니다.
2. 전체 파이프라인

3. 네이밍 변경 허용 범위 및 주의사항
| 구분 | 내용 |
|---|---|
| ✅ 변경 가능 | Biped 이름, Skin 본 이름 (엔진 bone name 일치 목적), Controller 접두사, Layer 표시 이름 |
| ⚠️ 주의 | Hierarchy / Constraint / Space가 깨지지 않게 일괄 규칙으로 변경 권장 |
| ❌ Fix Missing 생략 금지 | Rename 후 Fix Missing을 안 하면 Mirror / Picker / Reset 어긋남 |
4. Fix Missing — Rename 후에도 시스템이 따라오게
이름이 바뀌면 INFO에 기록된 예전 이름과 어긋나 Missing이 납니다.
| 개념 | 설명 |
|---|---|
| Seed | 이름이 바뀌어도 노드를 구별하기 위한 유니크한 주소값 |
| Fix Missing | Seed를 이용해 새 이름 노드를 다시 링크하는 기능 |
절차: Rig Info → Load → Missing 확인 → Fix Missing 실행 → Mirror 갱신 확인 → Ani Utils로 검증
5. 레이어 이름 커스터마이징
Layer 설정 → Edit Name → 팀/프로덕트명 프리셋 → 접두/접미 추가 → Apply to Rename
Hierarchy의 역할 분류는 유지하고, 표시 이름만 팀에 맞춥니다.
6. common 템플릿으로 저장
| 단계 | 내용 |
|---|---|
| 1 | 모델링 씬 (또는 New File) |
| 2 | Merge — common/BP_Human_Template.max의 노드 모두 |
| 3 | BipedPlus Scan — INFO / 미러 등 유지 확인 |
| 4 | Figure / 비율 등 캐릭터별 조정 |
| 5 | 캐릭터 폴더에 저장 → 애니 팀 배포 (Player로 작업) |
공유_리깅/
├── character_A/
├── character_B/
└── common/
└── BP_Human_Template.max ← 네이밍·레이어·INFO까지 맞춘 마스터
7. Picker 예외
| INFO / Ani Utils (Fix Missing 후) | Picker | |
|---|---|---|
| Rename 후 | 복구 가능 | 이름 기반이라 레이아웃이 깨질 수 있음 |
권장: 네이밍·템플릿이 확정된 뒤 새 네이밍으로 Picker를 재구성하고 팀에 배포.
Picker 파일 위치는 BipedPlus Setting 옵션에서 확인.
8. 체크리스트
- [ ] 팀 bone / Ctrl / Layer 네이밍 규칙이 문서화되어 있다
- [ ] Rename 예제(또는 팀 스크립트)로 일괄 변경한다
- [ ] Rename 후 Fix Missing + Mirror / Reset 검증을 한다
- [ ]
common/템플릿.max가 공유폴더에 있다 - [ ] 새 캐릭터는 Merge → Scan 절차를 쓴다
- [ ] Picker는 최종 네이밍 기준으로 재구성한다
- [ ] 애니 팀은 Player로 동일 설치 파일을 쓴다
Example Rename Script (handle 2-pass)
Edit NODE_RENAME_MAP to match your team's rules. Run in Max Script Editor after Build.
# -*- coding: utf-8 -*-
"""BipedPlus naming example (handle 2-pass, short version)"""
import pymxs
rt = pymxs.runtime
NODE_RENAME_MAP = [
("Bip001", "Bip009"),
("Bip001 Pelvis", "Bip009 Pelvis"),
("Ctrl_Head", "CTL_Head"),
("Skin_Spine1", "Bip001_Spine1"),
("Skin_L_Hand", "Bip001_L_Hand"),
]
def rename_nodes_by_handle(rename_map=None):
mapping = rename_map if rename_map is not None else NODE_RENAME_MAP
if not mapping:
raise ValueError("NODE_RENAME_MAP is empty.")
# Phase 1 — collect handles
collected = []
for src, dst in mapping:
node = rt.getNodeByName(src)
if node is None:
print(f"[SKIP] {src}")
continue
collected.append((int(node.handle), src, dst))
if not collected:
raise ValueError("No rename targets found in scene.")
# Phase 2 — apply
for handle, src, dst in collected:
node = rt.maxOps.getNodeByHandle(handle)
if node is None:
raise RuntimeError(f"handle={handle} restore failed ({src} → {dst})")
node.name = dst
print(f"[OK] {src} → {dst}")
print(f"Done ({len(collected)} ok). Next: Rig Info → Fix Missing")
if __name__ == "__main__":
rename_nodes_by_handle()
After running: Rig Info → Fix Missing → verify Mirror / Reset.