Blender にてオブジェクトを選択した状態で、以下のスクリプトを実行して、VRChat と VRM で使用する空の Shape Keys を追加する。
※ パーフェクトシンクに関しては、「パーフェクトシンク対応」という記事で説明する。
スクリプト
# VRM0
import bpy
def add_shape_keys():
keys = [
"Basis",
"Neutral",
"A",
"I",
"U",
"E",
"O",
"Blink",
"Joy",
"Angry",
"Sorrow",
"Fun",
"LookUp",
"LookDown",
"LookLeft",
"LookRight",
"Blink_L",
"Blink_R",
"vrc.v_sil",
"vrc.v_PP",
"vrc.v_FF",
"vrc.v_TH",
"vrc.v_DD",
"vrc.v_kk",
"vrc.v_CH",
"vrc.v_SS",
"vrc.v_nn",
"vrc.v_RR",
"vrc.v_aa",
"vrc.v_E",
"vrc.v_ih",
"vrc.v_oh",
"vrc.v_ou"
]
if bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
for key in keys:
bpy.context.active_object.shape_key_add(name=key)
add_shape_keys()
#VRM1
import bpy
def add_shape_keys():
keys = [
"Basis",
"happy",
"angry",
"sad",
"relaxed",
"surprised",
"aa",
"ih",
"ou",
"ee",
"oh",
"blink",
"blinkLeft",
"blinkRight",
"lookUp",
"lookDown",
"lookLeft",
"lookRight",
"neutral",
"vrc.v_sil",
"vrc.v_PP",
"vrc.v_FF",
"vrc.v_TH",
"vrc.v_DD",
"vrc.v_kk",
"vrc.v_CH",
"vrc.v_SS",
"vrc.v_nn",
"vrc.v_RR",
"vrc.v_aa",
"vrc.v_E",
"vrc.v_ih",
"vrc.v_oh",
"vrc.v_ou"
]
if bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
for key in keys:
bpy.context.active_object.shape_key_add(name=key)
add_shape_keys()
シェイプキーの名前は、Unity で GetBlendShapeIndex() に渡す値が完全一致である必要があるため、大文字と小文字を区別して(スクリプトの通りに)設定する。
手順
- Workspace を Scripting に変更する
- New Text に 上記のスクリプトをコピペする
- 実行する
既に Basis が存在する場合は、Basis.001 が生成されるので、手動で削除するか、予め配列から Basis を削除する必要がある。(もしくは例外処理を書けば良い。)

Shape Key の命名について
VRChat のドキュメントには、BlendShape をどういう名前にすると auto detect されるか記載されていないが、VRCAvatarDescriptorEditor3LipSync.cs の AutoDetectVisemes() に以下のような記述がある。
if (s.ToLowerInvariant() == "vrc.v_" + viseme){}
if (s.ToLowerInvariant() == "v_" + viseme){}
if (s.ToLowerInvariant().EndsWith(viseme)){}
if (s.ToLowerInvariant() == viseme){}
if (s.ToLowerInvariant().Contains(viseme)){}
また、VRChat のドキュメントに Oculus viseme index を使用すると記載されている。そのため、一番上の条件を参考にすれば、vrc.v_sil のようにするのが良いと思われる。