BipedPlus

Ep.18 — Customizing 03: 네이밍 & 팀 템플릿

마크다운 다운로드 이미지 포함 다운로드

스튜디오 네이밍으로 고친 뒤, 한 번만 만들고 common 템플릿으로 재사용하는 방법을 정리한 문서입니다.

1. 왜 필요한가

BipedPlus 기본 네이밍(Skin_*, Ctrl_*, Bip001)이 팀 규칙과 다르면 막히는 경우가 많습니다.
팀 규칙으로 바꿀 수 있고, 매번 Rename을 반복하지 않도록 템플릿으로 저장하는 것이 핵심입니다.

2. 전체 파이프라인

BipedPlus Naming & Template Pipeline

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 Mergecommon/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.

추가 도움이 필요하신가요?

문의하기