简体   繁体   English

如何使用协程将子对象旋转到某个角度时旋转父对象

[英]How to rotate a parent object while rotating a child object to a certain angle using coroutines

I have a semicircle like game object which I made by putting two arcs in an empty game object (SCircle) and rotating the 15° (for left arc) and -15° (for right arc) as seen below. 我有一个半圆形的游戏对象,我通过在空游戏对象(SCircle)中放置两个弧并旋转15°(对于左弧)和-15°(对于右弧)来制作,如下所示。

在此输入图像描述

SCircle has an Orientation enum with two values Left (rotates SCircle to 45°) and Right (rotates SCircle to -45°) as seen in the image below. SCircle有一个Orientation枚举,其中有两个值Left (旋转SCircle到45°)和Right (旋转SCircle到-45°),如下图所示。

在此输入图像描述

I use the following coroutine to move SCircle between orientations. 我使用以下协同程序在方向之间移动SCircle

IEnumerator RotateLeftOrRight(Vector3 byAngles, float inTime)
{
   Quaternion fromAngle = gameObject.transform.rotation ;
   Quaternion toAngle = Quaternion.Euler (transform.eulerAngles);


   if (circOrientation == Orientation.Left) {
       toAngle = Quaternion.Euler (gameObject.transform.eulerAngles - byAngles);
       circOrientation = Orientation.Right;

   }
   else if (circOrientation == Orientation.Right) {

       toAngle = Quaternion.Euler (gameObject.transform.eulerAngles + byAngles);
       circOrientation = Orientation.Left;
   }


   for(float t = 0f ; t <= 1f ; t += Time.deltaTime/inTime)
   {
       gameObject.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t) ;
       yield return null ;

   }
    gameObject.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, 1);
}  

I also used a very similar coroutine to move the individual arcs by 30° (in opposite directions) from say, Orientation Left , as seen below in the coroutine and image: 我还使用一个非常相似的协程将单个弧线移动30°(相反方向),例如, Left方向,如下图所示,在协程和图像中:

IEnumerator RotateArc(GameObject arcGO, Vector3 byAngles, float inTime)
{
    Quaternion fromAngle = arcGO.transform.rotation ;
    Quaternion toAngle = Quaternion.Euler (arcGO.transform.eulerAngles);

    if (rightArc.arcOrientation == Arc.Orientation.Down) {
        toAngle = Quaternion.Euler (arcGO.transform.eulerAngles + byAngles);
        rightArc.arcOrientation = Arc.Orientation.Up;

    }
    else if (rightArc.arcOrientation == Arc.Orientation.Down) {

        toAngle = Quaternion.Euler (arcGO.transform.eulerAngles - byAngles);
        rightArc.arcOrientation = Arc.Orientation.Up;
    }


    for(float t = 0f ; t <= 1f ; t += Time.deltaTime/inTime)
    {
        arcGO.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, t) ;
        yield return null ;

    }
    arcGO.transform.rotation = Quaternion.Lerp(fromAngle, toAngle, 1);

}

在此输入图像描述

Since SCircle Coroutine is activated by a mouse click, I have the case where the individual arcs coroutine is run and before it is complete the parent SCircle coroutine is also run. 由于通过鼠标单击激活了SCircle Coroutine,因此我将运行单个arcs coroutine并且在完成之前还运行父SCircle协程。 In this case the arcs end up moving from Left to A, which is not the behavior I need. 在这种情况下,弧线最终Left移动到A,这不是我需要的行为。 I would want the behavior of them ending up at B when moving from the Left . 我希望他们的行为在从Left移动时最终在B处结束。 Likewise, from B, when the SCircle coroutine is run while the arcs coroutine is in progress the orientation will return to the Left . 同样,从B开始,当弧形协程正在进行时运行SCircle协程时,方向将返回到Left

Please note that the blue arrow represents the movement of the left Arc, the red represents the right Arc and the black represents movement of SCircle - the parent object. 请注意,蓝色箭头表示左弧的移动,红色表示右弧,黑色表示SCircle移动 - 父对象。

在此输入图像描述

I believe the issue you're having is caused by the fact that as you rotate the individual arcs, what they're rotating around is also rotating itself. 我相信你所遇到的问题是由于当你旋转各个弧时,它们旋转的东西也在旋转。

In other words, your SCircle's axes are rotating, and your arcs are using those same axes to determine their own rotations. 换句话说,您的SCircle轴正在旋转,并且您的弧正在使用相同的轴来确定它们自己的旋转。 So if you look at your example A, you tell it to rotate in world space by -90, then immediately tell to rotate in world space by 30. To solve this, you want to get the arcs to rotate locally, not in world space. 因此,如果你看看你的例子A,你告诉它在世界空间中旋转-90,然后立即告诉世界空间旋转30点。为了解决这个问题,你想让弧线在本地旋转,而不是在世界空间。

I think you can solve this by setting up this structure: 我想你可以通过设置这个结构来解决这个问题:

Empty GameObject SCircle 空GameObject SCircle

------Empty gameObject BlueArcCenter -> position 0,0,0 ------清空gameObject BlueArcCenter - >位置0,0,0

-----------blue arc -> change position here to make it offset from zero ex:(radius, 0, 0) -----------蓝色弧 - >在此处更改位置以使其偏离零ex:(radius,0,0)

------Empty gameObject RedArcCenter -> position (0,0,0) ------空游戏对象RedArcCenter - >位置(0,0,0)

-----------red arc -> change position here to make it offset from zero ex:(-radius, 0, 0) -----------红色弧 - >在这里改变位置使其偏离零ex:( - radius,0,0)

Now alter your code so that: 现在改变你的代码,以便:

To rotate the blue and red arcs individually you rotate their arcCenters, 要单独旋转蓝色和红色圆弧,请旋转它们的arcCenters,

To rotate the whole configuration, rotate SCircle. 要旋转整个配置,请旋转SCircle。 This will in turn rotate both ArcCenters, which will in turn rotate both the arcs irrespective of how they are oriented relative to each other, or whether they are rotating themselves. 这将反过来旋转两个ArcCenters,它们将反过来旋转两个弧,而不管它们相对于彼此的方向如何,或者它们是否自己旋转。

Note: Also, I've read that people are using Quaternions a lot less these days since they don't really make sense when you read the code. 注意:此外,我已经读过人们现在使用Quaternions要少得多,因为当你阅读代码时他们没有意义。 You might want to change your code to normal rotations to make it more readable. 您可能希望将代码更改为正常旋转,以使其更具可读性。

If you have the setup listed above, use something like: 如果您有上面列出的设置,请使用以下内容:

to spin circle: 旋转圆圈:

thisSCircle.transform.Rotate(0, -90, 0, Space.Self);

to rotate arcs around their common center: 围绕公共中心旋转弧线:

blueArcCenter.transform.Rotate(0, -30, 0, Space.Self)
redArcCemter.transform.Rotate(0, 30, 0, Space.Self)

(you'd need to add lerps in and stuff but this should get you started). (你需要添加lerps和东西,但这应该让你开始)。

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

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