【问题标题】:How to use RotateAround to achieve different speed zones by angle如何使用RotateAround按角度实现不同的速度区
【发布时间】:2020-03-17 16:42:12
【问题描述】:

我正在尝试围绕某个对象旋转相机。 另外,在旋转的某些特定部分,以及在某个角度,移动应该是缓慢的

图示如下,绿色区域是慢动作区域,红色区域是应用的正常速度:

为此,我使用Transform.RotateAround(Vector3 point, Vector3 axis, float angle) 方法

所以,猜测慢速是原速度的一半,而 angleOfSlowMotionZone 是 90º,如图所示,我这样做:

  • 计算相机到达慢区(绿色)所需的时间,即:

    timeToArriveToSlowZone = (270 - (angleOfSlowMotionZone / 2)) / speed;

  • 计算结束慢区所需的时间:

    timeToEndSlowZone = angleOfSlowMotionZone / slowSpeed;

  • 最后计算完成整个TurnAround的时间:

    timeToFullTurn = timeToArriveToSlowZone + timeToEndSlowZone;

然后我调用一个协程来做这样的动作:

IEnumerator Rotation()
{
    second = 0;
    while(true)
    {
        second += Time.deltaTime;
        if(second >= timeToFullTurn)            
            second = 0;                
        newSpeed = (second <= timeToArriveToSlowZone || second >= timeToArriveToSlowZone + timeToEndSlowZone) ? speed : slowSpeed;            
        transform.RotateAround(targetGO.transform.position, Vector3.up, newSpeed * Time.deltaTime);
        yield return null;
    }
}

我的问题是,每转一圈,放慢动作的那一刻都有些不同。我怎样才能将其修正为 EXACTLY 作为建议的角度?

【问题讨论】:

    标签: c# unity3d rotation


    【解决方案1】:

    您的代码在超过 360 度时有问题处理,它被设置为 0 而不是大于 0 的适当数量。此外,您假设基于框架部分的整个框架的旋转速度应该相同开始,而不是依赖于该部分更改的早晚时间。

    我会为此使用嵌套的 while 循环,这也将说明速度是否足够快或 deltaTime 是否足够大以在同一帧中多次更改部分。 cmets中的解释:

    IEnumerator Rotation(float startAngle)
    {
        // parameters - could be fields
        float baseMoveSpeed = 90f;
        float slowMoveSpeed = 45f;
        float slowMoveAngle = 90f;
    
        float angleAtStartOfFrame = startAngle;
    
        while(true)
        {
            float timeLeft = Time.deltaTime;
            float newAngle = angleAtStartOfFrame;
    
            // Travel through sections until time this frame is accounted for
            while (timeLeft > 0)
            {
                float speed;
                float curRegionRemaining;
    
                // assume slow move region is from newAngle=0 to newAngle=slowMoveAngle
                if (newAngle < slowMoveAngle)
                {
                    speed = slowMoveSpeed;
                    curRegionRemaining = slowMoveAngle - newAngle;
                } 
                else
                {
                    speed = baseMoveSpeed;
                    curRegionRemaining = 360f - newAngle;
                }
    
                // travel to end of current region or as much as you can 
                // travel with remaining time
                float angleTraveledThisSection = Mathf.Min(timeLeft * speed,
                        curRegionRemaining);
    
                // how much time did that use?
                float timeUsedThisSection = angleTraveledThisSection / speed;
    
                // how much time is left to travel this frame?
                timeLeft -= timeUsedThisSection;
    
                // sum up how much travel has done
                newAngle = Mathf.Repeat(newAngle + angleTraveledThisSection, 360f);
            }
    
            transform.RotateAround(targetGO.transform.position, Vector3.up, 
                    newAngle - angleAtStartOfFrame);
    
            angleAtStartOfFrame = newAngle;
            yield return null;
        }
    }
    

    【讨论】:

    • 哇,Ruzihm,你总是拯救我的一天!它确实有效(我现在只编辑一个拼写错误),但一切都很完美。我的问题是我真的不明白为什么要使用这种方法。如果我不正确,请纠正我,你想说因为我的 >= 检查不准确,我每轮都带着那个错误,对吧?我的问题是我不明白你的代码是如何解决它的。
    • 那部分是你正在做的second += Time.deltaTime; if(second &gt;= timeToFullTurn) second = 0; 。假设deltaTime0.02second 在此代码运行之前是359.9999。之后,second 应该0更接近0.02。但是您的代码使它成为0,忽略它已经与360 有多接近。我也不确定您为什么使用timeToArriveToSlowZone = (270 - (angleOfSlowMotionZone / 2)) / speed; 而不是timeToArriveToSlowZone = (360 - angleOfSlowMotionZone) / speed;,但我决定避免使用这种数学方法。
    • 好吧,原来是这个携带问题。在我的原始代码上会采用类似的方法:if (second &gt;= timeToFullTurn) second = timeToFullTurn - second; 吗?还是我错过了什么?
    • 不,那会走错方向,给你的东西更像359.8。您可以改为使用second = second + Time.deltaTime; if (second &gt;= timeToFullturn) second = second - timeToFullTurn;second += Time.deltaTime; if (second &gt;= timeToFullturn) second -= timeToFullTurn; 或最简单的second = Mathf.Repeat(second + Time.deltaTime, timeToFullTurn);,这与我所做的类似。我在角度而不是时间上使用了Repeat,但概念是相似的。
    • 哦,我的大脑,当然,我交换了值,谢谢,我从你的回答中学到了很多东西!而且我已经计算出这样的奇怪原因,因为我在想如果 angleOfSlowMotion 从例如 225º 开始,并且他的弧度是 90º,360-90 != 225。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 2023-03-10
    • 2012-08-16
    • 2018-11-19
    • 1970-01-01
    • 2023-03-16
    • 2012-03-14
    相关资源
    最近更新 更多