こんにちは、Unityエンジニアのオオバです。

スクリーン座標をワールド座標に変換することって
年に何度か発生します。

オオバ
オオバ
そのたびに実装方法を忘れませんか(笑)

そんな未来のあなたのために、
Unityで スクリーン座標をワールド座標に変換方法
を解説します。

カメラを使ってScreenToWorldPointで座標変換

【Unity】スクリーン座標をワールド座標に変換する方法_0

結論を簡単にまとめます。

ソースコードで表すとコチラです。

💻ソースコード : マウス座標をワールド座標に変換するUnityサンプル
// マウスのスクリーン座標  
var screenPos = Input.mousePosition;  

// 例としてカメラから5m離れた場所を指定  
screenPos.z = 5;  

// スクリーン座標をワールド座標に変換  
var worldPos = _camera.ScreenToWorldPoint(screenPos);  

このコードを使うと、
マウスの座標がワールド空間の座標に変換されます。

使用例とともに詳細の解説に移ります。

→11万文字で徹底解説した「DOTweenの教科書」Unityアニメーションの超効率化ツールはこちら

マウスを追いかけるワールド空間のオブジェクト制御

このようなマウスに追随して
ワールド座標にメッシュを描画したいとします。

【Unity】スクリーン座標をワールド座標に変換する方法_1

実装するにあたって必要なのは、
マウスの座標をワールド座標に変換 することです。

マウスの座標とは解像度に依存した座標
つまりスクリーン座標のことです。

スクリーン座標とは解像度に依存した座標

スクリーン座標について解説します。

【Unity】スクリーン座標をワールド座標に変換する方法_2

となります。
Screen.widthScreen.height は解像度です。
640px 480pxのモニタだとしたら、

という値が入ります。

これがスクリーン座標です。

💻ソースコード : マウスからスクリーン座標の取得するサンプル
// スクリーン座標の取得  
var screenPosition = Input.mousePosition;  

マウスからスクリーン座標を取得したい場合は、
Input.mousePositionを使います。

この解像度に依存した座標を、
3D空間上に変換していきます。

カメラを使ってワールド座標に変換する

【Unity】スクリーン座標をワールド座標に変換する方法_3

Cameraコンポーネントの ScreenToWorldPoint を使います。
スクリーン座標をワールド座標に変換するメソッドです。

ScreenToWorldPoint(スクリーン座標);  

このようにスクリーン座標を代入すると
ワールド座標に変換されます。

オオバ
オオバ
簡単そうに見えますよね。

落とし穴 があるんです。

ScreenToWorldPointにマウス座標をそのまま代入してはいけない

試しにマウスの座標をワールド座標に変換してみます。

💻ソースコード : マウス座標をワールド座標に変換したサンプル
using UnityEngine;  

public class ScreenToWorld : MonoBehaviour  
{
    void Update()  
    {
        var worldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);  
        transform.localPosition = worldPos;  
    }
}

コチラのコードを実行してみます。

【Unity】スクリーン座標をワールド座標に変換する方法_4

何も表示されません。

👉 【Unityの基本】Transformを徹底解説「移動」や「回転」だけじゃない

カメラとオブジェクトが同じ座標に配置される

シーンビューを確認すると理由が分かります。

【Unity】スクリーン座標をワールド座標に変換する方法_5

カメラとオブジェクトが同じ座標になり
カメラに映らないため何も表示されないのです。

原因は Input.mousePositionのZ座標が0 であること。

ScreenToWorldPointのZ座標は
スクリーンからの距離にあたります。

つまりカメラからの距離です。
Input.mousePositionのZ値は0であるため、
常に カメラと同じ位置になってしまう というわけです。

ScreenToWorldPointのZ値はカメラからの距離

ScreenToWorldPointのZ値はカメラからの距離になります。

【Unity】スクリーン座標をワールド座標に変換する方法_6

↑↑つまりこういうことです。

ScreenToWorldPointのZ値を変えましょう。
試しにカメラから5m離れた場所を指定してみます。

var mousePos = Input.mousePosition;  
var worldPos = Camera.main.ScreenToWorldPoint(mousePos.x, mousePos.y, 5f);  
transform.localPosition = worldPos;  

【Unity】スクリーン座標をワールド座標に変換する方法_7

表示されました!!

【Unity】スクリーン座標をワールド座標に変換する方法_8

このようにScreenToWorldPointにマウス座標のX、Yを与えつつ、
Z値にカメラからの距離を指定することで
意図通りの挙動になります。

まとめ : スクリーン座標をワールド座標に変換する方法

【Unity】スクリーン座標をワールド座標に変換する方法_9

記事の内容を簡単にまとめます。

こんな感じです。

冒頭で触れたとおり、
スクリーン座標をワールド座標に変換することが
ときどき発生します。

だいたい使わない機能は忘れてしまうため、
この記事を読んで思い出してもらえればと思います。

オススメ記事
検証環境