セーブロード構築の第二段階、専用UIを組み込んでいきます。
今回の作業目標
- オートセーブをslot0固定にする設計
slot0 = オートセーブ専用 という意図だと思いますが、
問題: SaveSlot UIで「slot0」がオートセーブと手動セーブで衝突しないか?
確認: slot0はオートセーブ専用として手動セーブから除外しますか?それとも手動でも使えますか?
- 1ページ3スロットのページ方式
3スロットしかないなら「ページ方式」は不要なUI複雑化
9〜12スロットなら妥当
30スロットなら別のスクロール方式の方がUXが良い場合も
大胆な代替案:
ページ方式よりもスクロール方式+オートセーブ固定表示(最上部)の方がシンプルで操作しやすいケースが多い
- ローディング画面のタイミング
ロード時の「一瞬映り込み」をローディング画面で解決予定
原因によって解決策が変わります。
ローディング画面は「隠す」対処療法なので、根本原因を把握してから実装順序を決める方が良い。
ロード時の「一瞬映り込み」を解決
原因と対策
症状:「どのCutでセーブしても、ロード時にCut001が一瞬映り込む」状態。
原因:スタートCutだったため、常にアクティブにしている。
解決策:エディタ上でCut_001〜全CutをInactiveにして保存するだけ。(コード不要)
StartCut() が呼ばれたとき正しいCutだけActiveになるので、映り込みはなくなります。
症状:しかし「初回ロード時のみ読み込みが一瞬あって、ちらつく」状態は起こる。
原因:テクスチャ・スプライトは初回描画時にGPUへ転送される。
これはUnityの遅延ロード(Lazy Loading)の仕様です。セーブシステムの問題ではありません。
解決策:A. 暗幕(対処療法)映り込みを隠すだけ。根本は解決しない。
ロード開始 → 黒フェード → シーン復元完了 → フェードイン
解決策:B. テクスチャプリロード(根本解決)
シーン開始時に全テクスチャを一度描画してキャッシュ → ロード時は既にキャッシュ済み → 遅延なし
具体的にはResources.Loadや画面外での事前レンダリング。
🔍 「暗幕の表示時間問題」の本質
あなたが抱えている問題は、映り込みが消えるまで待つ必要があるが
その時間が環境によって変わる → 固定時間では対応できない
これは時間で解決するのではなく、完了を検知して解除するべき問題です。
A. 固定フレーム待機
yield return new WaitForSeconds(0.5f); // 暗幕中に数フレーム待つ。
シンプル。でも低スペックでは不十分な可能性あり。
B. ダミーレンダリング後に解除
暗幕中に画面外でCutの素材を一度レンダリング → キャッシュ済みになってから暗幕OFF
根本解決に近いが実装複雑。
C. ローディングアニメーション+最低表示時間
最低0.5秒は表示(短すぎるチラつき防止)+ セットアップ完了を待つ → どちらか長い方が終わったら解除
現実的なバランス案。
正直な推奨:Cが最もコスパが良いです。
ローディング画面はUX的にも「処理中である」ことをユーザーに伝えられるので、待ち時間への不満が減ります。
ただし本当にそれでいいですか?
今の映り込みは「初回だけ」「一瞬」という話でした。
そこにローディング画面という、そこそこ重い実装を入れるのは過剰対応になる可能性があります。
結論:まずは暗幕隠しで様子見。表示時間やフェード時間を調整できるように。
ロード専用暗幕
Sceneで共有するために、暗幕のCanvasはDontDestroyOnLoadにします。
■ 設計案
Sys_FadeManager.cs
├ FadeOut() // パッと暗幕ON
├ FadeIn(duration) // DOTweenでフェードアウト(暗幕消える)
└ displayTime // 暗幕の最低表示時間(Inspectorで調整可能)
ロード時の流れ:
SaveManager.LoadGame()
→ FadeManager.FadeOut() // パッと暗幕ON
→ yield return new WaitForSeconds(displayTime)
→ シーンロード・復元処理
→ FadeManager.FadeIn() // DOTweenでじわっと消える
■ スクリプト役割
Sys_FadeManager.cs(新規):暗幕ImageのON/OFF・フェード処理の実体
Sys_SaveManager.cs:ロード処理の司令塔。暗幕が必要な時にFadeManagerを呼ぶ
■ DontDestroyOnLoad暗幕の作り方

