【问题标题】:Rotate towards the mouse朝鼠标方向旋转
【发布时间】:2017-05-31 21:43:57
【问题描述】:

我想将一个立方体旋转到统一的鼠标位置(2d 中)(c#)。我有这个代码,但我不工作:

Vector3 a = GameObject.FindGameObjectWithTag("GunTop").transform.position;
Vector3 b = GameObject.FindGameObjectWithTag("GunBottom").transform.position;
Vector3 c = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x);
float aTob = Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, GameObject.FindGameObjectWithTag("GunBottom").transform.position);
float aToc = Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x));
float bToc = Vector3.Distance(GameObject.FindGameObjectWithTag("GunBottom").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x));

float winkel = Mathf.Acos(((Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, GameObject.FindGameObjectWithTag("GunBottom").transform.position) * Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, GameObject.FindGameObjectWithTag("GunBottom").transform.position)) + (Vector3.Distance(GameObject.FindGameObjectWithTag("GunBottom").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x)) * Vector3.Distance(GameObject.FindGameObjectWithTag("GunBottom").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x))) - (Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x)) * Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x)))) / (2 * Vector3.Distance(GameObject.FindGameObjectWithTag("GunTop").transform.position, GameObject.FindGameObjectWithTag("GunBottom").transform.position) * Vector3.Distance(GameObject.FindGameObjectWithTag("GunBottom").transform.position, new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.x))));

private void Update()
{
    transform.Rotate(0, 0, winkel);
}

GunTop 和 GunBottom 是立方体中间的最高点和最低点,用鼠标创建一个三角形。有人看到问题了吗?

编辑1: 好的,好消息。现在我必须找到解决问题的方法。第一个像 memBrain 悲伤(我改变了一点):

`    private void Update()
{
    Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
    Vector3 dir = Input.mousePosition - pos;
    float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    transform.rotation = Quaternion.Euler(0, 0, angle - 90);
}`

为了统一工作,我不得不对其进行一些更改。第二种解决方案,我可以优化我的代码,所以它现在可以工作了:

`   float winkel;
float echterWinkel;
float aTob;
float aToc;
float bToc;
private void Update()
{
    Vector3 a = 
GameObject.FindGameObjectWithTag("GunTop").transform.position;
    Vector3 b = 
GameObject.FindGameObjectWithTag("GunBottom").transform.position;
    Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
    Vector3 dir = Input.mousePosition - pos;
    aTob = Vector3.Distance(a, b);
    aToc = Vector3.Distance(a, dir);
    bToc = Vector3.Distance(b, dir);
    winkel = Mathf.Acos(((aTob * aTob) + (bToc * bToc) - (aToc * aToc)) / (2 
  * aTob * bToc));
    echterWinkel = Mathf.Rad2Deg * winkel;
    if (dir.x < 0)
    {
        transform.rotation = Quaternion.Euler(0, 0, echterWinkel);
    }
    else
    {
        transform.rotation = Quaternion.Euler(0, 0, -echterWinkel);
    }
   }
 }`

好的,到目前为止一切顺利。但我现在必须提出问题。显然第一个解决方案更好,所以我想知道它是如何工作的,“Mathf.Atan2()”是什么?

现在是第二个问题:我为什么要这样做

   `Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
    Vector3 dir = Input.mousePosition - pos;`

为了得到真正的鼠标位置?

【问题讨论】:

  • Input.mousePosition 在屏幕空间中吗?如果是这样,那么这至少是问题的一部分。
  • 是的,我以为这是一部分,我怎样才能获得鼠标位置?

标签: c# unity3d rotation


【解决方案1】:

您的代码对我来说似乎是不必要的复杂。您需要所有这些向量是否有特殊原因?不过,以下代码是来自 Unity 论坛 (http://answers.unity3d.com/questions/731922/rotate-object-to-face-mouse-2d-rotate-on-z-axis.html) 的示例,您可以使用它来围绕 z 轴旋转对象。

Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
Vector3 dir = Input.mousePosition - pos;
float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);

就这么简单。

编辑:请记住,变换将是目标游戏对象的变换。

附带说明,您的示例中的无效代码效率相当低。您已经声明了不使用的向量和不使用的浮点数。因此,您可以使用这些存储的值替换很多代码。

