0
\$\begingroup\$

I add news cameras in my game. I have 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.

Cameras 1, 2, 4 : good rotation

Cameras 3, 5 : bad rotation

Cam 1 (Blender):

enter image description here

Cam 1 (Unity): the fov is different

enter image description here

Cam 4 (Blender):

enter image description here

Cam 4 (Unity): the fov is different

enter image description here

Cam 3 (Blender):

enter image description here

Cam 3 (Unity): rotation is very different

enter image description here

Cam 5 (Blender):

enter image description here

Cam 5 (Unity): rotation is very different

enter image description here

This problem appears if camera orientation is "vertical" enter image description here

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;
    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;
        }
    }

    void Update()
    {

    }

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

        return gizmoPhoto;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Your script has hardcoded values for the camera rotations and positions. Where did you get those numbers from? Did you copy them from the Blender file by hand? If you did so, remember that Unity and Blender do not use the same coordinate system. \$\endgroup\$ – Philipp Jul 31 '19 at 10:00
  • 1
    \$\begingroup\$ And regarding the FOV: All the cameras you create are based on a copy of the first-best camera with the name "cam" in your complete scene. I can't see any code which changes the FOV, so the instantiated cameras will all inherit the FOV of that "cam" camera. \$\endgroup\$ – Philipp Jul 31 '19 at 10:03
  • \$\begingroup\$ @ Philipp : these hardcorded values exist only for simplify this example. In real life I get thes informations from file generate by a Blender script ;) Yes, Blender and Unity use differents coordinates system. I inverse Y and Z value in my code (see top). \$\endgroup\$ – LukeNukem Jul 31 '19 at 13:02
  • \$\begingroup\$ Yes, fov is not yet added :) \$\endgroup\$ – LukeNukem Jul 31 '19 at 13:09
  • \$\begingroup\$ Have you considered outputting to your file a forward and up vector for each camera, instead of an Euler angle triplet? These are less error-prone to work with, and you can convert them to a rotation with Quaternion.LookRotation(forward, up). \$\endgroup\$ – DMGregory Jul 31 '19 at 13:30
0
\$\begingroup\$

Unity and Blender use different coordinate systems. In Unity, y is up while in Blender, z is up. Also, rotations in Blender are counter-clockwise around the axis while they are clockwise in Unity. But you already got that correctly.

However, what you didn't get correctly is that when it comes to rotations, just switching the y-angle and the z-angle won't do. When you perform rotations in euler angles, then the order in which these rotations are performed does matter. And unfortunately Unity and Blender also disagree about that. Transform.eulerAngles creates the rotation by:

  1. rotating z degrees around the z axis,
  2. then x degrees around the x axis and
  3. then y degrees around the y axis.

While Blender performs rotations, it does so in this order:

  1. around z (which is Unity y)
  2. around y (which is Unity z)
  3. around x (which is Unity x)

To apply rotations on single axis' one at a time, start with an euler rotation of 0°:0°:0° and use transform.Rotate three times:

Transform camTransform = currentCam.GetComponent<Transform>()
camTransform.rotation.eulerAngles = Vector3.zero;
camTransform.Rotate(0.0f, cams_rot[i].z * -1, 0.0f);
camTransform.Rotate(0.0f, 0.0f, cams_rot[i].y * -1);
camTransform.Rotate(cams_rot[i].x * -1, 0.0f, 0.0f);

But there might also be a far easier solution for your problem which doesn't require any programming at all: Just import the cameras from the Blender project. Export your Blender project in .fbx format (if you aren't already - it's what Unity recommends) and when you drop it into Unity make sure "Import Cameras" is enabled in the import settings.

\$\endgroup\$
  • \$\begingroup\$ @LukeNukem I updated my answer after experimenting with Blender it at home. However, the code I posted is untested because I don't have access to your source file. Please try it and tell me if it works. \$\endgroup\$ – Philipp Jul 31 '19 at 21:00
  • \$\begingroup\$ @ Philipp : thanks for your feedback. I tryed it but the result is stange. I finally solved my problem with the DMGregory trick :D \$\endgroup\$ – LukeNukem Aug 1 '19 at 7:19
  • \$\begingroup\$ You say Blender performs rotations, ... in this order actually, that depends on the settings used, by default blender will rotate in XYZ but the rotation mode can be changed to any desired order. The trick would therefore be choosing the right euler rotation mode in blender. \$\endgroup\$ – sambler Aug 5 '19 at 1:52
0
\$\begingroup\$

I solved my problem with this :

import bpy
from mathutils import Vector

object_name = "cam3"
cam = bpy.data.objects[object_name]
up = cam.matrix_world.to_quaternion() * Vector((0.0, 1.0, 0.0))
cam_direction = cam.matrix_world.to_quaternion() * Vector((0.0, 0.0, -1.0))
\$\endgroup\$
  • 2
    \$\begingroup\$ Please don't wedge "Solved" into your question title. After a short delay you'll be able to click the checkmark on your own answer to mark it "Accepted" — that's how we flag solved problems here. \$\endgroup\$ – DMGregory Aug 1 '19 at 12:59
  • \$\begingroup\$ Have you tried changing your cameras rotation mode to quaternion in blender? \$\endgroup\$ – sambler Aug 5 '19 at 1:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.