- 新規空オブジェクトを作成
名前:Black_Canvas
- Black_CanvasにCanvasコンポーネントを追加
RenderMode → Screen Space – Overlay
SortingOrder → 999(他のUIより最前面)
- Black_Canvasの子に黒いImageを作成
名前:Black_Screen
Color → 黒・Alpha255
RectTransform → Stretch(全画面)
初期状態 → アクティブのまま・Alpha0にしておく
- Black_CanvasをHierarchyのルートに置く
SaveManagerと同じ扱いであり、子にしてしまうとエラーが起きる。
■ ImageをStretch(全画面)にする方法


ゲーム画面サイズに自動で伸びます。
Left「0」Top「0」Right「0」Bottom「0」になっていれば成功です。
■ 暗幕以外(任意のテキストや画像)もいっしょに表示させる設定

Black_Canvas ← ルートに置く
├ Black_Screen ← 暗幕Image
└ (将来追加するテキストやスプライトはここに)
コンポーネント一覧:Black_Canvas
├ Canvas
│ ├ Render Mode → Screen Space – Overlay
│ └ Sort Order → 999
├ CanvasScaler(自動追加されているはず)
├ GraphicRaycaster(自動追加されているはず)
├ CanvasGroup ← 手動で追加
│ ├ Alpha → 0
│ ├ Interactable → チェックOFF
│ └ Blocks Raycasts → チェックOFF
└ Sys_FadeManager.cs ← アタッチ
├ Canvas Group → Black_Canvas自身のCanvasGroupをアサイン
├ Display Time → 0.5
├ Fade In Duration → 0.5
└ Fade In Ease → InOutQuad
Black_Canvas → アクティブのまま
Black_Screen → アクティブのまま
Black_Canvas
├ Black_Screen
└ LoadingText ← 追加するだけでOK
└ アクティブ状態で置いておく
暗幕まとめ
・ローディング画面より先に根本原因を探った
・暗幕をCanvasGroup一本に統一してシンプルにした
・将来の拡張を考えた構造にした
✅ 暗幕システム(Sys_FadeManager.cs)完成
├ CanvasGroup一括制御
├ FadeOut():パッとON
├ FadeIn():DOTweenでじわっとOFF
├ Ease・時間はInspectorで調整可能
└ 子オブジェクトを追加するだけで拡張可能
✅ ロード時チラつき問題解決
├ Cut_001をエディタ上でInactive化
└ ロード時に暗幕で保護
セーブロード画面のUI設計
スロットの目標挙動と構造
【セーブ画面】
空スロット → クリックでセーブ
既存スロット → クリックで上書き確認ダイアログ → はいで上書き
Deleteボタン → クリックで削除確認ダイアログ → はいで削除
【ロード画面】
空スロット → クリックで反応なし
既存スロット → クリックでロード開始
Deleteボタン → クリックで削除確認ダイアログ → はいで削除
【ダイアログ】
A. 見た目は共通・メッセージだけ変える
「上書きしますか?」
「削除しますか?」
→ 1つのダイアログのテキストを差し替えて使い回す
B. ダイアログ自体を複数用意・見た目も別々
→ 上書き用・削除用・その他用を個別に作る
→ 将来デザインを個別に変えられる
A. SaveLoad_Canvasの子に置く
→ セーブロード画面を開いている時だけ使える
→ シンプル
B. 独立したCanvasとして別に置く
→ どこからでも呼び出せる
→ 将来他の場面でも使い回せる
■ 全体UI構造
SaveLoad_Canvas ← DontDestroyOnLoad
├ Header
│ └ TitleText(「セーブ」or「ロード」で切り替え)
├ SlotArea
│ ├ Slot_01
│ │ ├ ScreenshotImage
│ │ ├ SaveTimeText
│ │ └ DeleteButton
│ ├ Slot_02
│ └ Slot_03
├ PageArea(将来用・今は非表示)
│ ├ PrevButton
│ └ NextButton
└ CloseButton
Dialog_Canvas ← DontDestroyOnLoad・独立
├ MessageText
├ YesButton
└ NoButton
■ 作成スクリプト

・Sys_DialogManager.cs:ダイアログ表示用
・UI_SaveLoadPanel.cs:セーブロード画面表示用
・UI_SaveSlot.cs:スロット用
ダイアログ作成