Vector3 a = GameObject.FindGameObjectWithTag("GunTop").transform.position;
Vector3 b = GameObject.FindGameObjectWithTag("GunBottom").transform.position;
Vector3 c = new Vector3 (
    Input.mousePosition.x, 
    Input.mousePosition.y, 
    Input.mousePosition.x
);
float aTob = Vector3.Distance(a, b);
float aToc = Vector3.Distance(a, c);
float bToc = Vector3.Distance(b, c);

float winkel = Mathf.Acos (
    (
        (
            aTob * aTob
        ) + 
        (
            bToc * bToc
        ) -
        (
            aToc * aToc
        )
    ) / 
    (
        2 * aTob * bToc
    )
);

private void Update()
{
    transform.Rotate(0, 0, winkel);
}

请注意,在正确使用存储值之后,代码现在看起来多么简单。我还冒昧地使用花括号之类的括号来使长行代码更具可读性。你需要记住一件事。查找可能很昂贵。如果不需要,切勿多次查找。

我没有费心检查代码是否正确。我什至无法验证您的查找是否会返回一个值。事实上,这可能会成为这段代码的一个问题。如果任一查找失败,您将在 a 或 b 或两者中存储空值!您需要某种条件检查来验证 a 和 b 是否进行了成功的查找,以及如果没有找到该怎么办。就目前而言,当您第一次尝试对 a 或 b 执行操作时,您将遇到失败。目标是优雅地失败,而不是强行失败。

编辑 2:再次查看所有内容,我注意到另一个问题。您的意图是围绕 z 轴旋转,并将 z 坐标设置为 Input.mousePosition.x。这是错误的。您应该将其设置为固定值,例如“0”。您不希望 z 绑定到 x。

编辑 3:Here is the information provided by the Unity Scripting API for Mathf.Atan2(...)。

是的。这两行与获取鼠标位置有关。让我解释一下这里发生了什么。

Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);

这条线将你的“枪”对象的世界坐标(transform.position)转换为屏幕点坐标并将其存储在pos中。

Vector3 dir = Input.mousePosition - pos;

这一行获取 mousePosition 向量并从中减去之前的位置向量 (pos),并将其存储在 dir 中(可能是“方向”)。您可以像下面这样轻松更改 Vector3 c:

Vector3 c = Input.mousePosition;

这相当于您所做的,无需创建新的 Vector3 并像您所做的那样明确地为其分配矢量坐标。

float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

此行替换了 winkel。因此,您的整个代码可以压缩如下:

GameObject gun;

void Start()
{
    /*
        initialization code for gun GameObject
    */
}

void Update()
{
    Vector3 gunScreenPosition = Camera.main.WorldToScreenPoint(gun.transform.position);
    Vector3 mouseDirection = Input.mousePosition - gunScreenPosition;
    float angle = Mathf.Atan2(mouseDirection.y, mouseDirection.x) * Mathf.Rad2Deg;
    gun.transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}

您真的不需要您使用的所有额外代码。您需要 GunTop 和 GunBottom 有什么特别的原因吗?如果只是计算枪的位置,我的例子就足够了。

如果我没有再分享一件事,我就会失职。使用 Quaternion.Euler(...) 时要小心。它可能会遭受称为“gimbal lock”的情况

【讨论】:

  • 哇,谢谢,这很有帮助。我想使用存储的值,但统一不允许它,所以我采用了未存储的值。我需要向量来创建一个三角形并使用 arcos 来获得角度。我会尝试你的代码,我会尝试正确地编写我的代码。非常感谢你:)
  • 不客气。如果您需要任何进一步的帮助,请告诉我。
  • @Gmunderos7,我提供了 Unity 网站上 MathF.Atan2 文档的链接。我还复制了您的“答案”作为对您原始帖子的编辑(等待审核)。据我了解,您最好扩展您的原始帖子而不是添加新答案。因此,我建议在我的编辑经过审核后删除您的帖子。
  • 好的,谢谢。所以第一行我需要将gun.Position从世界空间转换为屏幕空间,然后我可以减去枪位置以获得相对于枪位置的鼠标位置,这是正确的吗?而且我需要转换枪位才能减去它,对吗?是否也可以将鼠标位置转换为世界空间以进行减法?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多