Cinema 4D

From Unify Community Wiki
Jump to: navigation, search

Contents

Overview

Description

Cinema_4D_logo.jpg
URL: http://www.maxon.net/
Tutorials: http://www.c4dcafe.com/ipb/index.php?automodule=downloads&showcat=1
Current Version: http://www.maxon.net/pages/download/downloads_e.html
Unity Documentation: http://unity3d.com/Documentation/Manual/HOWTO-ImportObjectCinema4D.html

Known Issues

Unity Scale Calibration

Meshes (Modelling)

Textures (UV's)

There seems to be a refresh bug within C4D (R10) which won't let you see the proper UV layout of your tags. In order to see the UV layout you want to work on you will have to manually drag the UV Tag into the UV Layout window. Another important factor when dealing with multiple UV's is that the order of the tags is important. See Image for clarification.
Drag and Drop the desired UV Tag into the UV Edit Window

Additional Info: It seems like this is not a refresh bug. Bodypaint has the ability to paint on multiple objects at once. Here is a statement of one of the programmers on that topic:

"Bodypaint UV visibility doesn't just show as soon as you select a tag, you have to actually select the UV set from the menu or drag & drop (and normally you have to also tell it to edit the UV's first too, choosing either UV Polygon or UV Points modes). That's reasonable seeing as you can paint on multiple objects at once that are selected and multiple materials, you don't want to swapping around a lot just because you're doing a multiselection, so the paint window is not directly connected to the object manager in most cases. That's probably because if there is no UVW tag somewhere to the right of a texture tag it uses the first (leftmost) UVW tag on the object when told to UVW projection. It "works" but it's back to front, the one on the right will be using the UVW tag on the left, and the texture tag on the left will be using the one on the right."

Bones

Animations

Exporting to Unity

The latest version of Cinema 4D (R11) properly exports joints to Unity. The only issue is that IK and Xpresso have to be manually baked before they can be imported into Unity.

The easiest way to bake IK and Xpresso is to use the Bake objects command. At times however, this will skip one or two keyframes here or there, introducing nasty pops in the animation.

Another way to bake IK and Xpresso is to use following script. It will record a keyframe on every frame and save the file at a path that you specify, leaving the original file untouched. It will also delete any objects that you specify. This is great if you have controllers that you don't want cluttering the hierarchy in Unity.

To use the script, simply go to Window -> Script Manager in Cinema 4D and paste the script. Name the script Export to Unity. Change the variables at the start of the script to match your own setup. Most important of course is the savePath, which should be the path of your Assets folder or subfolder where you want the exported files. Then go to Plugins -> User Scripts -> Export to Unity. Note that the baked file is .c4d, so you will still need Cinema 4D on the same machine as Unity to convert it to FBX.

/* Export to Unity script.
 *
 * Bakes animation for all joints in the scene, deletes
 * any controllers or other objects that you specify,
 * and saves the result as a new file at a specified path,
 * leaving the original untouched.
 *
 * Note: The script will only bake animation if the
 * filename has an @ in it.
 */
 
// Inputs. Change these to match your own setup.
var bakePosition = 1;
var bakeScale = 0;
var bakeRotation = 1;
var fps = 30;
var savePath = "/Users/User/Documents/Project/Assets/";
var deleteObjects;
assignArray()
{
	deleteObjects = new(array,2);
	deleteObjects[0] = "Controllers";
	deleteObjects[1] = "High Poly";
}
 
// Constants
const var joint = 1019362;
const var goto_start = 12501;
const var goto_next_frame = 12414;
const var record_active_objects = 12410;
const var record_position = 12417;
const var record_scale = 12418;
const var record_rotation = 12419;
const var delete_object = 12109;
const var close = 12664;
const var use_expressions = 13522;
 
// Bakes the current frame for all joints
bakeJoints(doc, obj)
{
	while (obj != NULL)
	{
		// Only key joints
		if (obj->GetType() == joint)
		{
			doc->SetActiveObject(obj);
			CallCommand(record_active_objects);
		}
 
		// Loop through all children and bake them as well
		var child = obj->GetDown();
		while (child != NULL)
		{
			bakeJoints(doc, child);
			child = child->GetNext();
		}
 
		obj = obj->GetNext();
	}
}
 
// Deletes the object hierarchy with the specified name
deleteObject(doc, name)
{
	var obj = doc->GetFirstObject();
	while (obj != NULL)
	{
		if (obj->GetName() == name)
		{
			doc->SetActiveObject(obj);
			CallCommand(delete_object);
		}
		obj = obj->GetNext();
	}
}
 
main(doc, op)
{
	// Because you can't assign arrays outside functions - yeah stupid
	assignArray();
 
	// Set what to parameters to bake
	if (IsCommandChecked(record_position) != bakePosition)
	{
		CallCommand(record_position);
	}
	if (IsCommandChecked(record_scale) != bakeScale)
	{
		CallCommand(record_scale);
	}
	if (IsCommandChecked(record_rotation) != bakeRotation)
	{
		CallCommand(record_rotation);
	}
 
	// Only bake keyframes if the filename contains "@"
	var currFilename = doc->GetFilename();
	var file = currFilename->GetLastString();
	if(strstr(file, "@") != -1)
	{
		// Bake keyframes for all joints
		CallCommand(goto_start);
		var frame = doc->GetTime()->GetFrame(fps);
		var maxFrame = doc->GetMaxTime()->GetFrame(fps);
		for (; frame <= maxFrame; frame++)
		{
			var obj = doc->GetFirstObject();
			bakeJoints(doc, obj);
			CallCommand(goto_next_frame);
			DrawViews(DA_NO_THREAD);
		}
	}
 
	// Delete objects
	var i;
  for(i = 0; i < sizeof(deleteObjects); i++)
	{
		deleteObject(doc, deleteObjects[i]);
	}
 
	// Save as new file
	var currFilename = doc->GetFilename();
	var newFilename = new(Filename);
	newFilename->SetFullString(savePath);
	newFilename->AddLast(currFilename->GetLastString());
	doc->Save(newFilename);
	println(newFilename->GetFullString(), " exported");
 
	// Close the new file
	CallCommand(close);
 
	// Reopen original file
	LoadDocument(currFilename);
	println(currFilename->GetFullString(), " reopened");
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Tools