独自バックログを実装【Unity6】

絶対調味ロジック

バックログは、採用しているメッセージ表示スクリプトに紐づけられての実装となると思います。
開発中の会話スクリプトは細々した機能をすでに搭載しているので、バックログがつくれるのかも分かりません。

会話システムに対しての設計図

Geminiに会話スクリプトを見てもらい、バックログを搭載できるのかを聞いてみました。

会話スクリプトの改修・バックログ表示用のオブジェクト作成、それらを連動させればいけそうな雰囲気です。

  • LogItemプレハブ ・・・・・・謎のテキストフィールドをプレハブ化
  • BacklogCanvas ・・・・・・メインCanvasの他で、バックログ専用のCanvasを作成
  • BacklogPanel ・・・・・・・バックログ表示用のUIパネル
  • Scroll View ・・・・・・・・バックログのスクロールフィールド

もちろんよく分からないので、言われるがままにオブジェクトとその設定をこなしていきます。

バックログ用UIオブジェクトの設置・設定

専用CanvasPanel(背景パネル)を作成。

■「Canvas」設定 >「Canvas Scaler
・UI Scale Mode Scale With Screen Size
・Reference Resolution 1600×900(ゲームの基準解像度)
・Screen Match Mode Match Width Or Height

Scroll View(スクロールフィールド)を作成。

■「Scroll View」設定 >「Scroll Rect
・Horizontal OFF(横スクロールは不要)
・Movement Type Clamped(ログの端でピタッと止まる設定。お好みで Elastic でも可)

■「Scroll View」 >「Viewport
・Mask コンポーネントを削除
・RectMask2D コンポーネントを追加(これで画面外のログの描画負荷をゼロにします)

Content(ログが並ぶ場所)の設定

■「Viewport」 >「Content
・Vertical Layout Group コンポーネントを追加
 Padding:Left / Right / Top / Bottom に適度な余白(例: 20)を入れる。
 Spacing:ログ一行ごとの隙間(例: 10)。
 Control Child Size:Width(ON) / Height(ON)
 Use Child Scale:Width(OFF) / Height(OFF)
 Child Force Expand:Width(ON) / Height(OFF)
・Content Size Fitter コンポーネントを追加
 Horizontal Fit:Unconstrained
 Vertical Fit:Preferred Size(ログが増えるほど Content の高さが自動で伸び、正しくスクロールできるようになる)

バックログ・アサイン設定

会話スクリプト内に追加されたバックログ設定に各オブジェクトをアサインしていきます。

負荷軽減を優先して作ってもらったシステムになります。
区切り線」を画像にするか、1px画像を引き延ばす作戦にするか、テキストを使うか、で
一番負荷の少ないテキストを線に見立てる方法をとってもらいました。

言われるがままに作成したオブジェクトですが、各説明を見ると、なんとなくの役割が理解できてきます。

至れり尽くせりのお膳立てにより、バックログの表示に成功です。
想定していたほどの問題は起きずに、見事に表示されてご満悦♪

会話システムとバックログの分離

できるかどうか分からなかったので、会話システム上にバックログ設定を追加しましたが、
分離できるならば、それに越したことはないので、やってもらうことに。

システム分離が、軽量化と利便性の向上につながり、良い感じの構築になりました。

  • バックログ部分は、1~3ドローコール程度で収まる。
    ・フォントアセットを使っている限り、100行あっても1回でまとめて描画(Batching)と判断してくれます。
    ・「RectMask2D」の採用で、画面外(スクロールで見えていない部分)のログは描画計算そのものがスキップ。
  • テクスチャサイズ(メモリ負荷)はほぼ増えない
    フォントアセットを使用しているので、
     ログが1文字でも1万文字でも、使っている「文字種」が同じならば、メモリ上のテクスチャサイズは増えない。
    ・背景(Background)も単色なら、無視できるほど軽量。
項目今回の構成
ドローコールほぼ一定(1~3)
CPU負荷ログ追加時の一瞬のみ
GPU負荷RectMask2Dで画面外はゼロ

