原貼地址: How to make "Camera.ScreenToWroldPoint" work on XZ plane?php
題主luwenwan問道:html
public class DragOnPlanXY : MonoBehaviour { void Update() { var screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position); transform.position = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); } }
這個代碼可讓物件隨着鼠標在XZ平面上移動, 可是怎麼能讓物件在XY平面上移動呢?
neginfinity提供了一個使用Vector3.ProjectOnPlane的方法this
using UnityEngine; public class DragByProjectOnPlane : MonoBehaviour { float timer = 0; void Update() { if (timer > 0) { timer--; return; } timer = 120; var screenPoint = Camera.main.WorldToScreenPoint(gameObject.transform.position); var targetTransform = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPoint.z)); Vector3 planePoint = Vector3.zero;//point on the plane Vector3 planeNormal = Vector3.up;//normal vector of the plane transform.position = Vector3.ProjectOnPlane(targetTransform - planePoint, planeNormal) + planePoint; } }
固然他只提供了最後3行代碼, 這個方法問題就是與鏡頭的深度沒法當即得到, 因此能明顯感到物件有一個延時.
這裏加了一個計數器能更清楚地看到這個問題.
exiguous提供了一個使用Plane.RayCast的方法spa
public static class ExtensionMethods_Camera { private static Plane xzPlane = new Plane(Vector3.up, Vector3.zero); public static Vector3 MouseOnPlane(this Camera camera) { // calculates the intersection of a ray through the mouse pointer with a static x/z plane for example for movement etc, // source: http://unifycommunity.com/wiki/index.php?title=Click_To_Move Ray mouseray = camera.ScreenPointToRay(Input.mousePosition); float hitdist = 0.0f; if (xzPlane.Raycast(mouseray, out hitdist)) { // check for the intersection point between ray and plane return mouseray.GetPoint(hitdist); } if (hitdist < -1.0f) { // when point is "behind" plane (hitdist != zero, fe for far away orthographic camera) simply switch sign // https://docs.unity3d.com/ScriptReference/Plane.Raycast.html return mouseray.GetPoint(-hitdist); } // both are parallel or plane is behind camera so write a log and return zero vector Debug.Log("ExtensionMethods_Camera.MouseOnPlane: plane is behind camera or ray is parallel to plane! " + hitdist); return Vector3.zero; } }