はじめに
『Fy Mascot』はMMDモデルやセリフ(テキストファイル)などを用意することで誰でも俺の嫁お気に入りのキャラクターを作ることができます。キャラクターの作成には、『Fy
Mascot』に付属しているキャラクターを参考にするとわかりやすいと思います。
キャラクターエンジンも含めて完全にオリジナルのキャラクターを作ることもできますが、付属しているキャラクターはセリフをスクリプト(テキストファイル)として分けているので、メモ帳でスクリプトを編集するだけでキャラクターに好きなセリフを話してもらうことができます。
まずは、モデルデータとセリフスクリプトでオリジナルのキャラクター作りにチャレンジしてみて下さい!
キャラクターデータ
キャラクターデータは『character』フォルダの中に、キャラクターごとにフォルダに分けて入っています。
キャラクターは以下のファイルで構成されています。
情報ファイル類
各キャラクターには『情報ファイル類』として、『document.xml』や『イメージ画像(image.png/icon.png)』などがあります。
・画像ファイル
『icon.png』、『image.png』の画像は、プロパティシートで表示される画像です。『icon.png』は120×120ピクセル、『image.png』は480×360ピクセルの画像です。
・ドキュメントファイル
『document.xml』はキャラクターの各種情報が書かれたもので、キャラクター自体の情報やキャラクターエンジンなどが書かれています。『document.xml』は『XML』形式の文字コードがUTF8のテキストファイルで、『メモ帳』で開くと編集ができます。
モデルとモーションデータ
『Fy Mascot』ではキャラクターにMMDモデルを使っています。MMDの『モデルデータ』と『モーション』および『情報ファイル』が必要です。すべてのファイルをキャラクターの『model』フォルダに保存します。
・モデルとモーションデータ
キャラクター一人に対して、『MMDモデル(PMD/PMX)』が一つ、何もしていない時の『モーション(VMD)』が一つ必要で、『モーション』はリアクションにあわせて増やすことができます。
『MMDモデル』のファイル名は『model』、モーションデータのファイル名は『model+3桁の数字』になります。数字は000から順番にふる必要があります(抜けるとそこから先は無視されます)。モーションは最低1つ以上、最大128個以下です。
マスコットのリアクションがどのモーションに対応するかは後述の『MMD情報ファイル』に記述するので、とりあえず順番に並べておけばOKです。下のモーションの対応表は例です。
『MMDモデル』には画像など複数のデータが入っていますが、中身のデータの意味がよく分らないのでとりあえず全部丸ごとキャラクターの『model』フォルダに入れてください(笑)。
・情報ファイル
モデルの位置とモーション情報を記述した『モデル情報ファイル』と、モーションごとのアタリ判定を記述した『モーション情報ファイル』があります。『モデル情報ファイル』のファイル名はモデルファイルと同じで、『モーション情報ファイル』のファイル名はモーションファイルと同じになります。
ファイルは文字コードがUTF8のテキストファイルで、$から始まる行はコメントとして無視されます。コメントは何行あっても構いませんが一行あたりの文字数は全角で100文字程度にしてください。
☆モデル情報ファイル
モデル情報ファイルにはモデルの位置などの設定と、モーションの情報を記述します。
@CAMERA:/@MODEL:
@CAMERAはMMDモデルのカメラ座標です。前の3つがカメラのXYZ座標、後ろ3つが向きのXYZ座標です。下の例では[Camera X, Camera Y, Camera Z]にあるカメラを[Target X, Target Y, Target Z]に向けて設定します。
@MODELはMMDモデルの位置です。前の3つがモデルのXYZ座標、後ろ3つがX軸、Y軸、Z軸で何度(0°~360°)回転させるかを設定します。下の例ではモデルを[X, Y, Z]においてX軸でRotation X度,Y軸でRotation Y度、Z軸でRotation Z度回転させた状態にします。
| @CAMERA:Camera X,Camera Y,Camera Z,Target X,Target Y,Target Z |
| @MODEL:X,Y,Z,Rotation X,Rotation Y,Rotation Z |
#モーションセット
#から始まる行はモーションセットの情報です。『キャラクターエンジン』から送られてくるモーションセットに対して、どのモーションを実行するのかを記述します。モーションセットは半角英数字で255文字以内です。
『everyday』が何もしていないときのモーションなので必ず記述してください。
| #モーションセット:動作モード,モーション番号 |
動作モードは、1回だけ行って通常のモーションに戻る場合は『ONCE』、次のモーションが指示されるまで繰り返す場合は『LOOP』を指定します。たとえば、『test』というモーションが送られてきた場合は、『model001.vmd』のモーションを1回だけ実行する場合は下記のようになります。
| #test:ONCE,1 |
複数のモーションを続けて行うよう記述することもできます。最大で16個まで対応しています。たとえば、『dance』というモーション名が『model002.vmd』→『model004.vmd』→『model006.vmd』→『model004.vmd』の順に繰り返し実行する場合は下記のように記述します。
| #dance:LOOP,2,4,6,4 |
複数のモーションからランダムで1つを選択するよう記述することもできます。たとえば、『angry』というモーションが『model003.vmd』→『model005.vmd』と『model009.vmd』のどちらか →『model007.vmd』の順に1回だけ実行する場合は下記のように記述します。なお、例は2つですが3つ以上から選択することも可能です。
| #dance:ONCE,3,$select{5|9},7 |
☆モーション情報ファイル
モーション情報ファイルにはアタリの情報を記述します。アタリは一つのモーションにつき最大16個です。アタリはクリック又はストローク(なでる)した際に『キャラクターエンジン』に送られます。アタリの動作は『キャラクターエンジン』次第で、対応してない場合は何の反応もしてくれません。
アタリの情報はアタリ名と位置(パーセンテージ)を記述します。アタリ名は半角英数字で255文字以内です。位置はキャラクターのウィンドウ(見えないですが解像度で設定したキャラクターが動き回れるエリア)の、上下は上からの距離、左右は中央からの距離をパーセンテージで(左,上,右,下)の順に記述します。
例えば下図の赤い四角で囲った領域(キャラクターの顔)でアタリ名がFACEならば、矢印で示した部分の距離となるので下記のようになります。激しく動くモーションでは適切な判定にならないかもしれませんが、まぁ細かいことは気にしないで頂けるとありがたいです。
| #FACE:5,20,5,30 |
キャラクターエンジン
キャラクターのセリフとモーションは、『キャラクターエンジン』というプログラム(DLL)でコントロールしています。『キャラクターエンジン』は、『Fy Mascot』からイベントが送られてきたら、それに応じてなんらかの反応(モーションとセリフ)をします。
『キャラクターエンジン』は仕様を公開しており、『Fy Mascot』にサンプルソースコードも添付しているのでオリジナルの『キャラクターエンジン』を作ることもできます。作成するにはプログラミング(C言語)の技術が必要になりますが、それだけに工夫次第ではかなり自由度が高いのがポイントです。
セリフスクリプト
添付のキャラクターの『キャラクターエンジン』では、イベントごとのセリフやモーションをスクリプト(テキストファイル)として保存しており、それを使ってイベントをこなします。このため、プログラムを書き換えなくてもスクリプトファイルを追加することで新たなイベントに対応することができるのが特徴です。
セリフスクリプトはキャラクターの『scripts』フォルダに保存してあり、ファイル名は『script+3桁の数字』になります。数字は000から順番にふる必要があります(抜けるとそこから先は無視されます)。セリフがどのイベントに対応するかは後述の『イベント情報』に記述するので、とりあえず順番に並べておけばOKです。
添付のキャラクターの『キャラクターエンジン』では、スクリプトファイルがないイベントが送られてきた場合は無視するようになっているので、全てのイベントを網羅する必要はありません。まずは最低限のセリフを選んで編集して、残りを削除することで無理なくキャラクターを作ることができます。
セリフスクリプトの概要
セリフスクリプトは、『イベント情報』と『セリフスクリプト』で構成されています。なお、イベント名でファイルを管理しているのでスクリプトファイルのファイル名は自由です。
☆イベント情報
イベント情報はこのスクリプトファイルが使われるイベントです。『information』と『parameter』の2つのパラメータがあり、『Fy Mascot』から送られてくるNOTICE-EXECUTIONの『event』タグに対応します。
例えば、マスコットをクリックすると『information』に『NOTICE』、『parameter』に『CLICK』というイベントが送られてきます。『キャラクターエンジン』はスクリプトファイルから、『information』が『NOTICE』で『parameter』が『CLICK』となっているものからセリフを選びます。
| 『information』 | 『parameter』 | 意味 |
|---|---|---|
| NOTICE | START | マスコット(キャラクター)が起動した。 |
| EXIT(※) | マスコットに終了コマンドが送られた。 | |
| STANDBY | マスコットがスタンバイ状態になった。 | |
| WAKEUP | マスコットがスタンバイ状態から復帰した。 | |
| TWEET | ひとりごとをつぶやく。 | |
| HEALTHCARE | パソコンが起動してから時間が経過した(休息を促す)。 | |
| BACKSEAT | スクリーンセーバーが解除された(席に戻った)。 | |
| RESOURCE | リソースの使用率が高い。 | |
| CHANGECHARACTER | キャラクターが変更された。 | |
| DROPFILE | キャラクターにファイルがドロップされた。 | |
| CLICK | キャラクターがツツかれた。 | |
| STROKE | キャラクターがナデられた。 | |
| MESSAGE | キャラクターに情報をしゃべってもらう。 | |
| NOTSUPPORTED | 対応していないオーダー・パラメータが実行された。 |
☆セリフアイテム
セリフアイテムはナンバー、アトリビュート(属性)、セリフスクリプトで構成されます。
☆ナンバー
セリフアイテムのナンバーで1から順番に欠番や重複のないようにふります。なお番号が抜けるとそこで検索が打ち切られてその後のセリフアイテムが無効になってしまうので注意してください。
☆アトリビュート(属性)
同じイベントでも『時間や季節』などによってセリフが変化した方がそれらしいですよね? 『キャラクターエンジン』はアトリビュートを使ってセリフアイテムの中から最適なセリフを選択することができます。例えば挨拶を朝と夜では異なるセリフにするといったことができるようになります。
各セリフアイテムは、カンマで区切って複数のアトリビュートを記述することができます。アトリビュートは最大で16個以下で全体で半角英数255文字以下(全角の場合は100文字程度)です。
| 『attribute』 |
| <attribute>属性1,属性2,属性3,属性4</attribute> |
また、『キャラクターエンジン』も下記に記載する複数のアトリビュートでマッチングを掛け、ヒット率がより高くなったセリフアイテムを選択する仕組みとなっています。なお、各アトリビュートにはウェイト(重みずけ)が設定されており、ヒットしたアトリビュートのウェイトの合計がヒット率です。
イベントにかかわらず自動的に設定されるアトリビュート。
| イベント | アトリビュート | ウェイト | 意味 |
|---|---|---|---|
| ツンデレ | TSUN | 1.0 | ツンとデレの出現割合は設定画面のスライダーで調整できます。 |
| DERE | 1.0 | ||
| 月 | JANUARY | 1.5 | 1月 |
| FEBRUARY | 1.5 | 2月 | |
| MARCH | 1.5 | 3月 | |
| APRIL | 1.5 | 4月 | |
| MAY | 1.5 | 5月 | |
| JUNE | 1.5 | 6月 | |
| JULY | 1.5 | 7月 | |
| AUGUST | 1.5 | 8月 | |
| SEPTEMBER | 1.5 | 9月 | |
| OCTOBER | 1.5 | 10月 | |
| NOVEMBER | 1.5 | 11月 | |
| DECEMBER | 1.5 | 12月 | |
| 曜日 | SUNDAY | 1.5 | 日曜日 |
| MONDAY | 1.5 | 月曜日 | |
| TUESDAY | 1.5 | 火曜日 | WEDNESDAY | 1.5 | 水曜日 |
| THURSDAY | 1.5 | 木曜日 | |
| FRIDAY | 1.5 | 金曜日 | |
| SATURDAY | 1.5 | 土曜日 | |
| 時間 | **:00 | 1.5 | **に0~23の時間が入る。 |
| 季節 | WINTER | 1.0 | 冬 12月~2月 |
| SPRING | 1.0 | 春 3月~5月 | |
| SUMMER | 1.0 | 夏 6月~8月 | |
| AUTUMN | 1.0 | 秋 9月~11月 | |
| 曜日 | WEEKDAY | 1.0 | 平日 |
| WEEKEND | 1.0 | 土日 (祝日の取得が面倒だったので…) | |
| 時間帯 | DAWN | 1.0 | 早朝 4時~6時(含まず) |
| MORNING | 1.0 | 朝 6時~11時(含まず) | |
| DAYTIME | 1.0 | 日中 11時~18時(含まず) | |
| NIGHT | 1.0 | 日中 18時~24時(含まず) | |
| MIDNIGHT | 1.0 | 夜中 0時~4時(含まず) | |
| その他 | NORMAL | 0.5 | 常時設定され、他にヒットがない場合などに選択。 |
イベントによって設定される独自のアトリビュート。
| イベント | アトリビュート | ウェイト | 意味 |
|---|---|---|---|
| START | FIRSTRUN | 3.0 | 初めて起動された |
| AGAIN | 3.0 | ついさっき起動したばかり | |
| REVIVE | 3.0 | 久しぶりに起動した | |
| HEALTHCARE | SUGGEST | 3.0 | ふつう |
| CAUTION | 3.0 | やばめ | |
| DANGER | 3.0 | 廃 | |
| BACKSEAT | SHORT | 3.0 | 短い時間席を離れていた |
| MIDDLE | 3.0 | 普通な時間席を離れていた | |
| LONG | 3.0 | 長い時間席を離れていた | |
| RESOURCE | CPU | 3.0 | CPU占有率が高い |
| MEMORY | 3.0 | メモリの使用率が高い | |
| CLICK | (アタリ名) | 5.0 | クリックされたアタリの名前 |
| CLICK | IMPULSE | 3.0 | 偶発的なクリック |
| FREQUENT | 3.0 | 頻繁なクリック | |
| HABITUAL | 3.0 | 常習的なクリック | |
| STROKE | (アタリ名) | 5.0 | クリックされたアタリの名前 |
| MESSAGE | (sender名) | 5.0 | メッセージの送り手の名前 |
☆スクリプト構文
セリフファイルにはいくつかのスクリプト構文があります。
- $select{"string1"|"string2"}
- $replace{word}
$select{"string1"|"string2"}は、複数のセンテンスからランダムで一つ選ぶ場合に利用します。
例えば、『私は甘い物は$select{"好き"|"嫌い"}です。』のように使えば、『私は甘い物は好きです。』か『私は甘い物が嫌いです。』がランダムで選択されます。センテンスの前後に『"』があることに注意してください。
$replace{word}は、特定の文字に置き換える場合に利用します。表のような日にちや時間といったものと、アプリケーション側から指定されたものがあります。
| 置き換え文字 | 意味 |
|---|---|
| character | キャラクターの名前で置き換えます。 |
| year | 今年の西暦で置き換えます。 |
| month | 今月の月で置き換えます。 |
| day | 今日の日にちで置き換えます。 |
| hour | 今の時間で置き換えます。 |
| minute | 今の分で置き換えます。 |
| week | 今日の曜日で置き換えます。 |
| season | 季節(春,夏,秋,冬)で置き換えます。 |
| period | 時間帯(早朝,朝,昼間,夜,真夜中)で置き換えます。 |
| sender | イベントの『information』が『MESSAGE』の時、送り手の名前で置き換えます。 (『sender』要素に記述された内容) |
| message | イベントの『information』が『MESSAGE』の時、送られてきた言葉で置き換えます。 (『message』要素に記述された内容) |

