首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >三维物体的统一三维四元数旋转透镜

三维物体的统一三维四元数旋转透镜
EN

Stack Overflow用户
提问于 2020-02-21 06:20:32
回答 1查看 518关注 0票数 0

我在做一个团结项目。有一个汽车雨刷,我想旋转它的方式,当我预先“雨刷切换”雨刷开始旋转从0,0, 0 ,0,-45,并开始勒平。但是当我按下“雨刷开关”时,雨刷必须旋转回0,0,0。例如,如果当前的雨刷旋转为0,0,-20,并且我按下“雨刷切换关闭”键,它们必须是rotateTowards 0,0,0。另外,如果我再次按下“雨刷开关”,雨刷必须开始从0,0,0到0,0,-45旋转。现在,情况是雨刷是旋转的,但当我按下“雨刷开关关闭”,雨刷停止在相同的当前旋转点,例如(0,0,-30)。当我再一次按下“雨刷开关”时,雨刷就会从奇怪的不同的旋转点开始。这是我的代码:

代码语言:javascript
运行
复制
using UnityEngine;
using System.Collections;

public class Wipers : MonoBehaviour 
{
    [SerializeField] protected Vector3 m_from = new Vector3(0.0F, 0.0F, 0.0F);
    [SerializeField] protected Vector3 m_to = new Vector3(0.0F, -45.0F, 0.0F);
    [SerializeField] protected float m_frequency = 1.0F;

    protected virtual void Update() 
    {
        if (ControlFreak2.CF2Input.GetAxis ("wipers") != 0) 
        {
            Quaternion from = Quaternion.Euler(this.m_from);
            Quaternion to = Quaternion.Euler(this.m_to);

            float lerp = 0.5F * (1.0F + Mathf.Sin(Mathf.PI * Time.realtimeSinceStartup * this.m_frequency));
            this.transform.localRotation = Quaternion.Lerp(from, to, lerp);     
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-21 07:03:42

  • 打开时的问题是,您直接使用的是Time.realtimeSinceStartup,当然,在关闭例程时,它也继续运行!所以你永远不知道什么时候雨刷会被打开。 →,您更愿意使用的时间,因为雨刷,从哪里开始。
  • 当你关闭时,你的问题当然是你立即停止移动。 →你宁愿总是完成一个完整的循环后,雨刷已关闭。

与其在Update中这样做,我建议使用一个柯鲁丁。与直接在Update中进行操作相比,协同工作更容易控制和维护。实际上,它们就像小的临时更新,像例程一样,在真正的Update完成后立即执行。

一个协同器,你可以让它继续和完成一个完整的周期,直到它实际完成。

在Update中,您将只检查用户输入并启动一个例程(如果没有一个已经在运行),并且该例程可以独立运行和终止一个完整的循环:

代码语言:javascript
运行
复制
[SerializeField] protected Vector3 m_from = new Vector3(0.0F, 0.0F, 0.0F);
[SerializeField] protected Vector3 m_to = new Vector3(0.0F, -45.0F, 0.0F);
[SerializeField] protected float m_frequency = 1.0F;

// TODO only for debugging
[SerializeField] private bool ControlFreak2Dummy;

private bool wipersOn;
private Quaternion from;
private Quaternion to;

private void Awake()
{
    // Store these once -> more efficient then recalculate them everytime
    from = Quaternion.Euler(m_from);
    to = Quaternion.Euler(m_to);
}

protected virtual void Update()
{
    // TODO switch these back
    //if (ControlFreak2.CF2Input.GetAxis ("wipers") != 0)
    if (ControlFreak2Dummy)
    {
         if(!wipersOn)  
         {
            StartCoroutine(Wipers());
         }
    }
}

// To make things easier for us this in itself closed routine is exactly ONE FULL wipers cycle
// so we can determine exactly when a full cycle is done or not
private IEnumerator Wipers()
{
    // block concurrent routines
    wipersOn = true;

    var duration = 1f / m_frequency;
    var timePassed = 0f;

    while (timePassed <= duration)
    {
        // Note: Your sinus factor calculation was a bit strange
        // (or maybe this early I'm way too stupid for maths lol ^^)
        // It was always minimum 0.5 and maximum 1, you rather want to pingpong between 0 and 1
        //
        // This now moves forth and back exactly once between 0 and 1
        var factor = Mathf.Sin(Mathf.PI *  timePassed / duration);

        transform.localRotation = Quaternion.Lerp(from, to, factor);

        // increase timePassed by the time passed since last frame
        timePassed += Time.deltaTime;

        // allows Unity to "pause" here, render this frame and
        // continue from here in the next frame
        yield return null;
    }

    // make sur it really terminates in 0
    transform.localRotation = from;

    // tell others that this routine is done
    wipersOn = false;
}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60333130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档