首页 > 解决方案 > Quaternion.RotateTowards 期间圆柱体对齐到位

问题描述

我想要做的是在场景的中心有一个支柱,我认为正在发生的是四元数。RotateTowards 接收的起始/初始四元数与导致它捕捉/传送到不同的动作的动作不同然后开始移动到下一个位置。我想这可能是因为我误解了四元数是如何统一处理的,所以我试着把它标准化,但我似乎无法在瞬移上得到任何改变。

我们的目标是将这个脚本附加到一个简单的 3D 圆柱体上并让它基本上摆动,在那里会有一个玩家在它上面试图停留在上面。但是我似乎无法弄清楚它为什么会传送并希望有第二双眼睛。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlatformWobble : MonoBehaviour
{
    public float timeDelay = 0;
    public float rRange = 0.5f;
    public float maxRotation = 20.0f;
    public float rotRate = 0.05f;

    private bool wobble = false;
    private Vector3 randomRotation;
    private Quaternion rotation;
    private Quaternion destination;
    private float x, y, z;
    private bool inPlace;

    private void Start()
    {
        randomRotation = new Vector3();
        inPlace = true;
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        if (inPlace)
        {
            destination = RotateRandomly();
            inPlace = false;
        }

        transform.localRotation = Quaternion.RotateTowards(transform.localRotation, destination, rotRate * Time.deltaTime);
        
        if (transform.localRotation == destination)
        {
            inPlace = true;
        }
    }

    //This will grab the rotation of the object and move it randomly, but won't exceed maxRotation;
    Quaternion RotateRandomly()
    {
        randomRotation = new Vector3(Random.Range(-rRange, rRange), Random.Range(-rRange, rRange), Random.Range(-rRange, rRange));
        rotation = transform.localRotation;

        x = rotation.x + randomRotation.x;
        if(x >= maxRotation && x <= 360 - maxRotation) { x = rotation.x; }

        y = rotation.y + randomRotation.y;
        if (y >= maxRotation && y <= 360 - maxRotation) { y = rotation.y; }

        z = rotation.z + randomRotation.z;
        if (z >= maxRotation && z <= 360-maxRotation) { z = rotation.z; }

        return new Quaternion(x, y, z, transform.localRotation.w);
    }
}

标签: c#unity3d

解决方案


FixedUpdate不会在每个渲染帧上调用,仅在物理帧上调用。您需要一种方法来告诉 Unity 让每个帧都显示旋转变化,而不是仅在物理帧刚刚运行时更新渲染。

这就是Rigidbody.MoveRotation目的。缓存对 的引用Rigidbody,计算它应该具有的新全局旋转,然后调用MoveRotation

    private Rigidbody rb;

    private void Start()
    {
        randomRotation = new Vector3();
        inPlace = true;
        rb = GetComponent<Rigidbody>();
    }

    // ...
   
    // Update is called once per frame
    void FixedUpdate()
    {
        if (inPlace)
        {
            destination = RotateRandomly();
            inPlace = false;
        }

        Quaternion newLocalRot = Quaternion.RotateTowards(transform.localRotation, 
                destination, rotRate * Time.deltaTime);

        Quaternion newGlobalRot = transform.parent.rotation * newLocalRot;

        rb.MoveRotation(newGlobalRot);
        
        if (transform.localRotation == destination)
        {
            inPlace = true;
        }
    }

推荐阅读