3Dの空間内をキャラクタが動きます。常にその近くで何かをUI(パネルなど)で表示したいとします。例えばキャラクタの名前とか。サイトをあちこち調べ(それでもなかなかうまくいかなかったんですが)、ようやくなんとかなりました。こんな感じです。
ハートをQuadに貼り付けたキャラクタが空間内を動きます。「これはQuadですよ」という説明をキャラの近くに常にUI(パネル)で表示します。パネルはCanvasに配置されています(Canvasはパネルの親)。
パネルはアンカーを中央(middle, center)、ピボットは(0.5, 0.5)としています。アンカー、ピボットについては前回の記事を参照してください。
方針としては、キャラクタの空間内の位置からスクリーン座標を求め、そこからキャンバス上の座標を得る、ということになります。以下の関数で実現できます。
//-----------------------------------------
void dispUI(Vector3 pos, GameObject goPanel) {
RectTransform rt = goPanel.GetComponent<RectTransform>();//①
RectTransform parentRt = rt.parent.GetComponent<RectTransform>();//②
Vector3 scrPt = Camera.main.WorldToScreenPoint(pos);//③
Vector2 v2 = new(scrPt.x, scrPt.y + 50);//④
Vector2 localPt;
RectTransformUtility.
ScreenPointToLocalPointInRectangle(
parentRt, v2, null, out localPt);//⑤
rt.localPosition = localPt;//⑥
}
//-----------------------------------------
引数のposはキャラの表示されている位置です。この近くにUIを表示するのが目的です。次の引数、goPanelはUIのゲームオブジェクトです。②ではパネルの親(Canvas)のRectTransformを取得しています。③は空間内の位置posをスクリーン座標に変換しています。スクリーン座標は画面の左下が(0, 0)、右上が(W-1, H-1)(Wはスクリーンの横のドット数、Hは縦のドット数)です。得られるscrPtは第1、2成分がスクリーン座標です。第3成分はカメラからposまでの距離ですが、ここでは使っていません。④でv2を得られたキャラのスクリーン座標より少し上にパネルを表示したいのでy成分を「+50」しています。⑤はスクリーン座標をparentRt(キャンバスのRectTransform)上の点の座標に変換します。第3引数でnullとなっているのは、CanvasのRender Modeが「Overlay」だからです。他の場合は使っているカメラ(Camera.mainとか)を入れるようです。第4引数に変換結果が得られます。最後、⑥でパネルの位置をセットして終わりです。
夏休みなので開発作業も進むし勉強もできるし、ブログも書けるしありがたいです。こうして余裕を持って面白いことを見つけて生徒に還元。これが本当の教育というものでしょう。