简体   繁体   English

Unity 3D - 如何全局旋转一个 object 基于秒

[英]Unity 3D - How to gllobaly rotate one object based on second

I have got a very large problem with rotation in Unity.我在 Unity 中遇到了一个非常大的旋转问题。 What I want:我想要的是:

I have two 3D objects.我有两个 3D 对象。 Just one is for player manipulating, second object Transform.rotation and Transform.position is dependent on object number one with scale of 1/10.只有一个用于玩家操作,第二个 object Transform.rotation 和 Transform.position 依赖于 object 第一个,比例为 1/10。 It means if I will move first object from (0,0,0) to (10,30,90) then obj.2 will move from (0,0,0) to (1,3,9).这意味着如果我首先将 object 从 (0,0,0) 移动到 (10,30,90),那么 obj.2 将从 (0,0,0) 移动到 (1,3,9)。 It's simple.这很简单。 But I have got LARGE problem with rotation.但是我在旋转方面遇到了很大的问题。

I can't make rotation on normal transform because it's based on "local position".我无法对正常变换进行旋转,因为它基于“本地位置”。 Below I present my problem with simplest 2D object situation:下面我用最简单的 2D object 情况介绍我的问题:

在此处输入图像描述

As you can see when I rotate red object +90 degrees the second object rotate +9 degrees and the axes become different in relation to the world.正如你所看到的,当我旋转红色 object +90 度时,第二个 object 旋转 +9 度,轴相对于世界变得不同。 After more transformations in 3D world it make a large mess.在 3D 世界中进行更多转换后,它变得一团糟。 For example after some transformations if I will want to rotate 3D object from me (like using accelerator on motocycle) on first make second object rotating from left to right (because it's based on object axis). For example after some transformations if I will want to rotate 3D object from me (like using accelerator on motocycle) on first make second object rotating from left to right (because it's based on object axis).

Of course using Transform.Rotate instead of Transform.localRotate (or Transform.EulerAngles instead of Transform.localEulerAngles) is not a solutions because it's means only if objects are childrens (it this this case are not).当然,使用 Transform.Rotate 代替 Transform.localRotate (或 Transform.EulerAngles 代替 Transform.localEulerAngles)不是一个解决方案,因为它只意味着对象是子对象(这种情况不是)。

WHAT I FOUND:我发现了什么:

Using Transform.Rotate(Xdegree,Ydegree,Zdegree, Space.World) is solution for rotating second object !使用 Transform.Rotate(Xdegree,Ydegree,Zdegree, Space.World) 是旋转第二个 object 的解决方案!

What I need:我需要的:

Xdegree, Ydegree and Zdegree from first (manipulated by player) object. Xdegree、Ydegree 和 Zdegree 从第一个(由玩家操作)object。

Transform.EulerAngles and Transform.Rotation DOESN'T work because it's returns "local objects" rotations. Transform.EulerAngles 和 Transform.Rotation 不起作用,因为它返回“本地对象”旋转。

So... I know that if 3D obj.2 rotation is (0;30;0) and i use obj2.Rotate(45,0,0) then the obj.2 rotation will be (~37.76;~39.23;~26.56) and it's okay.所以...我知道如果 3D obj.2 旋转为 (0;30;0) 并且我使用 obj2.Rotate(45,0,0) 那么 obj.2 旋转将为 (~37.76;~39.23;~ 26.56),没关系。 But I dont know how to convert the other way (from "local" rotation XYZ to degrees that I can use on Transform.Rotate() (of course I will divided this values (xyz) by 10 at the end because I have got 1/10 moving scale))但我不知道如何转换另一种方式(从“本地”旋转 XYZ 到我可以在 Transform.Rotate() 上使用的度数(当然我会在最后将这个值(xyz)除以 10,因为我有 1 /10 移动刻度))

If you need one GameObject to have 1/10 of the rotation and position of another, you could use something like:如果您需要一个游戏对象具有 1/10 的旋转和 position 的另一个,您可以使用类似的东西:

//the player-controlled cube
public Transform t1;
//the 1/10 cube
public Transform t2;

void Update(){
    //set the position of t2 to 1/10 of the position of t1
    t2.position = 0.1f * t1.position;
    //get the axis and angle of t1's rotation
    t1.rotation.ToAngleAxis(out float angle, out Vector3 axis);
    //t2 should be rotated in the same direction (axis), but with 1/10th of the angle
    t2.rotation = Quaternion.AngleAxis(angle * 0.1f, axis);
}

Edit: To allow resetting delta rotation and changing targets, you could do something like this.编辑:要允许重置增量旋转和更改目标,您可以执行以下操作。 Note: this glitches when it wraps more than a full circle, I'm not an expert on Quaternions so you'd have to figure it out yourself.注意:当它超过一个完整的圆圈时会出现故障,我不是四元数方面的专家,所以你必须自己弄清楚。

    //the player-controlled cube
    public Transform t1;
    //the 1/10 cube
    public Transform t2;
    private Vector3 t1originalPosition;
    private Quaternion t1originalRotation;
    private Vector3 t2originalPosition;
    private Quaternion t2originalRotation;

    void Start()
    {
        ResetTarget(t1);
    }

    void Update()
    {
        if (t1 != null)
        {
            //set the position of t2 to 1/10 of the position of t1
            t2.position = t2originalPosition + 0.1f * (t1.position - t1originalPosition);

            Quaternion t1Rotation = t1.rotation * Quaternion.Inverse(t1originalRotation);
            //get the axis and angle of t1's rotation
            t1Rotation.ToAngleAxis(out float angle, out Vector3 axis);

            //t2 should be rotated in the same direction (axis), but with 1/10th of the angle
            t2.rotation = Quaternion.AngleAxis(angle * 0.1f, axis) * t2originalRotation;
        }
        
    }

    public void ResetTarget(Transform target = null)
    {
        t2originalPosition = t2.position;
        t2originalRotation = t2.rotation;

        t1 = target;
        t1originalPosition = t1.position;
        t1originalRotation = t1.rotation;
    }

Use quaternions instead of the euler angles (xyz rotation angles).使用四元数而不是欧拉角(xyz 旋转角)。 And simply give the global rotation value (quaternion) of one object to the other.并简单地将一个 object 的全局旋转值(四元数)给另一个。 To add together quaternions, you just multiply them together.要将四元数相加,只需将它们相乘即可。

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

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