設定画面UIの実装【Unity6】

絶対調味ロジック

今回のコンセプトがビデオUIなので、中身の設定もそれっぽくしてみました。
ドット絵では賛否分かれる「ぼかし」も少しエフェクトしてみました。
パッキリとしているよりもビデオ感は強くなったと思います。

ボタンのビジュアル効果

概要

メニュー画面の各ボタン専用スクリプトに次いで、
ボタンのビジュアル効果だけを独立させた新規スクリプト「UI_ButtonVisual」を作成しました。

設定できるボタン表現は、「ノーマル」「ホバー」「プレス」の3状態にしました。
プレス時のアニメーションバージョンは削除しました。
前と同じように、他画像と連動できるように複数指定で増減可能にしています。

後々必要になり「セレクト」「無効」「トグル」も追加することになります。

基本方針

  • IPointerEnterHandler 系インターフェースで状態検知
  • Buttonの Transition = None を前提(Inspectorで手動設定、Editorのみ警告で検知)
  • OnDisable で必ずNormalにリセット(SetActiveベースのパネル開閉に対応)

Mode構成

Mode用途
Normal通常。Hover/Pressはポインターフラグで制御
Selectedタブ・排他選択ボタンの選択中状態
Disabledinteractable=false時の非活性状態
ToggleON/OFFそれぞれにNormal/Hover/Pressを持つ

Targetフィールド構成(1Targetあたり)

  • 通常:normal / hover / press
  • Selected:selected
  • Disabled:disabled
  • Toggle OFF:toggleOffNormal / toggleOffHover / toggleOffPress
  • Toggle ON:toggleOnNormal / toggleOnHover / toggleOnPress

外部呼び出しAPI

SetNormal();
SetSelected();
SetDisabled();
SetToggle(bool isOn);

共通パターン

// Awakeでキャッシュ
private UI_ButtonVisual visualXxx;
visualXxx = btnXxx?.GetComponent<UI_ButtonVisual>();

// RefreshAll/UpdateXxx内で呼び出し
visualXxx?.SetSelected();
visualXxx?.SetNormal();
visualXxx?.SetDisabled();
visualXxx?.SetToggle(bool);

メニュー画面

新規スクリプト「UI_ButtonVisual」を各ボタンにアタッチし、それぞれの画像を指定して出来上がりです。

画像の「ぼかし」効果を狙い、設定や画像圧縮を変更しました。

ぼかし」をするために画像圧縮をしているので、サイズも減って一石二鳥効果です。

仕上げに、少し粗い「走査線」もつけて完成です。
やはり「ぼかし」が入ると、画面越し表現に近づきますね。

使用フォントについての設定も「フォントの個別設定(ぼかしやシャープなど)」で詳しく解説しています。

システム設定

UI_SystemSettingsPanel

  • ウィンドウモード(Windowed/Fullscreen)→ Selected
  • 解像度3種 → Selected、フルスクリーン時は Disabled
  • リセットボタン → フルスクリーン時 Disabled

システム設定」「音量設定」「テキスト設定」には専用の「タブボタン」を採用しているので、
Sys_ConfigTabController」を対応するように改修しました。

  • spriteOn/Off・colorOn/Off フィールド削除
  • RefreshTabStates() のビジュアル処理を SetSelected() / SetNormal() に置き換え

そして、ここのシステム画面で「セレクト状態」と「トグル状態」も必要となったため、
UI_ButtonVisual」自体にも機能を追加しています。

音量設定

UI_AudioSettingsPanel

  • ミュートボタン4種 → Toggle(ON=ミュート中)
  • Masterミュート時に子チャンネルボタン → Disabled
  • muteOnColor / muteOffColor フィールド削除

テキスト設定

UI_TextSettingsPanel

  • スキップモード(SkipAll/SkipRead)→ Selected(排他)
  • ルビ設定 → 当初Selected2ボタン構成からToggle1ボタンに変更、btnRubyOff 削除

バックログ

バックログ画面にも「閉じるボタン」を設置できるようにし、
記述設定だった名前・セリフの「」と「サイズ」をインスペクターで調整できるように改善しました。

ダイアログ画面

背景に砂嵐アニメを配置してみました。
アニメーションは専用スクリプトで動かしています。

セーブロード画面