■ Dialog_Canvas のHierarchy構造
Dialog_Canvas
└ Panel
├ MessageText
├ YesButton
│ └ Text
└ NoButton
└ Text
■ コンポーネント設定
Canvas
├ Render Mode → Screen Space – Overlay
└ Sort Order → 200(SaveLoad_Canvasより前面)
Sys_DialogManager.cs をアタッチ
├ Dialog Panel → Panelをアサイン
├ Message Text → MessageTextをアサイン
├ Yes Button → YesButtonをアサイン
└ No Button → NoButtonをアサイン
Dialog_Canvas → アクティブ
└ Panel → 非アクティブ
CanvasはアクティブのままでPanelだけ非アクティブにするのがポイントです。
スクリプトがAwakeで動作するために必要です。
とりあえず提案してくれる感じ好き(*´ω`*)

UIオブジェクト作成

■ SaveLoad_Canvas のHierarchy構造
SaveLoad_Canvas
└ Panel
├ TitleText
├ SlotArea
│ ├ Slot_01
│ │ ├ ScreenshotImage
│ │ ├ SaveTimeText
│ │ ├ PreviewText
│ │ ├ EmptyText
│ │ └ DeleteButton
│ │ └ Text
│ ├ Slot_02(同上)
│ └ Slot_03(同上)
└ CloseButton
└ Text
■ コンポーネント設定
Canvas
├ Render Mode → Screen Space – Overlay
└ Sort Order → 100
UI_SaveLoadPanel.cs をアタッチ
├ Panel → Panelをアサイン
├ Title Text → TitleTextをアサイン
├ Slots → Size 3
│ ├ Element0 → Slot_01をアサイン
│ ├ Element1 → Slot_02をアサイン
│ └ Element2 → Slot_03をアサイン
└ Close Button → CloseButtonをアサイン
Slot_01〜03それぞれに
UI_SaveSlot.cs をアタッチ
├ Screenshot Image → ScreenshotImageをアサイン
├ Save Time Text → SaveTimeTextをアサイン
├ Preview Text → PreviewTextをアサイン
├ Empty Text → EmptyTextをアサイン
├ Slot Button → Slot自身のButtonをアサイン
└ Delete Button → DeleteButtonをアサイン
Slotプレハブ化の手順
① Slot_01の設定が完成した状態で
② HierarchyのSlot_01をProjectウィンドウのPrefabsフォルダにドラッグ
③ 「Slot」という名前でプレハブとして保存
④ Slot_02・Slot_03を削除
⑤ プレハブをHierarchyにドラッグしてSlot_02・Slot_03として配置
ページ追加時
→ プレハブを複製して並べるだけ
→ スクリプトでSlotを動的生成することも可能
SaveLoad_Canvas → アクティブ
└ Panel → 非アクティブ
CanvasはアクティブのままでPanelだけ非アクティブにするのがポイントです。
スクリプトがAwakeで動作するために必要です。

挙動テスト
① UI_SaveLoadButtonsのセーブボタンを押す
→ SaveLoad_Canvasが開く
→ タイトルが「セーブ」になっている
→ 空スロットに「Empty」が表示されている
② 空スロットをクリック
→ セーブされてパネルが閉じる
③ 再度セーブ画面を開く
→ スクリーンショット・日時・セリフが表示されている
④ 既存スロットをクリック
→ 「上書きしますか?」ダイアログが出る
→ はい → 上書きされてパネルが閉じる
→ いいえ → ダイアログが閉じるだけ
⑤ Deleteボタンをクリック
→ 「削除しますか?」ダイアログが出る
→ はい → スロットがEmptyに戻る
⑥ ロードボタンを押す
→ タイトルが「ロード」になっている
→ 既存スロットをクリックでロード開始
→ 暗幕が出てロードされる
表示・挙動の調整
操作調整
・セーブ画面表示中、「閉じる」ボタン以外(右クリック)でも閉じるように。
・セーブスロットを押したら即閉じではなく、画面は開いたままに。
・画面表示中に一回何かの操作をしたら、保存はされるが、スロットに情報が表示されなくなる挙動の修正。
記録年月日の「時間」を削除
Sys_SaveManager.cs 内記述
// 変更前
data.saveTime = DateTime.Now.ToString(“yyyy/MM/dd HH:mm“);
// 変更後
data.saveTime = DateTime.Now.ToString(“yyyy/MM/dd“);
個人的には情報過多表示は好み。
しかし、秒単位まで、いつプレイしたかバレる情報は、無いほうが世の中のためになると判断(^ω^)
「章」のテキスト保存追加

■ Hierarchyに追加するもの
System_set(もしくはルート)
└ ChapterManager ← 新規作成
└ Sys_ChapterManager.cs をアタッチ
├ Chapter Text → 「第1章」
└ Part Text → 「プロローグ」
■ Slot_00プレハブに追加するもの
Slot_00
├ ChapterText ← TextMeshProUGUIで新規作成
└ PartText ← TextMeshProUGUIで新規作成

Chapter Text → ChapterTextをアサイン
Part Text → PartTextをアサイン
二段になる長いセリフを省略化する

TextMeshProの設定のみで対応可能。


オートセーブの実装
■ オートセーブの負荷の本質
JSON書き込み → ほぼ0負荷・一瞬で終わる
SceneManager → オートセーブでは不要
スクリーンショット → 画面全体をキャプチャするため負荷あり
■ 確認
① オートセーブにスクリーンショットは必要か。No
② オートセーブのタイミングはCut単位でよいか。 (NextCut()が呼ばれるたびに自動保存)Yes
③ オートセーブはslot0固定で確定か。Yes
■ Hierarchyに追加するもの
SaveLoad_Canvas
└ Panel
└ SlotArea
├ Slot_Auto ← 新規作成(プレハブ化不要)
│ ├ SaveTimeText
│ ├ PreviewText
│ ├ ChapterText
│ └ PartText
│ ※ DeleteButtonは作らない
├ Slot_01(プレハブ)
└ Slot_02(プレハブ)

■ Inspectorでの設定
UI_SaveLoadPanel.cs
├ Auto Slot → Slot_Autoをアサイン
├ Slots → Size 2
│ ├ Element0 → Slot_01をアサイン
│ └ Element1 → Slot_02をアサイン
└ Close Button → CloseButtonをアサイン
■ セーブ画面の方で、オートセーブ押せちゃう問題
解決:セーブ画面時にボタンを非活性化する。(slotButton.interactable = false)
→ ボタンがグレーアウトして押せなくなる。
→ 見た目でも「押せない」とわかる。

セーブロードの実機挙動
想定していたセーブシステムの挙動がうまく実装されたと思います。
セーブのためでもあったCut進行構築をより理解する機会にもなりました。
1Cutに対して、そのCutでの表示情報をすべて(リアルタイムで過ぎ去った情報も改めて)与えておかないといけません。
被る情報(立ち絵の位置や消したオブジェクト)も記しておく必要があるので、構築の手間になる部分です。
(そもそもそういうことを理解していないでCut方式にしていた節もあります)
ここらへんの整理も課題として出てきたので、将来の自分に丸投げしておきましょう。
とにかく、一番の懸念点であった「セーブ・ロード」が実装できたのは大きな進捗です。
改善点や問題点は、若干まだありますが、素直に喜んでおくとします(*´ω`*)
保存データが決まり、テキスト設定や音量設定の保存に対しての答えを示せるので、
次はコンフィグ周りを作っていけそうです。
システム第二段階まとめ
✅ 暗幕システム(Sys_FadeManager.cs)
├ CanvasGroup一括制御
├ FadeOut():パッとON
├ FadeIn():DOTweenでじわっとOFF
└ Ease・時間はInspectorで調整可能
✅ SaveSlot UI
├ Slot_Auto(slot0・オートセーブ専用)
│ ├ セーブ画面では非活性化
│ ├ スクリーンショットなし
│ └ Deleteボタンなし
├ Slot_01・Slot_02(手動セーブ用プレハブ)
│ ├ スクリーンショット表示
│ ├ 日付表示(時分なし)
│ ├ セリフプレビュー(…省略あり)
│ ├ 章・パート表示
│ ├ 上書き確認ダイアログ
│ └ 削除確認ダイアログ
└ 右クリックで閉じる
✅ 共通ダイアログ(Sys_DialogManager.cs)
└ Show(message, onYes)で呼び出し
✅ 章テキスト・パートテキスト管理(Sys_ChapterManager.cs)
└ Inspectorで任意テキストを設定
✅ オートセーブ
├ slot0固定
├ スクリーンショットなし
└ Cut冒頭・最初のセリフ表示時に実行

コメント