マウス座標を3Dのワールド座標に変換してキャラクターを動かす

投稿者: | 2019-12-11

マウスでクリックした場所にナビメッシュエージェントを移動させてみます。

空のゲームオブジェクトに新しいスクリプトを付けます。
Textオブジェクトも作ります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class gameScript : MonoBehaviour
{

    public Text text;
    Vector3 cursorPosition;

    // Start is called before the first frame update
    void Start()
    {
        text.text = "";
    }

    // Update is called once per frame
    void Update()
    {
        cursorPosition = Input.mousePosition; // 画面上のカーソルの位置
	text.text = cursorPosition.ToString();
    }
}


マウスカーソルの画面上の座標が表示されます。左下が(0,0)です。平面なのでZ座標は常に0です。

メインカメラのScreenToWorldPoint()メソッドを使うと、これをワールド座標に変換できます。
デフォルトのメインカメラには始めから「MainCamera」タグが付いていて、このタグが付いているカメラは、Camera.main で取得できます。

参考:https://docs.unity3d.com/ja/current/ScriptReference/Camera-main.html

Z座標が0のままだとうまく行かないので、その前にZ座標に適当な値を入れます。

cursorPosition = Input.mousePosition; // 画面上のカーソルの位置
cursorPosition.z = 10.0f; // z座標に適当な値を入れる
cursorPosition3d = Camera.main.ScreenToWorldPoint(cursorPosition); // 3Dの座標になおす

Debug.DrawRay(Camera.main.transform.position, (cursorPosition3d - Camera.main.transform.position) * 100f, Color.red); // デバッグのレイを飛ばす

カメラからマウスカーソルが指す方向へレイを飛ばし、そのレイが他のオブジェクトとぶつかったポイントの座標を取得してみます。
デバッグ用のでなくゲームで使う普通のレイを飛ばします。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class gameScript : MonoBehaviour
{

    public Text text;
    Vector3 cursorPosition;
    Vector3 cursorPosition3d;
    RaycastHit hit;

    // Start is called before the first frame update
    void Start()
    {
        text.text = "";
    }

    // Update is called once per frame
    void Update()
    {
        cursorPosition = Input.mousePosition; // 画面上のカーソルの位置
        cursorPosition.z = 10.0f; // z座標に適当な値を入れる
        cursorPosition3d = Camera.main.ScreenToWorldPoint(cursorPosition); // 3Dの座標になおす

        // カメラから cursorPosition3d の方向へレイを飛ばす
        if (Physics.Raycast(Camera.main.transform.position, (cursorPosition3d - Camera.main.transform.position), out hit, Mathf.Infinity))
        {
            Debug.DrawRay(Camera.main.transform.position, (cursorPosition3d - Camera.main.transform.position) * hit.distance, Color.red);

            text.text = hit.point.ToString();
        }
              
    }
}

参考:https://docs.unity3d.com/jp/current/ScriptReference/RaycastHit.html


Planeの座標が(0, 0, 0)なので、カーソルがPlaneを指しているときのY座標は常に0です。グレーのCubeは高さが1なので、その上ではY座標は1になって、その側面はその中間の値になっています。
オブジェクトの表面の、マウスカーソルで指し示したポイントの座標が取れていることがわかります。

キャラクターを動かす

スタンダードアセットにあるAI TPSキャラクターをシーンにドラッグアンドドロップします。

床やCubeをまとめて選択します。

NavigationウィンドウでNavigation Staticにチェックを入れます。

Bake -> Bakeボタンを押します。

これでAI TPSキャラクターを動かせるようになりました。

AI TPSキャラクターには Nav Mesh Agentコンポーネントが予め付いているので、目的地を指定するとその場所へ移動してくれます。

目的地を教えるには、スクリプトでdestinationプロパティに目的地の座標を入れるだけです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.AI;

public class gameScript : MonoBehaviour
{

    public Text text;
    Vector3 cursorPosition;
    Vector3 cursorPosition3d;
    RaycastHit hit;

    public GameObject aiCharacter;
    NavMeshAgent agent;

    // Start is called before the first frame update
    void Start()
    {
        text.text = "";
        agent = aiCharacter.GetComponent<NavMeshAgent>();
    }

    // Update is called once per frame
    void Update()
    {
        cursorPosition = Input.mousePosition; // 画面上のカーソルの位置
        cursorPosition.z = 10.0f; // z座標に適当な値を入れる
        cursorPosition3d = Camera.main.ScreenToWorldPoint(cursorPosition); // 3Dの座標になおす

        if (Input.GetMouseButtonDown(0)) // マウスの左クリックをしたとき
        {
            // カメラから cursorPosition3d の方向へレイを飛ばす
            if (Physics.Raycast(Camera.main.transform.position, (cursorPosition3d - Camera.main.transform.position), out hit, Mathf.Infinity))
            {
                Debug.DrawRay(Camera.main.transform.position, (cursorPosition3d - Camera.main.transform.position) * hit.distance, Color.red);

                //text.text = hit.point.ToString();

                agent.destination = hit.point; // エージェントに目的地を教える
            }
        }       
    }
}

マウスでクリックしたポイントにキャラクターが移動します。

コメントを残す

メールアドレスが公開されることはありません。