UI_SaveLoadPanel

  • titleText(TextMeshPro)と titleImage(Image)を追加
  • titleText はセーブ/ロードモードに応じてコードで自動切替
  • titleImage はInspectorでアサインするだけ、コード側から操作しない
  • どちらも未アサインでもエラーなし

いつからかできていると錯覚していた「メイン画面だけのスクリーンショット
どうやら「スロット」を複数にした時点ですでにできておらず、
いままでずっとセーブ画面のスクリーンショットが表示されていたようでした。

いろいろと工夫してもらったのだけれど、撮影タイミングがうまくいかず、
結果的に「メニュー画面を開く直前に撮影しておき、セーブ時にあてがう」という方法で落ち着きました。

■ 原因
Sys_ScreenshotManager.CaptureScreenshot() は WaitForEndOfFrame で1フレーム待って撮影するだけで、
撮影タイミングでセーブパネルが表示されたままだった。

■ 試みた解決策と結果
CanvasGroupで透明化 → SetActive よりマシだがチカつきが発生。
根本解決にならず。

■ 最終解決策:撮影タイミングをセーブ時から切り離す
メニュー画面を開く直前(ゲーム画面が完全に表示されている状態)に撮影してメモリにキャッシュ。
セーブ時はキャッシュ済み画像をファイルに書き出すだけ。

変更スクリプト

Sys_ScreenshotManager

  • CaptureAndCache() 追加:撮影してメモリに保持
  • SaveCachedScreenshot(path) 追加:キャッシュをファイル書き出し
  • ClearCache() 追加:キャッシュ破棄
  • 旧 CaptureScreenshot() はAutoSave等のために残置

Sys_SaveManager

  • SaveRoutine() からスクリーンショット撮影処理を削除
  • 代わりに SaveCachedScreenshot() を呼ぶだけに変更

UI_Manager

  • メニューを開く処理を CaptureAndOpenMenu() コルーチンに変更
  • メニュー開封直前に CaptureAndCache() を実行してからパネルを開く

UI_MenuPanel

  • btnSave のリスナーは通常の SavePanel?.Open() に戻す
  • CaptureAndOpenSave() コルーチンは削除

注意点
・セーブ画面を開く経路が増えた場合、その箇所でも CaptureAndCache() を呼ぶ必要がある。
・AutoSaveはゲーム画面で実行されるため従来の CaptureScreenshot() のままで問題なし

キャッシュのメモリサイズ(解像度に依存)

解像度非圧縮テクスチャサイズ(RGBA32)
1280×720約3.5MB
1600×900約5.5MB
1920×1080約8MB

常に1枚だけ保持(上書き)なので、最大でも8MB程度です。
ロースペックPCでも問題ないレベルです。

処理負荷
CaptureScreenshotAsTexture() は WaitForEndOfFrame 後に1フレームだけ処理が走ります。
メニューを開くたびに1回だけなので、頻度としても問題ありません。

キャッシュクリア
UI_MenuPanel
タイトル遷移時に ClearCache() を呼び、キャッシュが確実に破棄されるようにしました
Sys_ScreenshotManager
シーン遷移時に OnDestroy で ClearCache() が呼ばれ、
タイトル遷移時は Co_ReturnTitle() で明示的に呼ばれます。二重に保護されています。

UI_SaveSlot(追加内容)

  • Awake で slotButton と deleteButton の UI_ButtonVisual をキャッシュ
  • Setup() 内でスロットボタンの状態に応じて SetDisabled() / SetNormal() を呼び出し
  • オートスロットのセーブ時のみ SetDisabled()、それ以外は SetNormal()
  • デリートボタンは常に SetNormal()(データなし時はGameObject自体が非表示のため不要)
ボタン状態
slotButton(通常)Normal / Hover / Press
slotButton(オートスロット・セーブ時)Disabled
deleteButtonNormal / Hover / Press

実機での挙動

セーブ時のスクリーンショットで詰まりそうになりましたが、
設定画面のデザイン実装に関してはすんなりと行きました。

キー操作」「パッド操作」は、まだすべてに対応させていないので見送りです。
キーコンフィグには手を出さないほうが良さそうな感じなので「操作画面」止まりにはなりそうです。

次はメイン画面内のUI?を実装しようと思います。
難題は音源連動のイコライザーになりそうですが、やはり音関係には必須システムですので頑張ります(^ω^)

コメント