よくあるミス
ブロックの閉じ忘れ
{ に対応する } がない場合に発生します。
// NG
OnBoot => {
湊: こんにちは。
// } を忘れている
インデントを揃えると見つけやすくなります。
比較に = を使う
条件式で == のところを = と書いてしまうケースです。
湊はこれを検出してエラーメッセージを出します。
// NG
if (save.フラグ = true) {
// OK
if (save.フラグ == true) {
キャラクター名のtypo
config.toml に登録していない名前を使っても、セリフは出ます。
ただし未登録の名前は \0(メインキャラ)として扱われるため、
本来 \1 のキャラが喋るはずのセリフが \0 の口から出るなど、話者だけが誤ります。
# config.toml
[characters]
"湊" = "\\0"
"助手" = "\\1"
// NG(「じょしゅ」は登録されていないので \0 で喋ってしまう)
じょしゅ: よろしくお願いします。
// OK
助手: よろしくお願いします。
セリフの話者がおかしいときは、: の前の名前が config.toml の [characters] と
一字一句同じか確認してください。
また、日本語のキャラクター名は config.toml 側で "湊" のように引用符で囲む必要があります。
global と let の混同
let で宣言した変数はトークが終わると消えます。
次回の起動で使いたい値は global save.* に保存してください。
// NG(次回起動時には消えている)
let 訪問回数 = 0
訪問回数 += 1
// OK
global save.訪問回数 += 1
文字列展開の閉じ忘れ
${ に対応する } がない場合に発生します。
// NG
湊: ${save.訪問回数回目です。
// OK
湊: ${save.訪問回数}回目です。
セリフ中の「名前.名前」が消える
セリフの行頭と ${…} の直後では、. を含む語が 変数.キー という変数の参照として読まれます。
読まれる範囲は、半角の空白や記号が出てくるまでです。かなや句読点は区切りにならないので、文の最後まで1つの参照になり、まとめて消えます。
// NG(何も表示されない)
湊: items.jsonを読み込みました。
// NG(items.json の部分だけ消え、「 を読み込みました。」が表示される)
湊: items.json を読み込みました。
// OK(文字列として埋め込む)
湊: ${"items.json"}を読み込みました。
エラーにはならず、セリフはそのまま出ます。ただし応答には警告(変数がないとき)か注意(キーがないとき)が付くので、SSPのエラーログで気づけます。
ファイル名・小数・バージョンなど . を含む語をそのまま見せたいときは、${"..."} で文字列として書いてください。
詳しい例は、移行ガイドのFAQ「セリフが丸ごと消える」にあります。
callした名前のtypo
call で呼んだトーク・関数が見つからなくても、エラーにはならず何も起こりません。
セリフが出ないだけなので、気づきにくいミスです。
静的チェックはこれを notice で知らせます。メッセージは呼び方によって3種類あります。 どれも構文チェッカーで確かめられます。
「は未定義です(動的callなら無視してください)」
call 名前 の名前が、どのトークにも関数にもないときに出ます。
挨拶する => {
湊: こんにちは。
}
OnBoot => {
call 挨拶 // 「挨拶する」の書き間違い
}
[notice] main.mntの6行目(OnBoot内): "挨拶" は未定義です(動的callなら無視してください)
ただし、変数に入れた名前を呼ぶ動的callでも同じ notice が出ます。
let target = "挨拶する" のあとの call target などは、変数名 target が未定義と判定されるためです。
動的callのつもりで書いたのなら、この notice は無視してかまいません。
「同じ「〜.」で始まるトークはありますが、この名前はありません」
call OnUpdate.OnTypo のようなドット付きの名前で、同じ前半(OnUpdate.)のトークはあるのに、その名前だけがないときに出ます。
OnUpdate.OnDownloadBegin => {
湊: ダウンロードを始めるよ。
}
OnBoot => {
call OnUpdate.OnDownloadBigin // 「Begin」の書き間違い
}
ドット付きの名前は call reference.0 のような動的callと見分けがつかないので、
同じ前半のトークが1つもないときは何も出ません。
「ビルトイン関数でも talk でも func でもありません」
名前(引数) の形で呼んだ名前が、ビルトイン関数にもトークにも関数にもないときに出ます。
行の先頭に書いた呼び出しだけでなく、let の右辺、if の条件、セリフ中の ${...}、ほかの関数の引数など、式の中の呼び出しも対象です。
func 挨拶する(name) {
湊: ${name}さん、こんにちは。
}
OnBoot => {
挨拶すろ("ユーザー") // 「挨拶する」の書き間違い
}
この形は動的callになることがないので、出たら書き間違いと考えてください。
OnBoot => {
let n = lenght(items) // 「len」の書き間違い。これも notice が出る
}
トーク名の後ろに書く if(条件式)(条件フィルタ)の中の呼び出しも対象です。
ビルトイン関数の名前はビルトイン関数で確かめられます。
ループの外でのbreak / continue
ループの外で break や continue を使うとエラーになります。
静的チェックで検出されます。
// NG
OnBoot => {
break
}
// OK
OnBoot => {
for (let i = 0; i < 5; i++) {
break
}
}
ファイルやJSONが読み込めない
file_read や json_parse は、失敗しても台本を止めずに null を返します。
そのまま使うと、後の処理で別の警告が出て原因がわかりにくくなるので、is_null で確かめてください。
let text = file_read("ghost/master/items.json")
if (is_null(text)) {
湊: items.json が読めませんでした。
}
失敗した理由は、応答の ErrorLevel / ErrorDescription に警告として載ります。よくある原因は次のとおりです。
| 症状 | 原因 | 対処 |
|---|---|---|
file_read が null | パスが違う | パスはゴーストのホーム(ghost フォルダの1つ上)から書きます。"items.json" ではなく "ghost/master/items.json" |
file_read が null | ファイルが1MBを超えている | ファイルを分けてください |
file_read が null | Shift_JIS のファイルを UTF-8 として読んだ | 第2引数に "sjis" を指定します |
json_parse が null | JSONの書き方の誤り(末尾の余分な ,、コメント、' で囲んだ文字列など) | 警告の「JSONの読み込みに失敗しました(1行目9文字目: 書き方が正しくありません)」の位置を見て直してください |
file_write が false | 書き込めない場所を指定した | 書けるのは ghost/master の中だけです。talks フォルダや config.toml などには書けません |
| エラーになる | 絶対パスや .. を含むパスを指定した | 禁止されたパスは警告ではなくエラーになります。相対パスで書いてください |
file_move が false | 移動先に同名のファイルがある | 上書きするなら第3引数に true を指定します |
制限の一覧はファイルとJSONにあります。