Skip to content

Getting started

BroTools has a camera export script that will export a camera for a game engine.

Game engines typically ignore any camera attributes when importing FBX files, only using transformation values.

This script creates a world space joint based rig that contains a root joint, a camera joint and a special attributes joint. It bakes the animation to the camera joint, and it bakes the focal length and some other camera attributes to the special attributes joint's transformation and rotation values. The game engine can then read these attributes from the joints.

You are correct. Using the Physical Camera mode in Unity is much more pragmatic. It allows you to pipe the Maya values directly into the camera component without manual trigonometry, as Unity’s physical camera model matches Maya's internal logic.

Here is the updated specification and the simplified Unity implementation.


Camera Export/Import Specification

This format encodes Maya camera data into a 3-joint hierarchy. To avoid issues with custom FBX attributes, optical data is stored in the Local Translation channels of a specific "attribute" joint.

1. Rig Hierarchy

  • root_joint: Origin (0,0,0).
  • camera_joint: Child of root_joint. World Space Position and Rotation.
  • attributes_joint: Child of camera_joint. Stores optical data in Translation channels.

2. Data Mapping

Node Channel Maya Attribute Engine Target
camera_joint Translation World Position Camera Position
camera_joint Rotation World Rotation Camera Rotation
attributes_joint Translation X Focal Length Focal Length (mm)
attributes_joint Translation Y Vertical Film Aperture Sensor Size Y (inches)
attributes_joint Translation Z Horizontal Film Aperture Sensor Size X (inches)

3. Unity Implementation (Physical Camera)

This approach requires the Physical Camera checkbox to be enabled on your Target Camera. Set Gate Fit to Fill to ensure the vertical/horizontal ratios match your Maya output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
using UnityEngine;

public class CameraDriver : MonoBehaviour
{
    [Header("Rig References")]
    public Transform cameraJoint;
    public Transform attributesJoint;

    [Header("Target")]
    public Camera targetCamera;

    void Start()
    {
        if (targetCamera == null) return;

        // Force correct physical settings on initialization
        targetCamera.usePhysicalProperties = true;
        targetCamera.gateFit = Camera.GateFitMode.Fill;
    }

    void LateUpdate()
    {
        if (cameraJoint == null || attributesJoint == null || targetCamera == null) return;

        targetCamera.transform.SetPositionAndRotation(cameraJoint.position, cameraJoint.rotation);

        targetCamera.focalLength = attributesJoint.localPosition.x;

        // Convert Maya inches to Unity millimeters
        float sensorX_mm = attributesJoint.localPosition.z * 25.4f;
        float sensorY_mm = attributesJoint.localPosition.y * 25.4f;

        targetCamera.sensorSize = new Vector2(sensorX_mm, sensorY_mm);
    }
}