ふと、キャラクターネーム表示を「MMO」っぽくしてみようと思いたちました。
所属部活を「クラン」のようにも表示してみようかなと。
Aiには「ADVでそれやると視線が定まらなくなる」と怒られつつも強行突破です。
単純にUI画面で「名前プレート」を設置だと、
カメラ位置(引き寄り)によってキャラクターとの距離が定まらなくて位置の違和感があります。
キャラクターの子オブジェクトに名前プレートを設置もやってみましたが、
こちらは追従はできるものの、やはりカメラ位置によっては、今度はサイズがバラバラになります。
これは想定よりも意外に難しそうです。
UIオブジェクトと通常オブジェクトの連携になるので、それなりのシステムが必要と判断し本腰を入れます。
ChtatGPTにて勧められた「World Space UI方式(MMO型)」というのを実装してみました。
これでもまぁ良かったのですが、カメラ位置でのズレが若干気になっていたので、
Claudeにて変更案の「Screen Space UI + WorldToScreenPoint方式」というので再実装しました。
追従型ネームプレートの設計図
目的
- 2.5D ADVにてキャラクターの頭上にネームプレートを正確に表示する
- 同キャラクター・複数ポーズに共通のネームプレートを表示させる
採用方式・採用理由
Screen Space UI + WorldToScreenPoint方式
- WorldSpace UI方式 → Perspectiveカメラの歪みでズレが発生するため却下
- WorldToScreenPoint → ワールド座標をスクリーン座標に変換するためズレが原理的に発生しない
全体構成
Scene
├ ito_normal(ポーズPrefab)
│ ├ Ma_ito_normal_eye
│ ├ Ma_ito_normal_mo
│ ├ Ma_ito_normal_main
│ ├ ito_N_Anchor(空Object・頭上に配置)
│ └ Sys_AnchorSync
│ myAnchor → ito_N_Anchor
│ characterID → “ito“
│
├ ito_End(ポーズPrefab)
│ └ 同上構成・characterID → “ito“(共通)
│
├ ito_battle(ポーズPrefab)
│ └ 同上構成・characterID → “ito“(共通)
│
└ UICanvas(Screen Space Overlay・Scene共通1枚)
└ Ito_Plate(非アクティブ初期状態)
└ Sys_NamePlateScreen ← characterID → “ito“
新規スクリプト

■ Sys_AnchorSync
ポーズPrefabのルートにアタッチ。
OnEnableのタイミングで対応するPlateにアンカーを登録する。
■ Sys_NamePlateScreen
UICanvas内のPlateにアタッチ。
毎フレームアンカーのワールド座標をスクリーン座標に変換して位置を更新する。
キャラクター追加時の手順
Anchor(空Object)を追加
ポーズ Prefab に Anchor(空Object)を追加し、頭上(任意)に配置します。

Sys_AnchorSync をアタッチ
ポーズ Prefab(親オブジェクト)に Sys_AnchorSync をアタッチし、
自身の基準アンカーと共通させる characterID を設定します。

Sys_NamePlateScreen をアタッチ
UICanvasの名前プレートに Sys_NamePlateScreen をアタッチし、
Sys_AnchorSync で設定した同じ characterID を設定します。

実機での見た目

ビルド後のアプリで実際に確認してみます。
カメラ位置によって、多少のズレはありますが、追従かつサイズ固定は成功しています。
実際のMMOでもキャラクターとの位置はカメラによって変わるので、こんなものでしょうか。
本格MMO式を取り入れようとすると、より複雑になりそうだったので今回は我慢です。
ちょっとした思い付きでしたが、なかなかに時間をとられたのが想定外でした。
同じキャラクター・ポーズ差分での共有という条件もあったので、
そこもちょっと時間がかかった要因になりました。
表示されている部活マークが気に入っています(*´ω`*)
改善★0411
■ 問題
解像度変更(960×540 / 1280×720 / 1600×900)でPlateの位置がずれる
■ 原因
WorldToScreenPoint はピクセル座標を返すため解像度に依存する。
解像度が下がるほどPlateが頭上から離れる挙動が発生。
■ 解決
WorldToViewportPoint で0〜1の正規化座標に変換し、Canvas解像度を掛けて配置。
解像度変化の影響を受けなくなった。
WorldToScreenPoint → ピクセル座標(解像度依存)→ ズレる
WorldToViewportPoint → 0〜1正規化座標(解像度非依存)→ ズレない
■ 変更箇所
Sys_NamePlateScreen のLateUpdateのみ

コメント