[Solved] XYZ rotation to <Transform>().EulerAngles give bad result

Hi,

I added new cameras in my game. But I have encounter a problem with rotation, the result is not alway the same as in Blender. I tried lot of ideas but today I do not have anymore.

An example will explain it better. Below, my scene in Blender.
This problem appears if camera orientation is “vertical” (orange color).

Cameras 1, 2, 4 : good rotation in Unity
Cameras 3, 5 : bad rotation in Unity

Cam 1 (Blender):

Cam 1 (Unity): the fov is different

Cam 2 (Blender):

Cam 2 (Unity): the fov is different

Cam 3 (Blender):

Cam 3 (Unity): rotation is bad

Cam 4 (Blender):

Cam 4 (Unity): the fov is different

Cam 5 (Blender):

Cam 5 (Unity): rotation is bad

I hope these images help you unterstand, you have may be already encounter this problem. Do you have a turn arround, a solution for me?

My code :

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

public class rotation_cams : MonoBehaviour
{
    private Vector3[] cams_loc;
    private Vector3[] cams_rot;

    // Start is called before the first frame update
    void Start()
    {
        cams_loc = new Vector3[5];
        cams_rot = new Vector3[5];

        cams_loc[0] = new Vector3(79.7771f, 21.7574f, 109.795f);
        cams_rot[0] = new Vector3(95f, -45f, -200f);

        cams_loc[1] = new Vector3(78.0048f, 21.9854f, 110.314f);
        cams_rot[1] = new Vector3(87.0958f, 1.34464f, -160.515f);

        cams_loc[2] = new Vector3(78.3154f, 18.9402f, 111.654f);
        cams_rot[2] = new Vector3(169f, 59.3947f, -110.242f);

        cams_loc[3] = new Vector3(78.023f, 18.7094f, 111.375f);
        cams_rot[3] = new Vector3(89.4105f, 16.7202f, -128.303f);

        cams_loc[4] = new Vector3(79.5798f, 19.7249f, 111.743f);
        cams_rot[4] = new Vector3(55.0461f, 74.0926f, -220.475f);

        int i = 0;
      
        foreach (Vector3 vector_loc in cams_loc)
        {
            string camName = "cam" + i.ToString();
            GameObject currentCam = AddCamera(camName);

            currentCam.GetComponent<Transform>().position = new Vector3(cams_loc[i].x, cams_loc[i].z, cams_loc[i].y);

            Vector3 objRotation = new Vector3(cams_rot[i].x * -1, cams_rot[i].z * -1, cams_rot[i].y * -1);
            objRotation.x += 90f;

            currentCam.GetComponent<Transform>().eulerAngles = objRotation;

            i += 1;
        }

    }

    // Update is called once per frame
    void Update()
    {

    }

    private GameObject AddCamera(string name)
    {
        GameObject gizmoPhoto = GameObject.Instantiate(GameObject.Find("cam"));
        gizmoPhoto.name = name;

        return gizmoPhoto;
    }
}

As far as I know Blender uses the ZYX rotation order for Eulers but Unity uses ZXY.

You could try creating your own quaternions using whatever order you like. For example, this should create a quaternion in ZYX order like Blender.

    Quaternion newRotation = Quaternion.AngleAxis(zAngle, Vector3.forward);
    newRotation *= Quaternion.AngleAxis(yAngle, newRotation * Vector3.up);
    newRotation *= Quaternion.AngleAxis(xAngle, newRotation * Vector3.right);

The problem is lines 40-41, I suspect. Euler angles often don’t play nicely with being tweaked one component at a time (and are, for the most part, pretty terrible overall and should be avoided whenever possible), and will sometimes work as you expect them to and sometimes not. This gets even more complex between different 3D applications because, as @tonemcbride pointed out, sometimes they apply these rotations in different orders.

That ^ code might solve this problem, but I’m really curious as to what the ultimate goal of this code is, because it seems like there must be drastically easier and more reliable ways to accomplish what you’re trying to do, but I’m not super clear on what exactly you’re trying to do. If you’re just importing camera locations from Blender, why not just attach Camera components to the GameObjects as imported from Blender, for example? You could find them by name or reference and use .AddComponent(), or you could spawn new camera objects as you are here and parent them to the transforms you want while zeroing out their local position/rotation.

Euler angles gives different resulting rotation when applied in different orders. That’s why unity uses quaternions for rotation. They don’t have order and lock problems. To skip all differences between unity and blender rotation systems export forward and up vectors from cameras instead of rotation and use camera.lookat method to apply them to unity cameras.

@ tonemcbride : Thanks for this trick, I tryed but results is not good.
@ StarManta : For satisfying your curiosity, I want import theses cameras in game after build.
@ palex-nx : Big thanks for your feedback ! I solved my problem with it ! :smile: