I’m a big fan of Perforce as a version control solution for game development, however when working in Unity the integration isn’t perfect. Specifically, using the current iteration of the built-in Mechanim animation system doesn’t really lend itself to merging changes.
Note: This is an advanced tutorial, recommended for those already familiar with the Unity3D game engine.
Note 2: While this post is specifically about my experience with Perforce, the same approach can be applied to any version control system you’ve integrated, since the Unity Version Control API is generic.
The Problem
Although the animation controllers are stored in ASCII as YAML, the results of trying to merge changes don’t generally make much sense. This is because the file contains all the graphical location data in addition to the state machine information, as well as references to additional data in the same file. What this means is, if two people happen to edit the same animation controller, one of those developers will be required to re-implement all their modifications manually .. even if the first dev only made a few minor changes.
It’s not impossible to merge, its just not intuitive. And since the animation controller is likely something that artists will want to tweak, you’ll have riots on your hand if you expect your artists to run a diff against the YAML file, looking for which changes to merge.
Of course, we could have simply edited our settings in Perforce so that on checkout, the animation controllers were locked, but that would have prevented other developers from experimenting with changes. And while the Unity Version Control UI does show a blue-checkmark to indicate an item is checked out remotely (see image on left), it is not readily noticeable.
The Solution
A simple solution was to just add a warning message to the inspector when an animation controller is checked out remotely via the Unity Version Control API. With this warning, a developer knows that someone else is working on the controller and we leave it to old fashion communication skills to work it out in advance.
using UnityEngine;
using UnityEditor;
using UnityEditor.Animations;
using UnityEditor.VersionControl;
using System.Collections;
[CustomEditor(typeof(UnityEditor.Animations.AnimatorController))]
public class P4AnimController : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
AnimatorController ACTarget = target as AnimatorController;
if (ACTarget != null)
{
if (!Provider.isActive)
{
EditorGUILayout.TextField("P4 Plugin is not connected.", EditorStyles.helpBox);
}
else
{
Asset.States[] statesToCheck = { Asset.States.CheckedOutRemote };
if (Provider.GetAssetByPath(AssetDatabase.GetAssetPath(ACTarget)).IsOneOfStates(statesToCheck))
{
EditorGUILayout.HelpBox("Animation Controller: CHECKED OUT REMOTELY", MessageType.Warning);
}
else
{
EditorGUILayout.TextField("Animation Controller: Not checked out remotely", EditorStyles.helpBox);
}
}
}
}
}
While this is an incredibly simple implementation, you can imagine that the Version Control API could be used to create editor pop-up messages, prevent saving features, or a variety of other measures to provide feedback to the dev team (beyond the tiny check-box and independent of the actual Perforce settings).
This also places the burden on updating the status with the built-in integration. The API gives you the ability to go a lot farther with making your own status update requests, or go even farther and automate checking in through some C# script.