▶
【Unity】3Dアクションゲームを作ろう!#7 ステージの作成(Skybox・落下判定)
▶
【Unity】3Dアクションゲームを作ろう!#8 ステージの作成(スイッチ・扉)
▶
【Unity】3Dアクションゲームを作ろう!#9 プレイヤーのHP管理
▶
【初心者Unity】JsonUtilityクラスでJSONを扱う方法
▶
【初心者Unity】スクリプトからコンポーネントを追加する方法
RenderModeによって異なる、HUDの表示方法
uGUIをキャラクターの頭上に表示(HUD)して、オブジェクトの移動に追従させる方法は、CanvasのRenderModeによって異なります。
今回はその実装の手っ取り早い方法について、RenderMode別に解説します。
RenderModeについての詳しい解説は、こちら をご覧ください。
※使用しているUnityのバージョンは2017.1.0f3です。
[Unity_317×90]
Screen Space – Overlayの場合

© Unity Technologies Japan/UCL
CanvasのRenderModeがScree Space – Overlayの場合、UIの位置をキャラクターに合わせて変化させるためには、キャラクターのワールド座標をスクリーン座標に変換してからUIに教える必要があります。
ワールド座標からスクリーン座標への変換は、RectTransformUtilityクラスに用意されているWorldToScreenPointメソッドを使用します。
同期させたいUIオブジェクトに適用するスクリプトです。
using UnityEngine;
public class UIController_Overlay : MonoBehaviour {
[SerializeField]
private Transform targetTfm;
private RectTransform myRectTfm;
private Vector3 offset = new Vector3(0, 1.5f, 0);
void Start() {
myRectTfm = GetComponent<RectTransform>();
}
void Update() {
myRectTfm.position
= RectTransformUtility.WorldToScreenPoint(Camera.main, targetTfm.position + offset);
}
}
WorldToScreenPointメソッドは、第1引数に描画するカメラ(コンポーネント)の指定、第2引数に変換対象のTransformのPosition(Vector3)を指定することで、Canvas平面上に対応するVector2の値を返します。
例えば下記のスクリプトは、位置を変化させたいUIオブジェクトにアタッチします。
UIを追従させる対象のPlayerオブジェクトからワールド座標を取得し、メインカメラにおけるスクリーンポジションを算出してRectTransformのPositionに値を代入しています。
ちなみに、変換される座標はPivotが基準になるため、キャラクターの頭上に表示するためにオフセットで調整しています。
Screen Space – Cameraの場合

© Unity Technologies Japan/UCL
RenderModeがScree Space – Cameraの場合、UIはカメラが描画ことになります。
そのため、Scree Space – Overlayでの変換にもうひと手間加え、ワールド座標から算出したスクリーン座標を、カメラの描画角を基準としたローカル座標に変換します。
ローカル座標への変換は、RectTransformUtilityクラスのScreenPointToLocalPointInRectangleメソッドを使用します。
using UnityEngine;
public class UIController_Camera : MonoBehaviour {
[SerializeField]
private RectTransform canvasRectTfm;
[SerializeField]
private Transform targetTfm;
private RectTransform myRectTfm;
private Vector3 offset = new Vector3(0, 1.5f, 0);
void Start() {
myRectTfm = GetComponent<RectTransform>();
}
void Update() {
Vector2 pos;
Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(Camera.main, targetTfm.position + offset);
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTfm, screenPos, Camera.main, out pos);
myRectTfm.position = pos;
}
}
ScreenPointToLocalPointInRectangleメソッドは、第1引数にCanvasのRectTransform、第2引数に変換するスクリーン座標、第3引数にUIを描画するカメラ(コンポーネント)、第4引数にoutパラメータを付与したVector2の変数を渡します。
outに渡す引数は事前に宣言しておきます。算出された値はoutの変数に入ります。
World Spaceの場合

© Unity Technologies Japan/UCL
RenderModeがWorld Spaceの場合、UIは通常のゲームオブジェクトと同じようにワールド座標系に配置できます。
したがって、手っ取り早くプレイヤーの位置と同期させるなら、プレイヤーの子オブジェクトにしてしまいましょう。
ただし、Rotationも同期されてしまうため、UIがカメラの方向を向くようにスクリプトで処理します。
using UnityEngine;
public class UIController_WorldSpace : MonoBehaviour {
private RectTransform myRectTfm;
void Start() {
myRectTfm = GetComponent<RectTransform>();
}
void Update() {
// 自身の向きをカメラに向ける
myRectTfm.LookAt(Camera.main.transform);
}
}
一番手っ取り早い感ありますね。
おまけ(列挙型を使ってRenderModeに動的に対応する)
別々のスクリプトを用意するのが面倒だったので、列挙型のRenderModeを使って一つのスクリプトにまとめてみました。
RenderModeが切り替わっても自動で対応できます。
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class UIController : MonoBehaviour {
[SerializeField]
private Canvas canvas;
[SerializeField]
private Transform targetTfm;
private RectTransform canvasRectTfm;
private RectTransform myRectTfm;
private Vector3 offset = new Vector3(0, 1.5f, 0);
void Start() {
canvasRectTfm = canvas.GetComponent<RectTransform>();
myRectTfm = GetComponent<RectTransform>();
}
void Update() {
Vector2 pos;
switch (canvas.renderMode) {
case RenderMode.ScreenSpaceOverlay:
myRectTfm.position = RectTransformUtility.WorldToScreenPoint(Camera.main, targetTfm.position + offset);
break;
case RenderMode.ScreenSpaceCamera:
Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(Camera.main, targetTfm.position + offset);
RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRectTfm, screenPos, Camera.main, out pos);
myRectTfm.localPosition = pos;
break;
case RenderMode.WorldSpace:
myRectTfm.LookAt(Camera.main.transform);
break;
}
}
}
私はこれ↑を使ってます。
以上です。
▶
【Unity】3Dアクションゲームを作ろう!#7 ステージの作成(Skybox・落下判定)
▶
【Unity】3Dアクションゲームを作ろう!#8 ステージの作成(スイッチ・扉)
▶
【Unity】3Dアクションゲームを作ろう!#9 プレイヤーのHP管理
▶
【初心者Unity】JsonUtilityクラスでJSONを扱う方法
▶
【初心者Unity】スクリプトからコンポーネントを追加する方法
ゲーム制作関連のオススメ連載リンク
とっても手軽なゲーム制作体験!
Unityゲーム開発基礎
実際のリリースゲームを題材にしたハンズオンゲーム制作連載
実践unityゲーム開発