メインコンテンツまでスキップ

表情

VRM キャラクターの表情を制御します。表情は名前付きのブレンドシェイプ -- happysadangryblink、および aaihoh などの口の形状 -- で、ウェイト値は 0.0 から 1.0 です。

インポート

import { Vrm } from "@hmcs/sdk";

表情の設定

setExpressions(weights) は現在の表情オーバーライドをすべて置換します。レコードに含まれない表情は VRMA アニメーションの制御に戻ります。

const character = await Vrm.findByName("MyAvatar");

// happy と blink をオーバーライド -- 他のすべての表情はアニメーションに戻る
await character.setExpressions({ happy: 1.0, blink: 0.5 });

表情の変更

modifyExpressions(weights)部分的な更新を行います -- 指定された表情のみが変更されます。呼び出しに記載されていない既存のオーバーライドはそのまま維持されます。

// まず happy を設定
await character.modifyExpressions({ happy: 1.0 });

// 次に happy のオーバーライドを除去せずに blink を追加
await character.modifyExpressions({ blink: 1.0 });
// 結果:happy=1.0、blink=1.0
ヒント

どの表情をオーバーライドするか完全に制御したい場合は setExpressions を使用してください。他のオーバーライドを変更せずに変更をレイヤリングしたい場合は modifyExpressions を使用してください。

表情のクリア

clearExpressions() はすべての表情オーバーライドを削除し、VRMA アニメーションに完全な制御を戻します。

await character.clearExpressions();

これは、スクリプトによる表情シーケンスからアニメーション駆動の表情に戻すときに便利です。

口の表情

modifyMouth(weights) はリップシンク用の口の表情を設定します。未指定の口の表情は 0.0 にリセットされますが、口以外のオーバーライド(happyblink など)は維持されます。

// 「あ」の音の口の形状を設定
await character.modifyMouth({ aa: 0.8 });

// 「お」の音に変更 -- aa は 0 にリセット、他のオーバーライドは維持
await character.modifyMouth({ oh: 1.0 });

// 口を閉じる -- すべての口の表情が 0 にリセット
await character.modifyMouth({});

この分離により、リップシンクを感情表現とは独立して制御できます。

表情のクエリ

expressions() はすべての表情の現在の状態(ウェイトとメタデータを含む)を返します。

const { expressions } = await character.expressions();
for (const expr of expressions) {
if (expr.weight > 0) {
console.log(`${expr.name}: weight=${expr.weight}, binary=${expr.isBinary}`);
}
}

ExpressionInfo には以下が含まれます:

  • name -- 表情名(例:"happy""aa"
  • weight -- 現在のウェイト値(0.0--1.0)
  • isBinary -- 表情が 0 か 1 にスナップするかどうか(中間値なし)
  • overrideBlink -- この表情がまばたきとどう相互作用するか("none""blend"、または "block"
  • overrideLookAt -- この表情が視線追従とどう相互作用するか
  • overrideMouth -- この表情が口の表情とどう相互作用するか

利用可能な表情

ほとんどのモデルで利用可能な標準 VRM 表情:

カテゴリ表情
感情happyangrysadrelaxedsurprisedneutral
aaihoueeoh
blinkblinkLeftblinkRight
視線lookUplookDownlookLeftlookRight
注記

利用可能な表情は VRM モデルによって異なります。すべてのモデルがすべての表情を含んでいるわけではありません。特定のモデルがサポートする表情を確認するには expressions() を使用してください。

例:感情リアクションシーケンス

const character = await Vrm.findByName("MyAvatar");
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

// 驚きリアクション
await character.setExpressions({ surprised: 1.0 });
await sleep(1000);

// 嬉しい表情に移行
await character.setExpressions({ happy: 1.0 });
await sleep(2000);

// アニメーション制御に戻す
await character.clearExpressions();

型定義

interface ExpressionInfo {
name: string;
weight: number;
isBinary: boolean;
overrideBlink: OverrideType;
overrideLookAt: OverrideType;
overrideMouth: OverrideType;
}

interface ExpressionsResponse {
expressions: ExpressionInfo[];
}

type OverrideType = "none" | "blend" | "block";

次のステップ