FANDOM


This script allows for integration with Unity's own Third Person Controller, which is included in their own Standard Assets package.  It can be used to move a character with both Direct and Point And Click methods, using the Third Person Controller script.

To use it:

  1. Take the existing ThirdPersonController or AIThirdPersonController prefab, and remove any existing control script (with ThirdPersonController, this is ThirdPersonUserControl; with AIThirdPersonController, this is AICharacterControl).
  2. Attach either AC's Player or NPC component
  3. In AC's Settings Manager, set your game's Movement method to either Point And Click or Direct
  4. Attach the script below to the character's root object
  5. (Optional) To allow for AC-controlled movement during e.g. cutscenes, also attach and configure a NavMeshAgent.  The scene must also rely on Unity Navigation pathfinding, as covered in the AC Manual.

UnityThirdPersonIntegration.cs:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityStandardAssets.Characters.ThirdPerson;
using AC;

public class UnityThirdPersonIntegration : MonoBehaviour
{

private NavMeshAgent navMeshAgent;
private AC.Char characterAC;
private ThirdPersonCharacter characterTP;

private enum ControlState { UnderDirectControl, UnityPathfinding, ACTurning };
private ControlState controlState = ControlState.ACTurning;

private Vector3 m_CamForward;
private Vector3 m_Move;
private bool m_Jump;


private void Start ()
{
// Get component variables, init the NavMeshAgent, and force Manual motion control to the AC character

navMeshAgent = GetComponentInChildren <NavMeshAgent>();
if (navMeshAgent != null)
{
navMeshAgent.updateRotation = false;
navMeshAgent.updatePosition = true;
}

characterAC = GetComponent <Char>();
characterAC.motionControl = MotionControl.JustTurning;

characterTP = GetComponent<ThirdPersonCharacter>();
}


private void Update ()
{
// Update what our current control state is
UpdateControlState ();

// Move the character according to the current control state
UpdateMovement ();
}


private void FixedUpdate ()
{
if (controlState == ControlState.UnderDirectControl)
{
// Do all the input checks for direct input
UpdateDirectInput ();
}
}


private void UpdateControlState ()
{
// Check if we want to determine the character's position through AC, or just through direct input
if (!KickStarter.stateHandler.IsInGameplay () || !characterAC.IsPlayer || characterAC.IsMovingAlongPath () || KickStarter.settingsManager.movementMethod == MovementMethod.PointAndClick)
{
// Check if we want to make the character pathfind, or do nothing while AC turns them
if (characterAC.charState == CharState.Move)
{
controlState = ControlState.UnityPathfinding;
}
else
{
controlState = ControlState.ACTurning;
}
}
else
{
controlState = ControlState.UnderDirectControl;
}
}


private void UpdateMovement ()
{
switch (controlState)
{
case ControlState.UnderDirectControl:
navMeshAgent.enabled = false;
if (!m_Jump)
{
m_Jump = Input.GetButtonDown ("Jump");
}
break;

case ControlState.UnityPathfinding:
if (navMeshAgent != null)
{
navMeshAgent.enabled = true;
}

if (navMeshAgent != null && navMeshAgent.isOnNavMesh)
{
navMeshAgent.SetDestination (characterAC.GetTargetPosition (true));

if (navMeshAgent.remainingDistance > navMeshAgent.stoppingDistance)
{
characterTP.Move (navMeshAgent.desiredVelocity, false, false);
}
else
{
characterTP.Move (Vector3.zero, false, false);
}
}
else
{
characterAC.Teleport (characterAC.GetTargetPosition (true));
ACDebug.LogWarning ("Character " + name + " cannot pathfind without a NavMeshAgent that is on the NavMesh - teleporting instead.", gameObject);
}
break;

case ControlState.ACTurning:
characterTP.Move (Vector3.zero, false, false);
break;
}
}


private void UpdateDirectInput ()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
bool crouch = Input.GetKey(KeyCode.C);

if (Camera.main != null)
{
// calculate camera relative direction to move:
m_CamForward = Vector3.Scale (Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized;
m_Move = v*m_CamForward + h*Camera.main.transform.right;
}
else
{
m_Move = v * Vector3.forward + h * Vector3.right;
}

if (Input.GetKey (KeyCode.LeftShift))
{
m_Move *= 0.5f;
}

characterTP.Move (m_Move, crouch, m_Jump);
m_Jump = false;
}


private void OnTeleport ()
{
// This function is called by the Char script whenever the character has been teleported.
if (navMeshAgent != null && navMeshAgent.isOnNavMesh)
{
navMeshAgent.Warp (transform.position);
}
}

}