☆スクリプト記号
セリフには、それらしく表示するためにいくつかのスクリプト記号をが用意されています。
| 記号 | 意味 |
|---|---|
| \n | 改行します。 |
| \w[数字] | 次の文字を表示するまで間をおきます。 (数字は何ミリ秒待つかを指定) |
| \e | 表示したセリフを消去します。 |
| \m[モーション名] | モーションセットを実行します。 モーション名は半角英数字で255文字以内です。 |
| \\ | \(円マーク)を表示します。 (\\を表示したい場合は\\\\と記述) |
生成AIでのセリフの作成
セリフはテキストファイルなので誰でも簡単に作ることができますが、マスコットに飽きないように色々なことを話してもらうためには大量のセリフを作る必要があります。また、自分で作ったセリフをしゃべられても微妙な気分になってしまうかもしれません。
そこでオススメするのが大量のセリフを簡単に用意できる生成AIの活用です。テキストベースでお題に沿ってたくさん列挙するのは生成AIの得意とするところで、そのキャラクターらしいセリフを作ることはもちろん、モーションやタグなどもちゃんと出力できます。
| 生成AIへのプロンプトの例 |
|
デスクトップマスコットのセリフを作ってもらいます。 以下のルールに従ってセリフを生成してください。 設定されたキャラクター性を強く反映した自然な会話文を作成してください。 1. キャラクター設定 (既存のキャラクターの場合) 例 : アニメ〇〇の〇〇 (オリジナルキャラクターの場合) 例 : 時代劇とお酒をこよなく愛する、クールでカッコいいメイドさん 2. モーション(表情・動作) セリフの先頭や文脈の切り替わりに以下のタグを挿入してください。 ※以下のリストにない独自のタグ(例:\m[jito]など)はシステムエラーの原因となるため禁止です。 \m[smile] … 笑った感じ \m[bow] … お辞儀 \m[yareyare] … やれやれ \m[sleepy] … 眠そう \m[bother] … 飽きた感じ \m[action] … 片手をあげてハイって感じ \m[bashful] … はにかむ感じ \m[scolding] … ぷんすこ怒る感じ \m[joke] … 冗談だよって感じ \m[talk]… お話する感じ \m[bye] … じゃぁねという感じ 3. ランダム選択機能 セリフが単調にならないよう、一部の言葉やフレーズをランダム化してください。 書式: $select{"言葉1"|"文章2"|"文章3"} (3つ以上も可) 4. 置換機能 以下のタグはシステム側でセリフを発されたタイミングに合わせて自動的に変換されます。 $replace{year} (年) $replace{month} (月) $replace{hour} (時) $replace{minute} (分) $replace{season} (季節) $replace{period} (時間帯:朝、昼、晩など) 5. 出力フォーマット(XML) 以下のXML形式で出力してください。 <item no="連番(1から開始)"> <attribute>指定された属性</attribute> <script>生成したセリフ(アクションや置換タグを含む)</script> </item> no="数字"は、各シチュエーションごとに1から始まる「通し番号」にして下さい(例:「終了時のセリフ」の中で1〜40、「起動時のセリフ」で1〜64など)。 属性が複数ある場合はカンマ(,)で区切ります。(例:BUST,IMPULSE、MORNING,SPRINGなど) ※XML形式としてコピペできるよう<や>はエスケープ文字の<や>にしないでください。 ※見やすくするため改行はしますが、空白行などは入れないでください。 以下のシチュエーションと属性の組み合わせを、それぞれ8通りずつ作成してください。 【作成するセリフのリスト】 ■ 1. 起動時のセリフ(全64個 / 通し番号1〜64) 属性(8種): FIRSTRUN, AGAIN, REVIVE, DAWN, MORNING, DAYTIME, NIGHT, MIDNIGHT ※FIRSTRUN(初回), AGAIN(頻繁), REVIVE(久しぶり)は期間の概念、他は時間帯。 ■ 2. 終了時のセリフ(全40個 / 通し番号1〜40) 属性(5種): DAWN, MORNING, DAYTIME, NIGHT, MIDNIGHT ■ 3. ウェイクアップ時(スタンバイ・非表示からの復帰)(全40個 / 通し番号1〜40) 属性(5種): DAWN, MORNING, DAYTIME, NIGHT, MIDNIGHT ■ 4. ヘルスケア(PC起動時間に応じた休憩勧告)(全24個 / 通し番号1〜24) 属性(3種): SUGGEST(提案), CAUTION(警告), DANGER(危険) ■ 5. 離席からの復帰(スクリーンセーバー解除時)(全24個 / 通し番号1〜24) 属性(3種): SHORT(数分), MIDDLE(数十分), LONG(数時間以上) ■ 6. リソース警告(CPUやメモリの高負荷時)(全16個 / 通し番号1〜16) 属性(2種): CPU, MEMORY ■ 7. クリック反応(マウスクリック時)(全32個 / 通し番号1〜32) 属性① (2種) : FACE, BUST・・・これはクリックされた場所。 属性② (3種類) : IMPULSE, FREQUENT, HABITUAL・・・これは頻度。 ※顔(FACE)は頻度はいらないのでFACE単体 FACE BUSTは単発(IMPULSE)・頻繁(FREQUENT)・執拗(HABITUAL)で変化させる。 BUST,IMPULSE BUST,FREQUENT BUST,HABITUAL |
NOTICE-EXECUTIONの拡張
添付のキャラクターの『キャラクターエンジン』には、NOTICE-EXECUTIONで『information』が『NOTICE』で『parameter』がMESSAGEのイベントで、ユーザーデータ『userdata』を使った拡張機能を搭載しています。
このイベントは、本来どのオプションプログラムからでも同じように読み上げるのですが、『userdata』に『extension』要素を追加することでオプションプログラムごとに違ったリアクションができるようになります。この要素がない場合でも通常通り一般的なリアクションをとります。
自作のオプションプログラムを作って、キャラクター側に対応するセリフスクリプトを用意することで、独自の機能でキャラクターに自然なセリフを話してもらうことが可能になります。
『extension』
| 『extension』 |
| <extension> <attribute>属性</attribute> <replace> <item no="1"><key>word1</key><word>言葉1</word></item> <item no="2"><key>word2</key><word>言葉2</word></item> <item no="3"><key>word3</key><word>言葉3</word></item> </replace> </extension> |
この要素は、『attribute』と『replace』で構成されます。
『attribute』はスクリプトファイルの『attribute』に対応してセリフを選択するのに使われます。現時点では、こちらはスクリプトのようなカンマ区切りによる複数のアトリビュートの指定には対応していません。
『replace』は任意で必要に応じて置き換える言葉を記述します。下の例ではスクリプトの『$replace{word}』という部分を『晴れのち曇り』という言葉に置き換えています。スクリプトファイルの項に記載された既定の置き換え文字は使わないでください。
初回起動時のキャラクター
初回起動時のキャラクターは"chanoletta"になっていますが、『config.ini』というテキストファイルを作成し例えば下記のように記述すると『orenoyome』というフォルダのキャラクターが初回起動時に選択されます。独自キャラクターを添付して配布する場合などに便利です。
| [CHARACTER] CHARACTER=orenoyome |
※ 二回目以降はセーブデータを初期化しない限りは、選択されているキャラクターが選択されます。