質問: new Vector3(min.x, min.y, myZ); } ``` ゲーム実行結果、やはり意図しない配置になりました。 ![イメージ説明](https://teratail.storage.googleapis.com/uploads/contributed_images/68caccd4d71ce253ce35a9a6be9f0490.jpeg)
回答: おそらく意図する動きは、 ``` void Start() { // キューブのワールド座標をメインカメラから見たビューポート座標に直す Vector3 viewportPosition = Camera.main.WorldToViewportPoint(this.transform.position); // xとyを0に書き換える // zにはメインカメラから見たキューブのカメラZ方向の位置...つまり奥行きの距離が入っているはずなので、書き換える必要はない viewportPosition.x = 0.0f; viewportPosition.y = 0.0f; // ビューポート座標をワールド座標に直し、キューブの位置をそこに設定する this.transform.position = Camera.main.ViewportToWorldPoint(viewportPosition); } ``` !プレビュー でいけるかと思うのですが、ご質問者さんの実験結果がちょっと妙ですので、なにか他の問題があるかもしれません。 ~~スクリプトがちゃんと目的のキューブにアタッチされているか(こちらは気づきやすいので間違ってはいないかと思いますが...)、カメラのタグが「MainCamera」になっているか、といった点を確認してみる必要がありそうです。~~ ※下に追記しましたが、実験結果について説明が付きそうでしたので、この部分は取り下げます。 ※ViewportToWorldPointの日本語版リファレンスでは、英語版リファレンスに載っている詳しい解説がかなり欠落しているようです。 > > public Vector3 **ViewportToWorldPoint**(Vector3 **position**); > > > **Parameters** > > **position** The 3d vector in Viewport space. > > > **Returns** > > **Vector3** The 3d vector in World space. > > > **Description** > > Transforms position from viewport space into world space. > > > Viewport space is normalized and relative to the camera. The bottom-left of the viewport is (0,0); the top-right is (1,1). The z position is in world units from the camera. > > > Note that ViewportToWorldPoint transforms an x-y screen position into a x-y-z position in 3D space. > > > Provide the function with a vector where the x-y components of the vector are the screen coordinates and the z component is the distance of the resulting plane from the camera. > > > 多少表現を補って解釈すると、下記のような内容かと思います。 *public Vector3 **ViewportToWorldPoint**(Vector3 **position**);* ***パラメーター*** ***position** ビューポート空間における3Dベクトル* ***戻り値*** ***Vector3** ワールド空間における3Dベクトル* ***説明*** *ビューポート空間におけるpositionをワールド空間における座標に変換します。* *ビューポート空間は正規化された、カメラに対して相対的な座標系となります。ビューポートの左下は(0,0)、右上は(1,1)です。z位置はワールド座標系単位でのカメラからの位置です。* *注意:ViewportToWorldPointはx-yからなるビューポート位置をx-y-zからなる三次元空間上の位置に変換します。引数として与えるベクトルはx-y成分にビューポート座標を、z成分に変換先平面のカメラからの距離を指定してください。* ### 追記 nearClipPlane、farClipPlaneについてですが、これらはカメラのインスペクタの「Clipping Planes」の「Near」と「Far」に対応していて、カメラに対して前後にこの範囲を外れた部分はスッパリ切断されたように描画されなくなってしまいます。描画の都合上、カメラに極めて近い部分や無限に遠い部分を表示することはできないため、これらに適切な値を入れて前後方向の描画範囲を制限してやる必要があります(参考:【Unity】【数学】視錐台(Frustum)について(第1回) – 株式会社ロジカルビート)。 ご質問者さんの参考にされたサイトでzにnearClipPlaneを使っているのは多分「nearClipPlaneの位置が視錐台前後方向の手前側の境界だから」といった理由ではないでしょうかね。 今回重要なのは水平垂直方向の境界がワールド空間ではどの位置にあるかということであって、zについては本来のオブジェクトの位置を維持したいということなので、上に例示したコードのように元のビューポート座標のzをそのまま使えばいいかと思います。 ### さらに追記 ご質問者さんのコードをあらためて見直してみたところ、実験結果はこのように説明できそうでした。 * nearClipPlaneを使わないで(0,0)の配置を試みた場合 カメラのワールド座標を(cx, cy, cz)とする。 `Camera.main.ViewportToWorldPoint(new Vector2(0, 0))`は型変換によってzが補われ、`Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0))`と解釈される。 得られるVector3は、引数として与えたビューポート座標のzが0なので、カメラを頂点とする四角錐の頂点...つまりカメラ自身の座標(cx, cy, cz)となる。 これを一旦Vector2型の`min`に代入したため型変換が起こり、czは欠落する。 `min`をVector3である`this.transform.position`に代入する際にまた型変換が起こり、z座標が補われた結果キューブの座標は(cx, cy, 0)に移動する...つまりワールドX、ワールドYはカメラの位置と同じで、ワールドZは0となる。 * nearClipPlaneを使って(0,0)の配置を試みた場合 移動前のキューブのワールド座標を(ox, oy, oz)とする。このうちozを変数に保管しておく。 `Camera.main.ViewportToWorldPoint(new Vector3 (0.0f, 0.0f, Camera.main.nearClipPlane))`の結果はニアクリップ面矩形の左下隅...つまりシーンビュー上に表示されているカメラ描画範囲の、カメラに近い側の四角形の左下隅のワールド座標となる。この座標を(nx, ny, nz)とする。 得られた座標のX、Yと、保管しておいたozを組み合わせて新たなVector3とし、これを`this.transform.position`に代入する。 結果、キューブの座標は(nx, ny, oz)に移動する...つまりニアクリップ面矩形の左下隅をZ軸方向に動かしていき、ozの位置に合わせたのと同等な位置となる。 こう考えれば、キューブの位置がご提示いただいた図のような位置になりそうです。ですので、先の回答で申し上げたカメラのタグ確認などは不要そうでしたね。お手間を取らせすみませんでした。