分離によるメリット

  • マルチログ対応
    「ストーリーログ」と「システムメッセージ」など、
    複数のログを別々のオブジェクトにアタッチしたメッセージシステムで個別に管理できる。
  • デバッグの容易さ
    ログが表示されないとき、原因が「メッセージシステム」にあるのか「ログシステム」にあるのかが明確になる。
  • 拡張性
    例えば「ログをファイルに保存する機能」を追加したくなった場合、「ログシステム」だけを改造すれば済む。

分離を活かした今後のアイディア

  • システムメッセージの記録
    アイテムを手に入れた時やフラグが立った時の通知(名前なしメッセージ)をログに混ぜ込める。
    (backlogManager.AddEntry(“”,”勇者は剣を手に入れた!”);
  • ボタン一発で全消去
    「logContent」の子要素を全部「Destroy」するメソッド追加で、「ログをクリア」ボタンが作れる。
  • 特定のログだけ色を変えれる
    「AddEntry」に引数を増やして、重要な会話だけ背景や文字色を変えることが可能。

理想的なシステムになり、演出の伸びしろも確保で完璧です(*´ω`*)

見た目の修正・調整

よく見ると、設定した「区切り線」が表示されていません。
同名の場合との違いも認識して、ちゃんと分かれるように修正していきます。

じゃっかんハマったので、細かくログにでるようにしてもらいチェックしていきます。

同じ「名前」の場合は、非表示にし、スペースを開けるようにも設定します。

最後まで進んでみて発覚することもあります。

「名前」部分が長いと、スペースとの差が生まれてしまって美しくありません。
そして「地の文」の時には「Unknown」と出てしまっています。(気を利かせて作ってくれていたものと思われます)

「名前」表示をセリフの上にすることで、長さ問題を解決。
「Unknown」表示も消してもらいました。
スペース設定はいらなくなったので削除です。(地味に数値設定が厄介だったので良い方向転換)

最後、気になったのはマウスホイールの感度(スクロール幅)

「Scroll View」>「Scroll Sensitivity
数値での変更設定があったので、これは楽でした。
「60」くらいにして様子見です。

まとめ

バックログシステム:完成

ビジュアルをいじってませんが、システムは完成です。
文字幅・区切り線幅・行間も数値で設定でき、デザイン表現は問題なし。
スクロール部分なども画像の差し替えでカスタムできるみたいなので、見た目変更も楽そうです。

独自会話システムを採用しているので、実装を敬遠していたバックログでしたが、
思ったよりもすんなりと実装出来て驚いています。

バックログシステム:資料

構成スクリプト

  • Sys_BacklogManager.cs:ログの生成、保持、最大件数管理、UI表示制御
    AddEntry(name, message) 外部からテキストを登録。【重要機能
    static lastCharaName:名前の変化を検知し、自動で境界線を挿入
    CalculateLayoutInputVertical():Unity 6のUIバグ(点滅・ガタつき)を防ぐための手動サイズ計算
  • Sys_Messenger.cs(独自会話システム):会話の進行、タイピング演出、入力検知
    「backlogManager」変数を通じて、発話の瞬間にログ登録を依頼。【連携

UI構造(階層図)

“`text
BacklogCanvas (Canvas / SortOrder: 10)
└── BacklogPanel (Panel / RaycastTarget: ON / ログ表示のトリガー)
└── Scroll View (ScrollRect / Horizontal: OFF)
└── Viewport (RectMask2D / 描画負荷削減)
└── Content (VerticalLayoutGroup + ContentSizeFitter)
└── LogItem (Prefab / TMP_Text単体 / Canvasなし)

操作仕様

  • ホイール上:バックログを開く
  • ホイール下:会話を進める(※バックログ表示中は無効化され、ログのスクロールに専念
  • 右クリック / ESC:バックログを閉じる

注意点(チェックリスト)

  • Unity6最適化:「LogItem」プレハブ内に「Canvas」を入れないこと(ドローコール増加と点滅の原因になるため)
  • アサイン:BacklogManager枠に、シーン内のBacklogManagerオブジェクトを必ずセットすること
  • 章の切り替え:シーンを跨ぐ際は、Sys_BacklogManager.ResetBacklogState();を呼び出すことで
    「直前の話し手」の記憶がリセットされ、新しい章の冒頭に不要な境界線が出るのを防げる。

コメント