如何旋转游戏对象以匹配球体上的法线

问题描述 投票:0回答:1

我正在尝试旋转游戏对象以匹配球体上的法线射线,但它会奇怪地围绕它旋转并在越过两极时翻转。为什么会发生这种情况,我该如何解决?

Expected behaviour Actual behaviour

using UnityEngine;

public class Test : MonoBehaviour {

    [SerializeField] private Transform objectToFollow;

    private Camera mainCamera;
    private int layerMask;

    private void Awake() {
        mainCamera = Camera.main;
        layerMask = ~(1 << objectToFollow.gameObject.layer);
    }

    private void Update() {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask)) {
            Vector3 objectSize = objectToFollow.GetComponent<Renderer>().bounds.extents;
            Vector3 newPosition = hit.point + Vector3.Scale(hit.normal, objectSize);

            objectToFollow.position = newPosition;

            objectToFollow.up = hit.normal;
        }
    }
}

我尝试使用 Quaternion.LookRotation 但它只会让事情变得更糟并且对象在球体表面上方偏移

c# unity3d quaternions
1个回答
0
投票

你的游戏对象在你越过两极时奇怪地旋转和翻转的原因是因为 Unity 的四元数旋转的工作方式。当您调整游戏对象的向上矢量时,Unity 会尝试将游戏对象的前向矢量与新的向上矢量对齐,同时保持对象的旋转尽可能接近之前的旋转。当试图在北极或南极附近设置向上矢量时,这会导致问题,而前向矢量可以指向任何方向。

要解决这个问题,可以使用Quaternion.LookRotation 来设置游戏对象的旋转,而不是直接设置up vector。下面介绍如何自定义脚本以使用 Quaternion.LookRotation:

    using UnityEngine;

public class Test : MonoBehaviour {

    [SerializeField] private Transform objectToFollow;

    private Camera mainCamera;
    private int layerMask;

    private void Awake() {
        mainCamera = Camera.main;
        layerMask = ~(1 << objectToFollow.gameObject.layer);
    }

    private void Update() {
        Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask)) {
            Vector3 objectSize = objectToFollow.GetComponent<Renderer>().bounds.extents;
            Vector3 newPosition = hit.point + Vector3.Scale(hit.normal, objectSize);

            objectToFollow.position = newPosition;

            // Calculate the new rotation
            Quaternion newRotation = Quaternion.LookRotation(hit.normal, objectToFollow.up);
            objectToFollow.rotation = newRotation;
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.