Adding a custom motion controller

Notes:

  • This tutorial has been updated to reflect the changes made to Motion Controller v2.
  • A further example of integrating PlayMaker-based control can be found on the AC wiki here.

While Adventure Creator provides multiple built-in options for character motion, it’s also possible to move characters through your own means - whether through custom scripts, or with one of the many controller assets on the Unity Asset Store. Adventure Creator makes the process of integrating an external controller as simple as possible by providing a number of useful script functions.

In this tutorial, we’ll allow our characters (both Player and NPCs) to be controlled with the Motion Controller asset. However, the principles used can be transferred to other such solutions.

The first step is to give our character the scripts necessary for both Adventure Creator and Motion Controller. Which way around you will want to do this will depend on the asset involved, but here we’ll begin with a Motion Controller-ready player and convert it to Adventure Creator. The Jones GameObject in Motion Controller’s MC_Simple scene is such a player:

Select Jones, and set his Movement Style to Adventure.

Next, add two scripts beneath his Motion Controller component: Player and Paths. These two are the minimum Adventure Creator needs to work.

At the top of the Player component, you can see fields for both the Animation engine and Motion control.

As Motion Controller will override both the animation and motion systems, we'll want to set these to Custom and Manual respectively.

Notice how the Movement settings box just below shrinks down to reflect how we now have full control over our player’s motion. We can now use Motion Controller to guide this player in an Adventure Creator scene without any trouble. However, we still want Adventure Creator to be able control the player during cutscenes - as well as control NPCs during gameplay. We can link the two together with a simple script, which we’ll call CustomControllerLink. Use the Add Component button at the bottom of the Inspector to create and add a script with this name.

Open the script up for editing. Both Adventure Creator and Motion Controller use their own scripting namespaces, so we’ll need to include these in the header:

using UnityEngine;
using System.Collections;
using com.ootii.Actors.AnimationControllers;
using AC;

We now want to create two script variables, to reference the attached MotionController and Player scripts. Note that Adventure Creator’s Player script is a subclass of Char, as is the NPC script. By referencing Char instead of Player, we can use the same script to control NPCs.

public class CustomControllerLink : MonoBehaviour
{
	private MotionController motionController;
	private Char _char;

We'll also create a public boolean, disableDuringGameplay, which we can check in the Inspector if we want to use Motion Controller as normal during gameplay.

public bool disableDuringGameplay;

Next, we want to assign these variables as appropriate, so they can be referenced later. Do this in the Start function:

private void Start ()
{
	motionController = GetComponent <MotionController>();
	_char = GetComponent <AC.Char>();
}

Our integration will basically boil down to either manipulating the MotionController based on AC's calculations, or 'releasing' it so that it's free to do it's thing as normal. Let's add two functions that will do each of these things: SetCharacterPosition and ClearCharacterPosition:

private void SetCharacterPosition ()
{
	if (_char.GetPath ())
	{
		motionController.SetTargetPosition (_char.GetTargetPosition (), 1f);
	}
	else
	{
		ClearCharacterPosition ();

		if (_char.IsTurning () && _char.charState == CharState.Idle)
		{
			// Turn on the spot
			Quaternion newRotation = Quaternion.RotateTowards(motionController.transform.rotation, _char.GetTargetRotation(), 5f);
			motionController.SetTargetRotation (newRotation);
		}
	}
}

private void ClearCharacterPosition ()
{
	motionController.ClearTarget ();
}

SetCharacterPosition will call MotionController's SetTargetPosition function is the character is moving along a Path. The GetTargetPosition function is a public function of AC's Char script, and will return the intended position AC wishes that character to move towards. You can read more about that function, and others, in AC's scripting guide.

If the character is not along a path, then it will instead call ClearCharacterPosition. This function calls MotionController's ClearTarget function, which removes the effects that calling SetTargetPosition has made. It also makes an additional check for turning on the spot: since Motion Controller handles the turning of the character only while moving, we must rotate the character manually when the character is standing.

Finally, we just need to call these functions when appropriate in our Update function. Remember our disableDuringGameplay function: if it's checked in our Inspector (i.e. 'True'), then we only want to control the character if we're in a Cutscene. We can determine this by reading the StateHandler's gameState variable.

private void Update ()
{
	if (disableDuringGameplay)
	{
		if (KickStarter.stateHandler && KickStarter.stateHandler.gameState == GameState.Cutscene)
		{
			SetCharacterPosition ();
		}
		else
		{
			ClearCharacterPosition ();
		}
	}
	else
	{
		SetCharacterPosition ();
	}
}

Our script is now complete, and will work for both Player characters and NPCs. The complete script is as follows:

using UnityEngine;
using System.Collections;
using com.ootii.Actors.AnimationControllers;
using AC;
	

public class CustomControllerLink : MonoBehaviour
{
	
	private MotionController motionController;
	private Char _char;

	public bool disableDuringGameplay;

	
	private void Start ()
	{
		motionController = GetComponent <MotionController>();
		_char = GetComponent <AC.Char>();
	}
	
	
	private void Update ()
	{
		if (disableDuringGameplay)
		{
			if (KickStarter.stateHandler && KickStarter.stateHandler.gameState == GameState.Cutscene)
			{
				SetCharacterPosition ();
			}
			else
			{
				ClearCharacterPosition ();
			}
		}
		else
		{
			SetCharacterPosition ();
		}
	}
	
	
	private void SetCharacterPosition ()
	{
		if (_char.GetPath ())
		{
			motionController.SetTargetPosition (_char.GetTargetPosition (), 1f);
		}
		else
		{
			ClearCharacterPosition ();

			if (_char.IsTurning () && _char.charState == CharState.Idle)
			{
				// Turn on the spot
				Quaternion newRotation = Quaternion.RotateTowards(motionController.transform.rotation, _char.GetTargetRotation(), 5f);
				motionController.SetTargetRotation (newRotation);
			}
		}
	}


	private void ClearCharacterPosition ()
	{
		motionController.ClearTarget ();
	}

}

Adventure Creator and Motion Controller can now work together. If you want to go deeper with custom scripting, or make use of another controller asset, the following functions and variables are available in the Char script:

"Adventure Creator" and this website are copyright Chris Burton, ICEBOX Studios

Go to top