unity3d 如何在C#中示例化鼠标所在位置的Unity预置?

snz8szmq  于 2023-01-05  发布在  C#
关注(0)|答案(1)|浏览(150)

我尝试在点击光标位置时示例化我的 * ballPrefab *。我知道Input.mousePosition只接受x和y坐标。但是,我的摄像头看的是x(全局)(as you can see here)的方向。所以我将x改为0。问题是,无论我在哪里左键点击,每次都在相同的y和z位置生成预制件。
这是我的准则。

[SerializeField]
private GameObject ballPrefab;

void Update()
{
    Vector3 mousePos = Input.mousePosition;
    mousePos = Camera.main.ScreenToWorldPoint(mousePos);
    mousePos.x = 0;

    if (Input.GetButtonDown("Fire1"))
    {
        Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
    }
}

我在网上搜索了一个小时。
我遇到的是Cursor.Position,它似乎是旧的(?),因为System.Windows.Forms不存在。
我还尝试将鼠标位置设置为new Point,但无法将其转换为Vector3。
我还想到了transform.localPosition,因为我的相机面向"错误"的方向,但如果我使用Input.mousePosition,我无法应用变换。
最后,我读到了光线投射,但我并不真正理解它们。

hpcdzsge

hpcdzsge1#

要理解这个问题,最好先了解ScreenToWorldPoint是如何工作的。闭上一只眼睛,直视前方,不要移动眼睛(就像一个2D相机)。然后伸出你的一只手臂,把你的食指放在你视野范围内的某个东西上(就像鼠标指针一样),但不要移动眼睛或直视它。ScreenToWorldPoint函数的工作原理是记录手指在眼睛视图的X轴和Y轴上的位置,但它也需要知道你在Z轴(深度)上伸出手臂和手指有多远,才能让你的手指与你所指的东西对齐。
问题是Input.mousePosition将返回Vector3,其中Z轴(深度)为0,也就是说你传给ScreenToWorldPoint的时候,它基本上不知道你的胳膊和手指伸了多远,就像把你的手指直接放在你的眼球上,但是添加很少的X或Y,这样手指仍然指向你的物体。你会得到非常小的X和Y值,而Z值将在你的眼球(相机)所在的任何地方。
另一个问题是,你手动将结果X值设置为0,所以X值将始终为0,Z值将始终位于相机的Z位置,Y值将非常小,这一切都是因为没有向ScreenToWorldPoint函数传递深度值,这将导致ballPrefab在世界上的最终位置始终大致相同。
所以试着给予它一个像这样的深度参考:

public float distanceFromCamera = 5f;
public GameObject ballPrefab;

void Update()
{      
    if (Input.GetButtonDown("Fire1"))
    {
        Vector3 mousePos = Input.mousePosition;
        mousePos = Camera.main.ScreenToWorldPoint(
                       new Vector3(mousePos.x, mousePos.y, distanceFromCamera));
        Instantiate(ballPrefab, mousePos, ballPrefab.transform.rotation);
    }     
}

似乎您希望球始终位于世界的X轴上,因此另一种解决方案是使用摄影机X位置的绝对值(基本上是摄影机与X轴的距离)作为深度值。

mousePos = Camera.main.ScreenToWorldPoint(
              new Vector3(mousePos.x, mousePos.y,
                Mathf.Abs(Camera.main.transform.position.x)));

这将允许您在无需调整任何distanceFromCamera变量的情况下移入和移出相机(在您的情况下是沿着X轴)。

相关问题