Unity - Importing an Animated Character from Cinema 4D

From NoskeWiki
Jump to: navigation, search

About

NOTE: This page is a daughter page of: Unity and Cinema 4D


Unity is a wonderful game engine, and Cieman 4D is my favorite 3D modelling software. There are actually a few great youtube videos which demonstrate how to put a Cinema4D model into YouTube, but the tend to skip over some important steps, so here I wrote down a step by step of how you can create a character in Cinema 4D, add some animation routines, and then import that character into Unity, and create the animation and movements scrips to have him running around your scene.  :)


Part 1: Create the Character in Cinema 4D and Export as FBX

  • Create Null Object at 0,0,0 called "MyHumanoid"
  • Aim to make your human ~2m tall. TIP: Create a box 2m tall (to delete later) as a target height.
  • Create hierarchy of bones underneath, starting with a "pelvis" at (0,0.8,0).
    • For bones: prefer "l_shoulder", "r_shoulder", "r_upper_arm", "r_hand", etc, to help Automatic Setup of Humanoid
    • For mesh: If creating single mesh, name whatever, if creating hierarchy parts I named "r_shoulder_sphere" to help distinguish from bones.
    • Certain parts, you may have to click "make editable", to turn to mesh. Sphere & cylinders, even effects like taper seem to be mostly okay though.
  • Prefer T-pose.
  • Save as "MyHumanoid.c4d".
  • Save new copy as "MyHumanoidAnimated.c4d".
  • Put arms down to the sides and this will be your "default standing position".
  • Add a running animation from frames 0-40, and idle from 40-90.
    • To make animation check rotate only and select the correct bone at the right frame, rotate it and click the keyframe icon to make each keyframe.
    • TIP: Fastest way, select the upper_arm, lower_arm, upper_leg and lower_leg bones (on each side), set to default pose and add keyframes to 0, 20, 40. Now select these bones indivdually, and change the "P" values to (+/-40) add keyframes at 10 and 30... it will result in fairly crude run, but at least it's a start!
  • Go: File > Export > FBX
    • Select: FBX Version=7.3, Animation=true, Textures and Materials=true, Mesh Normals=true, Textures=true... all else false.


