简体   繁体   English

unity - 围绕 Y 轴旋转 object,同时不断设置不同的朝向地面的旋转

[英]Unity - rotating object around Y axis, while constantly setting up different rotation towards the ground

so i don't know if i explained it properly in the title, but what i'm trying to do is by clicking Q or E rotate object around the Y axis, but at the same time i'm raycasting to the ground to check the point rotation to face it in to the right direction.所以我不知道我是否在标题中正确解释了它,但我想做的是通过单击 Q 或 E 绕 Y 轴旋转 object,但同时我正在向地面投射光线以检查点旋转以使其朝向正确的方向。

To clarify this, here is an example: I'm trying to place the fireplace, i'm on the hill.为了澄清这一点,这里有一个例子:我正在尝试放置壁炉,我在山上。 To prevent the fireplace go into the terrain, i need to rotate it so that i would "stick" to the terrain by it's bottom, but then i want to rotate it around the Y a couple of degrees.. Here is the code that i've got:为了防止壁炉 go 进入地形,我需要旋转它,这样我才能通过它的底部“粘”在地形上,但是我想将它围绕 Y 旋转几度。这是我的代码有:

using UnityEngine;

public class Foobar : MonoBehaviour
{
    Transform cam;
    Transform prefabAsTransform;
    Vector3 currentPos;
    float addToY = 0.5f;
    int mask;

    void Start()
    {
        cam = Camera.main.transform;
        prefabAsTransform = transform;
        mask = LayerMask.GetMask("Default");
    }

    void Update()
    {
        RaycastHit hit;
        if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
        {
            currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
            prefabAsTransform.position = currentPos;
            prefabAsTransform.transform.up = hit.normal;
        }

        if (prefabAsTransform != null)
        {
            if (Input.GetKeyDown(KeyCode.Q))
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    prefabAsTransform.Rotate(new Vector3(0, 1, 0));
                }
                else
                {
                    prefabAsTransform.Rotate(new Vector3(0, 10, 0));
                }
            }
            if (Input.GetKeyDown(KeyCode.E))
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    prefabAsTransform.Rotate(new Vector3(0, -1, 0));
                }
                else
                {
                    prefabAsTransform.Rotate(new Vector3(0, -10, 0));
                }
            }
        }
    }
}

The problem here is that it's facing the terrain without any issues, but i'm unable to rotate it around Y by myself.这里的问题是它面对地形没有任何问题,但我无法自己围绕 Y 旋转它。 I assume that's due to the fact, that i'm constantly updating the rotation, but i have no idea how to change that.我认为这是因为我不断更新轮换,但我不知道如何改变它。

Yes, it's because you are setting the rotation every frame with prefabAsTransform.transform.up = hit.normal;是的,这是因为您使用prefabAsTransform.transform.up = hit.normal;设置每一帧的旋转。 and not taking the current forward direction into account.并且不考虑当前的前进方向。

Instead, you should use prefabAsTransform.rotation = LookRotation(newForward, newUp);相反,您应该使用prefabAsTransform.rotation = LookRotation(newForward, newUp); But, how can you use the current forward to determine newForward ?但是,如何使用当前 forward 来确定newForward You can use cross products for that.您可以为此使用交叉产品。 This worked for me:这对我有用:

void Update()
{
    RaycastHit hit;
    if (Physics.Raycast(cam.position, cam.forward, out hit, Mathf.Infinity, mask))
    {
        currentPos = new Vector3(hit.point.x, hit.point.y + addToY, hit.point.z);
        prefabAsTransform.position = currentPos;

        Vector3 newUp = hit.normal;
        Vector3 oldForward = prefabAsTransform.forward;

        Vector3 newRight = Vector3.Cross(newUp, oldForward);
        Vector3 newForward = Vector3.Cross(newRight, newUp);

        prefabAsTransform.rotation = Quaternion.LookRotation(newForward, newUp);
    }

    if (prefabAsTransform != null)
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            if (Input.GetKey(KeyCode.LeftControl))
            {
                prefabAsTransform.Rotate(new Vector3(0, 1, 0));
            }
            else
            {
                prefabAsTransform.Rotate(new Vector3(0, 10, 0));
            }
        }
        if (Input.GetKeyDown(KeyCode.E))
        {
            if (Input.GetKey(KeyCode.LeftControl))
            {
                prefabAsTransform.Rotate(new Vector3(0, -1, 0));
            }
            else
            {
                prefabAsTransform.Rotate(new Vector3(0, -10, 0));
            }
        }
    }
}

代码工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM