マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

視点の直線上にあるオブジェクトの名前を表示する

オブジェクトを追跡するラベルを参考に(とは言ってもそのままだが)視点の直線上にあるオブジェクトの名前を表示するプログラムを作った。以下のプログラムをC#スクリプトとして作成して、First Person Controllerに貼り付ければOK。直線上の物体はPhysics.Linecastで取得できる。あとは先ほどのリンクの通りやれば視点の直線上にあるオブジェクトの名前が表示されるはず。ただ、カメラとオブジェクトの位置によって名前の表示位置がオブジェクトから離れてしまったりするのでそこを改善したい


using UnityEngine;
using System.Collections;

public class PrintName : MonoBehaviour {

    public Vector3 offset;    // 表示位置の調整
    public float width;        // 表示領域の幅
    public float height;    // 表示領域の高さ
   
    void Awake () {
        offset = new Vector3(0.0f, 2.0f, 0.0f);
        width = 100;
        height = 20;
    }

    // スクリーン座標を GUI 座標に変換
    private Vector2 ScreenToGUI (float x, float y) {
        return new Vector2 (x, Screen.height - y);
    }
    
    //オブジェクトのGUIを取得
    private Vector2 GetGUIPoint(Vector3 target){
        // オブジェクトのスクリーン座標を取得
        Vector3 sp = Camera.main.WorldToScreenPoint(target);
        
        //GUI座標に変換
        return ScreenToGUI(sp.x, sp.y);
    }
    
    //オブジェクトの名前をGUIで表示する
    private void DrawTargetName(Transform target, Vector2 screenPos){
        GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));

        GUI.Label(
            new Rect(screenPos.x - width * 0.5f,
                screenPos.y,
                width, height),
            target.name);
       
        GUILayout.EndArea();
    }
    
    void OnGUI(){
        Vector3 from = transform.position;
        Vector3 to = from + transform.forward * 100.0f;
        RaycastHit hit;

        if(!Physics.Linecast(from, to, out hit)){
            return;
        }
        
        //直線上にある最も近い物体を取得
        Transform target = hit.transform;
       
        //GUI 座標に変換
        Vector2 screenPos = GetGUIPoint(target.position + offset);
        
        //Targetの名前を描画する
        DrawTargetName(target, screenPos);
    }
}