Part 2: Load into Unity and Setup Animation

  • Start Unity.
  • Create new project and import "PlayerController", and create the following directories under Assets: "Animators", "Models", "Scripts"
  • Move newly created "MyHumanoid.fbx" to Assets > Models folder, preferably to it's own subfolder called "Player".
  • Select and expand "MyHumanoid" in Unity's Project Hierarchy.
  • Set up the two animations:
    • In the Inspector window > Animations tab, rename "C4D Animation Take" to "Running" and change the frames range from 0-40. Now add a new animation called "Idle" and set frame range from 40-90. Tick "loop time" for both animations.
    • Click "Apply".
    • Expand "MyHumanoid" and you should see "Idle" and "Running" animations have been created.
  • Now set up the rig (optional).
    • In the Inspector window > "Rig", and change "Animation Type" to Humanoid, then click "Configure" button.
    • You must save model.
    • Inspector will now show you green human, and hopefully will have connected the right bones to the correct joints. Otherwise you can alter these pretty easily.
  • Open Assets > Animators folder (in Projects window) and click Add > Animator Controller. Call it "MyHumanoidAnimator", and click Window > Animator to edit.
    • From the project window drag the "Idle" animation (under MyHumanoid) into the Animator window. It will appear in orange to represent the default state.
    • Also drag in the "Running".
    • Right click the "Idle" box > Add Transition, and drag a connection to Running. Then do the same from "Running" back to "Idle".
    • In the bottom right of the Animator window, click the Parameters "+" button and add a bool called "IsRunning".
    • Select the transition arrow from Idle to running, and change the condition to "IsRunning" "true". Do the same for the other transition (but where "IsRunning" "false".


  • Drag "MyHumanoid" into the Scene window and set him to position 0,0,0.
  • With the player selected in the "Hierarchy" window, drag "MyHumanoidAnimator" onto the "Animator > Controller" field which is automatically added to the model.
  • Now click "Add Component > New Script" and create a c# script called "PlayerMovement".


Add the following script to PlayerMovement.cs:

// Apply to player.
using UnityEngine;
using System.Collections;
 
public class PlayerMovement : MonoBehaviour {
  private Animator anim;                 // Reference to the animator component.
  private int stateIsRunning;            // Reference animator's "IsRunning" var.
 
  void Awake () {
    anim = GetComponent<Animator>();
    stateIsRunning = Animator.StringToHash("IsRunning");
  }
 
  void FixedUpdate () {
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");
    MovementManagement(h, v);
  }
 
  void Update () {
  }
 
  void MovementManagement (float horizontal, float vertical) {
    // Animation:
    if (vertical > 0) {  // Will eventually want different animation for backwards.
      anim.SetBool (stateIsRunning, true);
    } else {
      anim.SetBool (stateIsRunning, false);
    }
  }
}
  • Move "Main Camera" to a position where you can see your humanoid properly (try: 0,1,-5)
  • Click "Play" and then use the forward / back arrow keys and you should see your humanoid transition from Idle to Running and back.
    • Reminder: Don't forget to click 'Stop' to make changes - any changes you make while playing are temporary
  • To see it a little nicer click Component > Add > Point Light, move it behind the camera and give it a big radius.


Part 3: Make Your Character Run Around the Scene

Okay, so he animates, but he's stuck on the spot. The exciting part is making him actually run.

  • Select your player in the Hierarchy, click "Add Component" add a "RigidBody" component.
  • Expand the RigidBody Constraints and freeze position in y (if gravity is ticked we don't want him falling yet), and freeze rotation in x, y and z (we will control the rigid body rotation ourselves).

Change PlayerMovement.cs to:

// Apply to player.
using UnityEngine;
using System.Collections;
 
public class PlayerMovement : MonoBehaviour {
  private Animator anim;                 // Reference to the animator component.
  private int stateIsRunning;            // Reference animator's "IsRunning" var.
 
  private float turnSpeed = 360f;        // Angle in degrees user can turn per second.
  private float angleFacing = 180f;      // Angle user is currently facing.
  private float turnSmoothing = 100.0f;  // A smoothing value for turning the player.
  private float runSpeed = 0.02f;        // Speed of players run.
 
  void Awake () {
    anim = GetComponent<Animator>();
    stateIsRunning = Animator.StringToHash("IsRunning");
  }
 
  void FixedUpdate () {
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");
    MovementManagement(h, v);
  }
 
  void Update () {
  }
 
  void MovementManagement (float horizontal, float vertical) {
    // Animation:
    if (vertical > 0) {  // Will eventually want different animation for backwards.
      anim.SetBool (stateIsRunning, true);
    } else {
      anim.SetBool (stateIsRunning, false);
    }
 
    // Rotate:
    angleFacing += (horizontal * turnSpeed * Time.deltaTime);
    float rad = Mathf.Deg2Rad * angleFacing;
    Vector3 targetDirection = new Vector3(Mathf.Sin(rad), 0f, Mathf.Cos(rad));
    Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
    Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime);
    rigidbody.MoveRotation(newRotation);
 
    // Move:
    float moveAmount = vertical * runSpeed;
    Vector3 newPos = rigidbody.position;
    newPos.x += (Mathf.Sin(rad) * moveAmount);
    newPos.z += (Mathf.Cos(rad) * moveAmount);
    rigidbody.MovePosition(newPos);
  }
}
  • Click "Play" and then use all your arrow keys and your player should move!


Part 4: Make Camera Follow Player

If you want a 3rd person shooter style game you can simply place the MainCamera as a child of your player, looking over his shoulder - no script required! For something a tiny more challenging lets say I want the camera to look down and follow the player, but keep its starting orientation.

If you want your camera to follow your player, about the simplest script you could add to "MainCamera" is this for CameraMovement.cs:

// Apply to MainCamera
using UnityEngine;
using System.Collections;
 
public class CameraMoveScript : MonoBehaviour {
  private Transform player;           // Reference to the player's transform.
  private Vector3 relCameraPos;       // The relative position of the camera from the player.
 
  void Awake () {
    // NOTE: The value of "Tags.player" will be just "Player", but it's good to make a Tags.cs
    player = GameObject.FindGameObjectWithTag(Tags.player).transform;
    relCameraPos = transform.position - player.position;  // Save position at start.
  }
 
  void FixedUpdate () {
    // The standard position of the camera is the relative position of the camera from the player.
    Vector3 standardPos = player.position + relCameraPos;
    transform.position = standardPos;
  }
}

And it is a good idea to start a (non-applied) Tag.cs:

// Don't apply to any object
using UnityEngine;
using System.Collections;
 
public class Tags : MonoBehaviour {
  // Maintain your list of tag strings here:
  public const string player = "Player";
}
  • Click 'Play' to test that the camera stays at the same position relative to the player. Experiment to find a good angle looking down on the player.  :)
  • Tidy up your scripts by moving them all to the "Scripts" folder you made.


Part 5: Add a Scene and Collision Detection

  • Select your player in the Hierarchy, and under the Rigid Body component, add a "Capsule Collider" and adjust the size so it fits over your player from head to toe. Try adjusting y to 1, radius 0.5 and height 2 and refine from there.
  • Create a new Cinema 4D file, add single null object called "MySceneRoot" and under that add a floor of 500x500m and a few cubes to represent buildings.
  • Save this new file, export it as a "Scene1.fbx", then drag into the "Assets/Models/Scene" folder.
    • Tip: before exporting, certain objects *may* need to be right clicked "Convert to Object" so that you have an editable mesh... although hopefully the export process will take care of this for you.
  • Wait for Cinema 4D to process the new model, then drag "Scene1" into the Hierarchy.
  • Adjust the position so that it's just under the player (hopefully at position 0,0,0).
  • Select each mesh under "MySceneRoot" and click "Add Component" > "Mesh Collider". Each component should add the matching mesh automatically, but if you have a complex scene a trick most game developers use it to create an (unseen) lower resolution mesh, specifically for collision detection.
  • Click 'Play' and you should now be able run around the floor and bump into buildings (not run through them).
  • Experiment with the players "RigidBody" values, by adding gravity, unlocking the X component, and running off the edge of the scene.
  • You change the gravity amount under: Edit > Project Settings > Physics.
  • Add more complexity to the environment by making the floor editable and raising/lowering points... adding more cubes, and altering your "PlayerMovement.cs" to add a jump.
  • Continue having fun!  :)


Other Tips

There is a convention where you can save "ModelName@Anation.fbx", and save just the animation... and can apply this to any model. See C4D to Unity video.


Videos