BipedPlus

Ep.18 — Customizing 03: 命名规范 & 团队模板

下载 Markdown 含图片下载

如果无法访问 YouTube,可在 Bilibili 搜索 OtakuSolutions 频道观看相关内容。

本文档说明如何将 BipedPlus 命名调整为工作室规范,并保存为可重复使用的 common 模板

如果无法访问 YouTube,可在 Bilibili 搜索 OtakuSolutions 频道观看相关内容。

1. 为什么需要

当 BipedPlus 默认命名(Skin_*Ctrl_*Bip001)与团队规则不匹配时,工作流程就会受阻。
可以进行重命名——关键是将结果保存为模板,避免每次重复操作

2. 完整流程

BipedPlus Naming & Template Pipeline

3. 命名变更的允许范围和注意事项

类型 内容
✅ 可以更改 Biped 名称、Skin 骨骼名称(与引擎骨骼名对应)、控制器前缀、层显示名称
⚠️ 注意 使用统一批量规则重命名,避免破坏 Hierarchy / Constraint / Space
❌ 禁止省略 Fix Missing 重命名后不执行 Fix Missing 将导致 Mirror / Picker / Reset 失效

4. Fix Missing — 重命名后保持系统同步

名称更改后,INFO 记录的旧名称会不匹配,导致 Missing 错误。

概念 说明
Seed 即使节点被重命名,也能识别该节点的唯一地址值
Fix Missing 利用 Seed 重新链接重命名后节点的功能

操作步骤:Rig Info → Load → 检查 Missing → 执行 Fix Missing → 确认镜像更新 → 通过 Ani Utils 验证

5. 自定义层名称

层设置 → Edit Name → 新建预设(团队/产品名)→ 添加前缀/后缀 → Apply to Rename
保持 Hierarchy 中的角色分类不变——只将显示标签改为符合团队规范的名称。

6. 保存为 common 模板

步骤 内容
1 打开建模场景(或新建文件)
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
重命名后 可恢复 基于名称——布局可能失效

推荐:在命名和模板确定后,用新命名重建 Picker,并与模板 .max 一起分发给团队。
Picker 文件位置在 BipedPlus Settings 中查看。

8. 检查清单

  • [ ] 团队的 bone / Ctrl / Layer 命名规则已文档化
  • [ ] 使用批量重命名脚本(或团队脚本)
  • [ ] 重命名后:验证 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.

需要更多帮助?

联系支持