MOD作成ガイド
このガイドでは、レンアイシステムのMODを作成する方法を初心者向けに解説します。
必要なもの
必須
- テキストエディタ(VSCode、Notepad++など)
- 画像編集ソフト(GIMP、Photoshopなど)
推奨
- JSON検証ツール
- 画像最適化ツール
MOD構造(分割管理)
ファイル構成
my_character_mod/
├── mod.json # メタデータ(18行程度)
├── character.json # キャラクター定義(470行程度)
├── events/ # イベントスクリプト(個別管理)
│ ├── first_meeting.json
│ ├── daily_conversation.json
│ └── confession.json
└── portraits/ # 立ち絵(階層構造)
└── spring/ # 季節フォルダ
├── uniform/ # 服装フォルダ
│ ├── normal.png
│ ├── happy.png
│ └── ...
└── casual/ # 私服フォルダ
├── normal.png
└── happy.png
基本的な流れ
- 企画: キャラクターの設定を考える
- 素材作成: 立ち絵や背景を用意
- MOD定義: mod.json・character.jsonを作成
- イベント作成: イベントスクリプトを書く(events/)
- テスト: ゲーム内で動作確認
- 配布: ZIPファイルにパッケージング
ステップ1: キャラクター設定
基本情報を決める
- 名前
- 年齢
- 性別(male / female)⭐ 重要
- 関係性タイプ(romance / friendship)⭐ 重要
- 性格
- 好きなもの・嫌いなもの
- 趣味
性別と関係性タイプについて ⭐ 重要
性別(gender):
"male": 男性キャラクター"female": 女性キャラクター"other": その他
関係性タイプ(relationship_type):
"romance": 恋愛対象キャラクター(告白イベント・恋人エンディングあり)"friendship": 恋愛対象外キャラクター(友達・ライバル・先生など)
重要: relationship_typeは性別ごとにオブジェクト形式で指定する必要があります。
恋愛対象プレイヤー性別(target_player_gender) ⭐ 重要:
- 恋愛対象キャラクター(
romance)の場合、必ず設定することを推奨 - プレイヤーの性別がこの設定に含まれている場合のみ選択可能
- BL・百合・異性愛・両対応など、あらゆる組み合わせに対応
設定例
1. 異性愛キャラクター(通常):
{
"gender": "female",
"relationship_type": {
"male": "romance",
"female": "friendship"
},
"target_player_gender": ["male"]
}
2. BL(男性×男性):
{
"gender": "male",
"relationship_type": {
"male": "romance",
"female": "friendship"
},
"target_player_gender": ["male"]
}
3. 百合(女性×女性):
{
"gender": "female",
"relationship_type": {
"male": "friendship",
"female": "romance"
},
"target_player_gender": ["female"]
}
4. 両対応キャラクター:
{
"gender": "female",
"relationship_type": {
"male": "romance",
"female": "romance"
},
"target_player_gender": ["male", "female"]
}
5. 恋愛対象外(友達):
{
"gender": "male",
"relationship_type": {
"male": "friendship",
"female": "friendship"
}
}
注意: target_player_genderを指定しない場合、全性別のプレイヤーで選択可能になります。
選択可否の例
| キャラクター | target_player_gender | プレイヤー(男性) | プレイヤー(女性) |
|---|---|---|---|
| さくら(異性愛) | ["male"] |
✅ 選択可 | ❌ 選択不可 |
| 武(乙女ゲー) | ["female"] |
❌ 選択不可 | ✅ 選択可 |
| 蓮(BL) | ["male"] |
✅ 選択可 | ❌ 選択不可 |
| あおい(百合) | ["female"] |
❌ 選択不可 | ✅ 選択可 |
| はるか(両対応) | ["male", "female"] |
✅ 選択可 | ✅ 選択可 |
| ゆうき(友達) | 設定不要 | ✅ 選択可 | ✅ 選択可 |
注意:
- この制限はゲーム開始時のキャラクター選択画面で適用されます
- MODのインストール自体は制限されません
target_player_genderを設定しない場合、すべてのプレイヤーで選択可能(後方互換性)
ストーリーを考える
- どんな出会い方をするか
- どんなイベントが発生するか
- どんなエンディングがあるか
ステップ2: 素材準備
立ち絵
立ち絵は季節・服装(制服/私服/その他)の組み合わせで表示できます。
最低限必要なもの:
- 通常表情(normal.png)- デフォルト立ち絵
推奨(基本表情):
- 嬉しい表情(happy.png)
- 悲しい表情(sad.png)
- 怒り表情(angry.png)
- 照れ表情(shy.png)
- 驚き表情(surprised.png)
季節別立ち絵:
- 季節ごとに異なる服装・表情を用意
- 例: 夏服、冬服など
詳細バリエーション:
- 服装(制服/私服)× 季節 の組み合わせ
- 例: 制服の夏服、dating関係での照れ顔など
- 未定義の組み合わせは自動的にフォールバック
イベント専用立ち絵:
- 特定のイベントでのみ使用する立ち絵
- 例: 浴衣、水着、ドレス、パジャマなど
- 未定義の組み合わせは自動的にフォールバック
サイズ: 1024x1536px 推奨
形式: PNG(透過対応)推奨
背景画像(任意)
背景にはシステム提供のデフォルト背景とMODで用意する特別な背景があります。
システムが提供する背景(用意不要):
- 教室、廊下、体育館、図書館、保健室など(学校関連)
- 公園、カフェ、駅前、商店街など(町関連)
- これらは季節に応じて自動的に変化します
MODで用意するもの(任意):
- イベント専用背景: 特別なシーン用
- 夏祭り会場
- 花火大会の背景
- 海辺の夕暮れ
- 水族館、遊園地など特別な場所
- 一枚絵(CG): 重要なシーン用
- 告白シーン
- キスシーン
- プロポーズ
- 結婚式など
サイズ: 1920x1080px(フルHD)推奨
重要: 通常の場所の背景はシステムが提供するため、MOD作成者は特別なシーン用の背景のみを用意すればOKです!
音声ファイル(任意)
- BGM
- 効果音
- ボイス
形式: MP3推奨
ステップ3: プロジェクト構造
フォルダを作成
最小構成
my_character_mod/
├── mod.json
├── portraits/
│ └── normal.png
└── events/
└── first_meeting.json
完全版(立ち絵バリエーション対応)
立ち絵のディレクトリ構造は 季節 → 服装 → 表情 です。服装は uniform(制服)や casual(私服)などです(関係性による stranger/friend/dating フォルダは廃止済みで使用しません)。
my_character_mod/
├── mod.json
├── portraits/
│ ├── spring/
│ │ ├── uniform/ # 制服
│ │ │ ├── normal.png
│ │ │ ├── happy.png
│ │ │ └── shy.png
│ │ └── casual/ # 私服
│ │ ├── normal.png
│ │ ├── happy.png
│ │ └── shy.png
│ ├── summer/ # 夏用(任意)
│ │ └── casual/
│ │ ├── normal.png
│ │ └── happy.png
│ └── event/ # イベント専用立ち絵(任意)
│ ├── yukata_normal.png # 浴衣
│ ├── yukata_happy.png
│ ├── swimsuit_normal.png # 水着
│ └── swimsuit_shy.png
├── backgrounds/ # イベント専用背景
│ ├── festival_entrance.png
│ ├── festival_fireworks.png
│ └── beach_sunset.png
├── cg/ # 一枚絵(CG)
│ ├── confession_scene.png
│ └── first_date.png
└── events/
├── first_meeting.json
└── summer_festival.json # 浴衣・背景を使用するイベント
ステップ4: mod.jsonを作成
バージョン互換性について ⭐重要
MODがどのゲームバージョンで動作するかを指定します。
バージョン形式
バージョンは major.minor.patch 形式(セマンティックバージョニング)で指定します:
- major: 大きな変更(例: 1.0.0 → 2.0.0)
- minor: 機能追加(例: 1.0.0 → 1.1.0)
- patch: バグ修正(例: 1.0.0 → 1.0.1)
フィールド
min_game_version(必須): このMODが動作する最低ゲームバージョンmax_game_version(必須): このMODが動作確認済みの最高ゲームバージョン
例:
{
"min_game_version": "0.1.0",
"max_game_version": "0.1.999"
// 0.1系(0.1.0 ~ 0.1.999)で動作確認済み
}
{
"min_game_version": "1.0.0",
"max_game_version": "1.2.0"
// 1.0.0 ~ 1.2.0 で動作確認済み
}
推奨設定:
- マイナーバージョンの最終版を指定(例:
0.1.999,1.0.999) - これにより、同じマイナーバージョン内のパッチアップデートで警告が出なくなります
- 新しいシステムバージョンがリリースされたら、テスト後に
max_game_versionを更新してください
警告について:
- システムバージョンが
max_game_versionを超える場合、MOD選択画面に「このシステムバージョンでは動作未確認」と表示されます - 警告が表示されても選択・使用は可能ですが、正常に動作しない可能性があります
最小構成の例
mod.json(メタデータのみ):
{
"mod_version": "1.0.0",
"mod_id": "my_character",
"mod_name": "私のキャラクター",
"mod_name_en": "My Character",
"author": "あなたの名前",
"description": "キャラクターの説明",
"description_en": "Character description",
"min_game_version": "0.1.0",
"season_preference": "all",
"supported_genders": ["male", "female"],
"character_file": "character.json",
"events_metadata_file": "events.json"
}
character.json(キャラクター定義):
{
"id": "my_char",
"family_name_ja": "田中",
"given_name_ja": "さくら",
"family_name_en": "Tanaka",
"given_name_en": "Sakura",
"gender": "female",
"age": 17,
"description_ja": "キャラクターの詳細説明",
"description_en": "Character description",
"personality_tags_ja": ["明るい"],
"personality_tags_en": ["Bright"],
"hobby_ja": ["読書"],
"hobby_en": ["Reading"],
"favorite_things_ja": ["本"],
"favorite_things_en": ["Books"],
"dislike_things_ja": ["運動"],
"dislike_things_en": ["Sports"],
"relationship_type": {
"male": "romance",
"female": "friendship"
},
"target_player_gender": ["male"],
"portraits": {
"spring": {
"uniform": {
"normal": "portraits/spring/uniform/normal.png"
}
}
},
"initial_stats": {
"male": {
"affection": 0,
"intimacy": 0,
"relationship": "acquaintance"
},
"female": {
"affection": 0,
"intimacy": 0,
"relationship": "acquaintance"
}
},
"stat_ranges": {
"affection": {"min": -100, "max": 100},
"intimacy": {"min": -100, "max": 100}
},
"unlock_conditions": {
"male": null,
"female": null
}
}
events.json(イベントリスト):
{
"events": [
{
"id": "first_meeting",
"title_ja": "初めての出会い",
"title_en": "First Meeting",
"description_ja": "さくらとの最初の出会い",
"description_en": "First encounter with Sakura",
"type": "story",
"default_bgm": "character_theme",
"required_conditions": {
"day": [{"operator": "==", "value": 1}]
},
"script_file": "events/first_meeting.json",
"once_only": true,
"priority": 100
}
],
"endings": [
{
"id": "ending_normal",
"title_ja": "いつもの日常",
"title_en": "As Usual",
"description_ja": "",
"description_en": "",
"type": "normal",
"required_conditions": {},
"script_file": "events/endings/ending_normal.json",
"priority": 0
}
]
}
endings(31日目用)について
endingsはevents.jsonに書きます(character.jsonではありません)。endingsが無い(または空)場合、NO_ENDINGS_DEFINED警告が出て、31日目のエンディング画面に表示されません。- まずは「常に発生するノーマルエンディング」1つから作るのがおすすめです。
- 詳細は events.json(イベント一覧) と エンディングの作り方 を参照してください。
default_bgmフィールド(任意):
- イベント開始時に自動的に再生されるBGMを指定できます
- BGM ID(
bgm_galleryから解決)または直接パス指定 - 未指定の場合は、前のBGM(場所のデフォルトBGMなど)が継続再生されます
- イベントスクリプト内で明示的にBGMを指定すると、それが優先されます
重要なポイント
- mod_id: 英数字とアンダースコアのみ、他のMODと被らないように
- character_file: キャラクター定義ファイル名を指定(
character.json) - events_metadata_file: イベントリストファイル名を指定(
events.json、任意) - relationship_type: 必須。性別ごとにオブジェクト形式で指定
- initial_stats: 必須。性別ごとにオブジェクト形式で指定
- unlock_conditions: 必須。性別ごとにオブジェクト形式で指定(条件なしの場合はnull)
- パス: 相対パスで指定(
../や/で始まるパスは禁止)
ステップ5: イベントスクリプトを作成
シンプルなイベントの例
{
"event_id": "first_meeting",
"scenes": [
{
"scene_id": "s01",
"type": "dialogue",
"text_ja": "ある日、不思議な女の子に出会った。",
"text_en": "One day, I met a mysterious girl."
},
{
"scene_id": "s02",
"type": "dialogue",
"character": "my_char",
"portrait": "normal",
"text_ja": "こんにちは!",
"text_en": "Hello!"
},
{
"scene_id": "s03",
"type": "dialogue",
"character": "player",
"text_ja": "こ、こんにちは...",
"text_en": "Hello...?"
},
{
"scene_id": "s04",
"type": "end"
}
]
}
ポイント:
typeフィールドは必須ですcharacterフィールドが無い場合 = ナレーション(話者名なしの文章)character: "player"= 主人公の独白(心の声)character: "キャラクターID"= キャラクターのセリフ
テキスト内の変数展開(プレースホルダー)
会話テキストや話者名では、プレイヤー名やゲーム状態変数を埋め込めます。
プレイヤー名の埋め込み
{
"scene_id": "s01",
"type": "dialogue",
"character": "my_char",
"text_ja": "おはよう、{{player.given_name}}!",
"text_en": "Good morning, {{player.given_name}}!"
}
ゲーム状態変数の埋め込み
{
"scene_id": "s02",
"type": "dialogue",
"character": "my_char",
"text_ja": "あのカフェには{{var.visited_cafe_count}}回行ったね!",
"text_en": "We've been to that cafe {{var.visited_cafe_count}} times!"
}
話者名の動的変更
{
"scene_id": "s03",
"type": "dialogue",
"character": "my_char",
"name_display": "{{var.current_relationship}}",
"text_ja": "今日も良い天気だね!",
"text_en": "Nice weather today!"
}
使えるプレースホルダー:
{{player.*}}: プレイヤー名(given_name,family_name,full_name,nicknameなど){{var.*}}: ゲーム状態変数(イベントで設定した変数を参照)
詳細は 変数とconditional を参照してください。
シーンの種類
1. キャラクターのセリフ
キャラクターのセリフを表示します。
基本形(推奨):
{
"scene_id": "s01",
"type": "dialogue",
"character": "my_char",
"portrait": "happy",
"text_ja": "こんにちは!元気?",
"text_en": "Hello! How are you?"
}
重要: character フィールドを指定すると、キャラクター定義ファイル(character.json)から自動的に多言語対応の名前が表示されます。
話者名の自動表示について:
characterのみ指定: キャラクターの姓名が自動表示(例: "広田 はるか" / "Haruka Hirota")name_displayで上書き: 特別な表示が必要な場合のみ使用(例: "???")
初対面シーン(名前を隠す場合):
{
"scene_id": "s02",
"type": "dialogue",
"character": "my_char",
"portrait": "normal",
"name_display": "???",
"text_ja": "あの、すみません...",
"text_en": "Um, excuse me..."
}
ポイント:
type: "dialogue"は必須です- 通常は
name_displayを省略してください(自動表示が便利です) name_displayは初対面シーンなどで名前を隠したい場合のみ使用- 多言語対応のため
text_jaとtext_enの両方を記述してください
2. 主人公の独白(心の声)
主人公の心の声(独白)を表示します。character: "player" を指定します(character 未指定のナレーションとは別扱いです)。
{
"scene_id": "s03",
"type": "dialogue",
"character": "player",
"text_ja": "(今日も良い天気だな...)",
"text_en": "(It's a beautiful day today...)"
}
ポイント:
type: "dialogue"は必須ですcharacter: "player"で主人公を明示的に指定します- プレイヤーの名前が話者名として自動表示されます
3. 選択肢
プレイヤーに選択肢を提示します。
{
"scene_id": "s04",
"type": "choice",
"text_ja": "どう答える?",
"text_en": "What should I say?",
"choices": [
{
"choice_id": "c01",
"text_ja": "元気だよ!",
"text_en": "I'm great!",
"stat_changes": {"affection": 5},
"next_scene": "s05"
},
{
"choice_id": "c02",
"text_ja": "まあまあかな",
"text_en": "Not bad",
"stat_changes": {"affection": 2},
"next_scene": "s06"
}
]
}
ポイント:
type: "choice"は必須です
4. 背景設定
背景を変更します。
{
"scene_id": "s07",
"type": "image",
"background": "school_classroom"
or
"cg": "sakura_afternoon_event"
}
ポイント:
type: "image"あるいはtype: "cg"は必須です
5. BGM設定
BGMを変更します。
{
"scene_id": "s07",
"type": "image",
"background": "school_classroom",
"bgm": "audio/bgm/daily.mp3"
}
ポイント:
bgmは character.json で定義されたBGMのIDか、ファイルのパスを指定します。
6. 終了
イベントを終了します。
{
"scene_id": "s99",
"type": "end"
}
7. 条件分岐
フラグやステータス、日数などの条件に基づいて、自動的に次のシーンを決定します。
{
"scene_id": "s10",
"type": "conditional",
"branches": [
{
"conditions": {
"stats": {
"affection": {"operator": ">=", "value": 50}
}
},
"next_scene": "s11_high"
},
{
"conditions": {
"required_flags": ["first_date"]
},
"next_scene": "s11_date"
}
],
"default_next_scene": "s11_normal"
}
ポイント:
branchesで複数の条件を定義- 上から順に評価され、最初に一致した条件の
next_sceneに遷移 - すべて不一致の場合は
default_next_sceneに遷移
8. ランダム分岐
指定した複数のシーンからランダムに1つを選択します。
{
"scene_id": "s12",
"type": "random",
"next_scenes": ["s13_a", "s13_b", "s13_c"]
}
ポイント:
- 会話のバリエーションを増やすのに便利
- 最低2つのシーンを指定
9. 立ち絵表示
キャラクターの立ち絵を画面に表示します。
{
"scene_id": "s14",
"type": "character_show",
"character": "my_char",
"portrait": "uniform.happy",
"position": "center"
}
ポイント:
portraitはドット記法("服装.表情")で指定positionは "left", "center", "right" のいずれか- 複数キャラクター登場シーンに便利
表示効果の指定:
{
"scene_id": "s15",
"type": "character_show",
"character": "my_char",
"portrait": "casual.smile",
"position": "right",
"effects": {
"scale": 1.2,
"opacity": 1.0,
"offset_x": 50.0,
"offset_y": -30.0
}
}
effectsで指定できるキー(現行実装):
scale(倍率)opacity(透明度)brightness(明度)offset_x,offset_y(位置オフセット)color(カラーフィルターの色、カラーコード)color_intensity(カラーフィルターの強度、0.0~1.0)color_brightness(カラーフィルター時の明度、0.0~2.0)
カラーフィルターの使用例:
{
"scene_id": "sunset_scene",
"type": "dialogue",
"character": "haruka_hirota",
"portrait": "happy",
"position": "center",
"effects": {
"scale": 1.2,
"color": "#FF8844",
"color_intensity": 0.3,
"color_brightness": 0.95
},
"text_ja": "夕焼けがきれいだね..."
}
カラーフィルターの注意点:
colorを使う場合はcolor_intensityも必ず指定してくださいcolor_brightnessは省略可能(デフォルト: 1.0)- イベントでカラーフィルターを指定すると、時間帯による自動カラーフィルターは適用されません
10. 立ち絵非表示
キャラクターの立ち絵を非表示にします。
{
"scene_id": "s16",
"type": "character_hide",
"character": "my_char"
}
全キャラクター非表示:
{
"scene_id": "s17",
"type": "character_hide"
}
ポイント:
characterを省略すると全キャラクター非表示
11. 時間進行
イベント内で時間を進めます。デートイベントなどで便利です。
{
"scene_id": "s18",
"type": "time_advance",
"advance_to_time": "evening"
}
ポイント:
advance_to_timeで到達する時間帯を指定- 有効な値: "earlyMorning", "morning", "afternoon", "evening", "night", "dayEnd"
- 「朝から夜まで時間が経過した」といった演出が可能
使用例:
{
"scene_id": "s19",
"type": "dialogue",
"character": "my_char",
"portrait": "casual.happy",
"text_ja": "じゃあ、カフェに行こう!",
"text_en": "Let's go to the cafe!"
},
{
"scene_id": "s20",
"type": "time_advance",
"advance_to_time": "evening"
},
{
"scene_id": "s21",
"type": "dialogue",
"character": "my_char",
"portrait": "casual.surprised",
"text_ja": "もうこんな時間!楽しかったね。",
"text_en": "It's already this late! That was fun."
}
12. 場所移動
イベント内で場所を移動します。場所のデフォルト背景・BGMが自動適用されます。
{
"scene_id": "s22",
"type": "location_change",
"location": "cafe"
}
ポイント:
locationで移動先の場所IDを指定- 背景とBGMが自動的に適用される
- デートイベントで複数の場所を巡る際に便利
使用例:
{
"scene_id": "s23",
"type": "dialogue",
"text_ja": "(カフェに向かおう)",
"text_en": "(Let's head to the cafe)"
},
{
"scene_id": "s24",
"type": "location_change",
"location": "cafe"
},
{
"scene_id": "s25",
"type": "dialogue",
"character": "my_char",
"portrait": "casual.happy",
"text_ja": "わぁ、素敵なカフェ!",
"text_en": "Wow, what a nice cafe!"
}
ステップ6: イベント発生条件
基本的な条件
"required_conditions": {
"day": [{"operator": ">=", "value": 7}],
"time": ["morning", "afternoon"],
"stats": {
"affection": {"operator": ">=", "value": 20}
}
}
条件の種類
| 条件 | 説明 | 例 |
|---|---|---|
| day | 日数 | [{"operator": ">=", "value": 7}] |
| time | 時間帯 | ["morning", "afternoon"] |
| locations | 場所 | ["school_classroom", "cafe"] |
| stats | ステータス | {"affection": {"operator": ">=", "value": 20}} |
| required_flags | 必須フラグ | ["flag1", "flag2"] |
| forbidden_flags | 禁止フラグ | ["bad_flag"] |
ステップ7: ステータス変更
基本的な使い方
{
"scene_id": "s01",
"type": "dialogue",
"character": "my_char",
"portrait": "happy",
"text": "ありがとう!",
"stat_changes": {
"affection": 5,
"intimacy": 5
}
}
ポイント
- 正の値で増加、負の値で減少
- 範囲は
stat_rangesで定義した範囲内に自動調整されます
ステップ8: フラグの使用
フラグとは
特定のイベントが発生したかどうかを記録する仕組みです。
フラグを設定
{
"scene_id": "s01",
"type": "dialogue",
"character": "my_char",
"portrait": "normal",
"text": "私、田中さくらって言います!",
"flags_set": ["name_revealed"]
}
フラグで条件分岐
"required_conditions": {
"required_flags": ["name_revealed"]
}
これで「name_revealed」フラグが設定されている場合のみイベントが発生します。
ステップ9: テスト
ゲーム内でテスト
- MODフォルダを
mods/ディレクトリに配置 - ゲームを起動
- MODが読み込まれるか確認
- イベントが正しく動作するか確認
チェックリスト
- ☐ MODが正しく読み込まれる
- ☐ キャラクターが表示される
- ☐ イベントが発生する
- ☐ 選択肢が動作する
- ☐ ステータスが変化する
- ☐ エラーが発生しない
ステップ10: パッケージング
ZIPファイルの作成
- MODフォルダ全体をZIPに圧縮
- ファイル名を
{mod_id}_v{version}.zipにする - 例:
my_character_v1.0.0.zip
配布
- Steam Workshop(PC版)
- 公式MODサイト
- GitHub
- 個人サイト
トラブルシューティング
MODが読み込まれない
原因:
- mod.jsonの形式が間違っている
- 必須フィールドが欠けている
- ファイルパスが間違っている
対処:
- JSONバリデーターで構文チェック
- ゲームログを確認
イベントが発生しない
原因:
- 発生条件を満たしていない
- script_fileのパスが間違っている
- once_only=trueで既に実行済み
対処:
- 条件を確認
- パスを確認
- セーブデータをリセット
画像が表示されない
原因:
- ファイルパスが間違っている
- ファイル名の大文字小文字が違う
- ファイルが存在しない
対処:
- パスを確認(大文字小文字も含めて)
- ファイルの存在を確認
ベストプラクティス
1. 命名規則
- mod_id:
author_charactername(例:tanaka_sakura) - scene_id:
scene_001,scene_002... - choice_id:
choice_001,choice_002...
2. コメント
JSONにはコメントが書けないので、README.mdに詳細を記載。
3. テスト
- 各選択肢をテスト
- エンディング到達まで確認
- 複数のプレイパターンをテスト
4. ドキュメント
README.mdに以下を記載:
- キャラクター紹介
- イベント一覧
- エンディング条件
- ライセンス情報
バリデーションエラーを避けるベストプラクティス
MODを作成する際、バリデーションエラーを避けるための重要なポイントをまとめました。
必須項目チェックリスト
✅ 1. 必須立ち絵を作成
最も重要: spring.casual.normal立ち絵は必須です。
portraits/
└── spring/
└── casual/
└── normal.png ← これが必須!
エラー回避:
- この立ち絵がないと
MISSING_NORMAL_PORTRAITエラーになりMODが選択不可になります - 他の立ち絵がなくても、これ1枚あればMODは動作します
- フォールバック機能により、他の表情・服装・季節が未定義でも自動的にこの立ち絵が使用されます
✅ 2. バージョンを必ず指定
mod.jsonに必須:
{
"min_game_version": "0.1.0", // 必須
"max_game_version": "0.1.999" // 必須
}
エラー回避:
min_game_versionが未指定または空の場合、INVALID_MIN_VERSIONエラーmax_game_versionが空の場合、MISSING_MAX_VERSIONエラー- セマンティックバージョニング形式(
X.Y.Z)でなければエラー
推奨設定:
min_game_version: 現在のゲームバージョン(例:0.1.0)max_game_version: マイナーバージョンの最大値(例:0.1.999)
✅ 3. イベントIDを一致させる
events.jsonとスクリプトのIDを必ず一致させる:
// events.json
{
"id": "first_meeting", // ← この値
"script_file": "events/first_meeting.json"
}
// events/first_meeting.json
{
"event_id": "first_meeting", // ← この値を一致させる
"scenes": [...]
}
エラー回避:
- IDが一致しないと
EVENT_ID_MISMATCHエラー - コピー&ペーストする際は、必ずIDも変更する
✅ 4. エンディングを最低1つ定義
events.jsonに必須(推奨):
{
"endings": [
{
"id": "ending_normal",
"title_ja": "いつもの日常",
"title_en": "As Usual",
"description_ja": "",
"description_en": "",
"type": "normal",
"required_conditions": {},
"script_file": "events/endings/ending_normal.json",
"priority": 0
}
],
"events": []
}
警告回避:
- エンディングがないと
NO_ENDINGS_DEFINED警告が表示されます - エンディングがないキャラクターは31日目のエンディング画面に表示されません
✅ 5. MODサイズを200MB以下に抑える
制限:
- MOD全体(全ファイル合計): 200MB以下
- 個別ファイル制限:
- 画像1ファイル: 5MB以下推奨
- 音声1ファイル: 10MB以下推奨
エラー回避:
- MODサイズが200MBを超えると
MOD_SIZE_EXCEEDEDエラー - 画像最適化ツール(TinyPNG、OptiPNG)を使用してファイルサイズを削減
バリデーション成功のための10のルール
- 必須立ち絵を最初に作成:
spring.casual.normal.png - バージョンを明確に指定:
min_game_versionとmax_game_version - IDを一貫させる:
events.jsonとスクリプト内のevent_id - シーンIDを一意にする: 重複しないシーンID
- 参照を確認する:
next_sceneの参照先が存在するか - エンディングを定義する: 最低1つのエンディング
- ドット記法を使用: 立ち絵パスは
clothing.emotion - ファイルサイズを管理: MOD全体で200MB以下
- JSON構文を確認: 括弧、カンマ、引用符の対応
- テストを実行: 実際にゲーム内で動作確認
参考資料
初心者向けガイド
- アセット作成ガイド
- JSON作成の基本
- バリデーションガイド - エラーを避けるためのガイド
詳細解説(リファレンス)
- mod.jsonについて
- character.jsonについて
- events.json(イベント一覧)
- イベント発生条件(required_conditions)
- イベントスクリプトについて
- エンディングの作り方
- 立ち絵について
- 一枚絵(CG)・背景
- フラグ管理について
- 変数とconditional
- 特殊イベントの書き方
- 音声(BGM/SE/Voice)
- 検証コード一覧
質問・サポート
- GitHub Issues
- 公式フォーラム
- Discord
まとめ
これで基本的なMODが作成できます!まずはシンプルなキャラクターから始めて、徐々に複雑なイベントやエンディング、そして季節対応を追加していきましょう。
Happy Modding! 🎮💕