Files
BABA_YAGA/Assets/Third Parties/Opsive/UltimateCharacterController/Editor/Managers/CharacterManager.cs
Scove 3e39117acc Consolidate third-party plugins into Assets/Plugins
Move and consolidate many third-party plugin files and metadata from various locations (notably Assets/Third Parties/Plugins 1 and scattered Opsive/Photon folders) into a unified Assets/Plugins directory. Includes DOTween, PrimeTween, Native/BackroomsNoise, Sirenix/Odin Inspector, and Opsive UltimateCharacterController/shared libs, plus updates to several .meta files and removal of obsolete installer/legacy files. This standardizes plugin layout and cleans up duplicate/obsolete assets.
2026-06-16 18:41:44 +07:00

1152 lines
63 KiB
C#

/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Editor.Managers
{
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Editor.Utility;
using Opsive.UltimateCharacterController.Editor.Inspectors.Utility;
using Opsive.UltimateCharacterController.StateSystem;
using Opsive.UltimateCharacterController.Utility;
using Opsive.UltimateCharacterController.Utility.Builders;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
/// <summary>
/// Draws the Character Builder settings within the window.
/// </summary>
[Serializable]
[OrderedEditorItem("Character", 2)]
public class CharacterManager : Manager
{
/// <summary>
/// Specifies the perspective that the character can change into.
/// </summary>
private enum Perspective
{
First, // The character can only be in first person perspective.
Third, // The character can only be in third person perspective.
Both, // The character can be in first or third person perspective.
None // Default value.
}
/// <summary>
/// Specifies if the rig is a humanoid or generic. Humanoids allow for animation retargetting whereas generic characters do not.
/// </summary>
private enum ModelType { Humanoid, Generic }
private string[] m_ToolbarStrings = { "New Character", "Existing Character" };
[SerializeField] private bool m_DrawNewCharacter = true;
[SerializeField] private GameObject m_AddCharacter;
[SerializeField] private Perspective m_AddPerspective = Perspective.None;
[SerializeField] private string m_FirstPersonMovementType;
[SerializeField] private string m_ThirdPersonMovementType;
[SerializeField] private bool m_StartFirstPersonPerspective = true;
[SerializeField] private bool m_AddAnimator = true;
[SerializeField] private ModelType m_AddModelType;
[SerializeField] private RuntimeAnimatorController m_AddAnimatorController;
[SerializeField] private GameObject[] m_AddFirstPersonArms;
[SerializeField] private RuntimeAnimatorController[] m_AddFirstPersonArmsAnimatorController;
[SerializeField] private GameObject[] m_AddFirstPersonHiddenObjects;
[SerializeField] private bool m_AddStandardAbilities = true;
[SerializeField] private bool m_AddAIAgent = false;
[SerializeField] private bool m_AddNavMeshAgent = false;
[SerializeField] private bool m_AddItems = true;
[SerializeField] private Inventory.ItemCollection m_AddItemCollection;
[SerializeField] private bool m_AddHealth = true;
[SerializeField] private bool m_AddUnityIK = true;
[SerializeField] private bool m_AddFootEffects = true;
[SerializeField] private bool m_AddRagdoll = true;
[SerializeField] private StateConfiguration m_AddStateConfiguration;
[SerializeField] private int m_AddProfileIndex;
[SerializeField] private string m_AddProfileName;
[SerializeField] private GameObject m_ExistingCharacter;
[SerializeField] private Perspective m_ExistingPerspective;
[SerializeField] private bool m_ExistingAnimator = true;
[SerializeField] private ModelType m_ExistingModelType;
[SerializeField] private RuntimeAnimatorController m_ExistingAnimatorController;
[SerializeField] private GameObject[] m_OriginalExistingFirstPersonArms;
[SerializeField] private GameObject[] m_ExistingFirstPersonArms;
[SerializeField] private RuntimeAnimatorController[] m_ExistingFirstPersonArmsAnimatorController;
[SerializeField] private GameObject[] m_OriginalExistingFirstPersonHiddenObjects;
[SerializeField] private GameObject[] m_ExistingFirstPersonHiddenObjects;
[SerializeField] private bool m_ExistingAIAgent = false;
[SerializeField] private bool m_ExistingNavMeshAgent = true;
[SerializeField] private bool m_ExistingItems = true;
[SerializeField] private Inventory.ItemCollection m_ExistingItemCollection;
[SerializeField] private bool m_ExistingHealth = true;
[SerializeField] private bool m_ExistingUnityIK = true;
[SerializeField] private bool m_ExistingFootEffects = true;
[SerializeField] private StateConfiguration m_ExistingStateConfiguration;
[SerializeField] private int m_ExistingProfileIndex;
[SerializeField] private string m_ExistingProfileName;
private List<Type> m_FirstPersonMovementTypes = new List<Type>();
private string[] m_FirstPersonMovementTypeStrings;
private List<Type> m_ThirdPersonMovementTypes = new List<Type>();
private string[] m_ThirdPersonMovementTypeStrings;
private string[] m_PerspectiveNames = { "First", "Third", "Both" };
private Material m_InvisibleShadowCaster;
/// <summary>
/// Initialize the manager after deserialization.
/// </summary>
public override void Initialize(MainManagerWindow mainManagerWindow)
{
base.Initialize(mainManagerWindow);
// Set the default perspective based on what asset is installed.
if (m_AddPerspective == Perspective.None) {
#if FIRST_PERSON_CONTROLLER
m_AddPerspective = Perspective.First;
#elif THIRD_PERSON_CONTROLLER
m_AddPerspective = Perspective.Third;
#endif
}
// Get a list of the available movement types.
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; ++i) {
var assemblyTypes = assemblies[i].GetTypes();
for (int j = 0; j < assemblyTypes.Length; ++j) {
// Must derive from MovementType.
if (!typeof(Character.MovementTypes.MovementType).IsAssignableFrom(assemblyTypes[j])) {
continue;
}
// Ignore abstract classes.
if (assemblyTypes[j].IsAbstract) {
continue;
}
if (assemblyTypes[j].FullName.Contains("FirstPersonController")) {
m_FirstPersonMovementTypes.Add(assemblyTypes[j]);
} else if (assemblyTypes[j].FullName.Contains("ThirdPersonController")) {
m_ThirdPersonMovementTypes.Add(assemblyTypes[j]);
}
}
}
// Create an array of display names for the popup.
if (m_FirstPersonMovementTypes.Count > 0) {
m_FirstPersonMovementTypeStrings = new string[m_FirstPersonMovementTypes.Count];
for (int i = 0; i < m_FirstPersonMovementTypes.Count; ++i) {
m_FirstPersonMovementTypeStrings[i] = InspectorUtility.DisplayTypeName(m_FirstPersonMovementTypes[i], true);
}
}
if (m_ThirdPersonMovementTypes.Count > 0) {
m_ThirdPersonMovementTypeStrings = new string[m_ThirdPersonMovementTypes.Count];
for (int i = 0; i < m_ThirdPersonMovementTypes.Count; ++i) {
m_ThirdPersonMovementTypeStrings[i] = InspectorUtility.DisplayTypeName(m_ThirdPersonMovementTypes[i], true);
}
}
// Look for the ItemCollection within the scene if it isn't already populated.
if (m_AddItemCollection == null || m_ExistingItemCollection == null) {
m_AddItemCollection = m_ExistingItemCollection = ManagerUtility.FindItemCollection(m_MainManagerWindow);
}
// Find the state configuration.
var stateConfiguration = ManagerUtility.FindStateConfiguration(m_MainManagerWindow);
if (stateConfiguration != null) {
if (m_AddStateConfiguration == null) {
m_AddStateConfiguration = stateConfiguration;
}
if (m_ExistingStateConfiguration == null) {
m_ExistingStateConfiguration = stateConfiguration;
}
}
m_InvisibleShadowCaster = ManagerUtility.FindInvisibleShadowCaster(m_MainManagerWindow);
}
/// <summary>
/// Draws the Manager.
/// </summary>
public override void OnGUI()
{
var toolbarSelection = GUILayout.Toolbar(m_DrawNewCharacter ? 0 : 1, m_ToolbarStrings, EditorStyles.toolbarButton);
m_DrawNewCharacter = toolbarSelection == 0;
GUILayout.Space(10);
if (m_DrawNewCharacter) {
DrawNewCharacter();
} else {
DrawExistingCharacter();
}
}
/// <summary>
/// Draws the controls for a new character.
/// </summary>
private void DrawNewCharacter()
{
DrawPerspective(ref m_AddPerspective);
if (m_AddPerspective == Perspective.Both) {
m_StartFirstPersonPerspective = EditorGUILayout.Popup("Start Perspective", m_StartFirstPersonPerspective ? 0 : 1, new string[] { "First Person", "Third Person" }) == 0;
} else {
m_StartFirstPersonPerspective = (m_AddPerspective == Perspective.First);
}
// Show the available first person MovementTypes.
if (m_AddPerspective == Perspective.First || m_AddPerspective == Perspective.Both) {
var selectedMovementType = -1;
for (int i = 0; i < m_FirstPersonMovementTypes.Count; ++i) {
if (m_FirstPersonMovementTypes[i].FullName == m_FirstPersonMovementType) {
selectedMovementType = i;
break;
}
}
var movementType = selectedMovementType == -1 ? 0 : selectedMovementType;
selectedMovementType = EditorGUILayout.Popup("First Person Movement", movementType, m_FirstPersonMovementTypeStrings);
if (movementType != selectedMovementType || string.IsNullOrEmpty(m_FirstPersonMovementType)) {
m_FirstPersonMovementType = m_FirstPersonMovementTypes[selectedMovementType].FullName;
}
if (m_AddPerspective != Perspective.Both) {
m_ThirdPersonMovementType = string.Empty;
}
}
// Show the available third person MovementTypes.
if (m_AddPerspective == Perspective.Third || m_AddPerspective == Perspective.Both) {
var selectedMovementType = -1;
for (int i = 0; i < m_ThirdPersonMovementTypes.Count; ++i) {
if (m_ThirdPersonMovementTypes[i].FullName == m_ThirdPersonMovementType) {
selectedMovementType = i;
break;
}
}
var movementType = selectedMovementType == -1 ? 0 : selectedMovementType;
selectedMovementType = EditorGUILayout.Popup("Third Person Movement", movementType, m_ThirdPersonMovementTypeStrings);
if (movementType != selectedMovementType || string.IsNullOrEmpty(m_ThirdPersonMovementType)) {
m_ThirdPersonMovementType = m_ThirdPersonMovementTypes[selectedMovementType].FullName;
}
if (m_AddPerspective != Perspective.Both) {
m_FirstPersonMovementType = string.Empty;
}
}
var character = EditorGUILayout.ObjectField("Character", m_AddCharacter, typeof(GameObject), true) as GameObject;
if (character != m_AddCharacter) {
m_AddCharacter = character;
if (IsValidHumanoid(m_AddCharacter)) {
m_AddModelType = ModelType.Humanoid;
} else {
m_AddModelType = ModelType.Generic;
}
if (m_AddModelType == ModelType.Humanoid) {
m_AddAnimatorController = ManagerUtility.FindAnimatorController(m_MainManagerWindow);
}
}
// An animator is required for third person and AI agents.
var validCharacter = CheckValidCharacter(m_AddCharacter, true);
GUI.enabled = validCharacter && m_AddPerspective == Perspective.First;
var prevAddAnimator = m_AddAnimator;
var canBuild = DrawAnimator(m_AddCharacter, m_AddPerspective != Perspective.First, validCharacter, ref m_AddAnimator, ref m_AddModelType, ref m_AddAnimatorController);
if (prevAddAnimator && !m_AddAnimator) {
m_AddUnityIK = m_AddFootEffects = m_AddRagdoll = false;
}
GUI.enabled = validCharacter && canBuild;
if (m_AddPerspective == Perspective.First || m_AddPerspective == Perspective.Both) {
GUILayout.Space(7);
DrawFirstPersonArms(ref m_AddFirstPersonArms, ref m_AddFirstPersonArmsAnimatorController);
if (m_AddCharacter != null) {
GUILayout.Space(5);
DrawFirstPersonHiddenObjects(ref m_AddFirstPersonHiddenObjects);
}
GUILayout.Space(7);
}
GUILayout.Space(5);
// Reduce clutter by having an advanced foldout.
if (InspectorUtility.Foldout(this, "Advanced")) {
EditorGUI.indentLevel += 2;
// Abilities are added and removed through the inspector after the character has been built.
m_AddStandardAbilities = EditorGUILayout.Toggle("Standard Abilities", m_AddStandardAbilities);
DrawAdvancedComponents(m_AddAnimator, ref m_AddAIAgent, ref m_AddNavMeshAgent, ref m_AddItems, ref m_AddItemCollection, ref m_AddHealth, ref m_AddUnityIK,
ref m_AddFootEffects, true, canBuild, m_AddCharacter);
DrawProfileFields(ref m_AddStateConfiguration, ref m_AddProfileIndex, ref m_AddProfileName, null);
if (m_AddItems && m_AddItemCollection == null) {
canBuild = false;
}
if (m_AddUnityIK && !IsValidHumanoid(character)) {
canBuild = false;
}
if (m_AddFootEffects && !m_AddAnimator) {
canBuild = false;
}
if (m_AddRagdoll && !IsValidHumanoid(character)) {
canBuild = false;
}
EditorGUI.indentLevel -= 2;
}
// If the character hasn't been built yet then it should be created.
GUI.enabled = validCharacter && canBuild;
GUILayout.Space(5);
if (GUILayout.Button("Build Character")) {
// The first person perspective allows for null characters.
if (m_AddCharacter == null) {
m_AddCharacter = new GameObject("First Person Character");
}
var origCharacter = m_AddCharacter;
if (EditorUtility.IsPersistent(m_AddCharacter)) {
var name = m_AddCharacter.name;
m_AddCharacter = GameObject.Instantiate(m_AddCharacter) as GameObject;
m_AddCharacter.name = name;
}
CharacterBuilder.BuildCharacter(m_AddCharacter, m_AddAnimator, m_AddAnimatorController, m_FirstPersonMovementType, m_ThirdPersonMovementType, m_StartFirstPersonPerspective,
m_AddFirstPersonHiddenObjects, m_InvisibleShadowCaster, m_AddAIAgent);
CharacterBuilder.BuildCharacterComponents(m_AddCharacter, m_AddAIAgent, m_AddItems, m_AddItemCollection, !string.IsNullOrEmpty(m_FirstPersonMovementType) || (m_AddFirstPersonArms != null && m_AddFirstPersonArms.Length > 1),
m_AddHealth, m_AddUnityIK, m_AddFootEffects, m_AddStandardAbilities, m_AddNavMeshAgent);
#if FIRST_PERSON_CONTROLLER
if (m_AddFirstPersonArms != null) {
var firstPersonObjects = m_AddCharacter.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
if (firstPersonObjects != null) {
for (int i = 0; i < m_AddFirstPersonArms.Length; ++i) {
if (m_AddFirstPersonArms[i] == null) {
continue;
}
if (EditorUtility.IsPersistent(m_AddFirstPersonArms[i])) {
var name = m_AddFirstPersonArms[i].name;
m_AddFirstPersonArms[i] = GameObject.Instantiate(m_AddFirstPersonArms[i]) as GameObject;
m_AddFirstPersonArms[i].name = name;
}
ItemBuilder.AddFirstPersonArms(m_AddCharacter, m_AddFirstPersonArms[i], m_AddFirstPersonArmsAnimatorController[i]);
m_AddFirstPersonArms[i].transform.SetParentOrigin(firstPersonObjects.transform);
}
}
}
#endif
if (m_AddRagdoll) {
// Add the ragdoll ability and open Unity's ragdoll builder.
var characterLocomotion = m_AddCharacter.GetComponent<UltimateCharacterLocomotion>();
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.Ragdoll));
Inspectors.Character.Abilities.RagdollInspectorDrawer.AddRagdollColliders(characterLocomotion.gameObject);
}
if (m_AddAnimator) {
// Ensure the Animator Controller has the required parameters.
AnimatorBuilder.AddParameters((UnityEditor.Animations.AnimatorController)m_AddAnimatorController);
}
if (m_AddStateConfiguration != null) {
if (m_AddProfileIndex > 0) {
m_AddStateConfiguration.AddStatesToGameObject(m_AddProfileName, m_AddCharacter);
InspectorUtility.SetDirty(m_AddCharacter);
}
}
m_AddFirstPersonHiddenObjects = null;
Selection.activeObject = m_AddCharacter;
m_AddCharacter = origCharacter;
}
GUI.enabled = true;
}
/// <summary>
/// Draws the perspective controls.
/// </summary>
private void DrawPerspective(ref Perspective perspective)
{
var selectedPerspective = (Perspective)EditorGUILayout.Popup("Perspective", (int)perspective, m_PerspectiveNames);
var canSwitchPerspective = true;
// Determine if the selected perspective is supported.
#if !FIRST_PERSON_CONTROLLER
if (selectedPerspective == Perspective.First || selectedPerspective == Perspective.Both) {
Debug.LogError("Unable to select the first person perspective. If you'd like to create a first person character ensure the Firts Person Controller is imported.");
canSwitchPerspective = false;
}
#endif
#if !THIRD_PERSON_CONTROLLER
if (selectedPerspective == Perspective.Third || selectedPerspective == Perspective.Both) {
Debug.LogError("Unable to select the third person perspective. If you'd like to create a third person character ensure the Third Person Controller is imported.");
canSwitchPerspective = false;
}
#endif
if (canSwitchPerspective && selectedPerspective != perspective) {
perspective = selectedPerspective;
}
}
/// <summary>
/// Is the character a valid character?
/// </summary>
/// <param name="character">The character to check against.</param>
/// <param name="buildCharacter">Is the character a new character?</param>
/// <returns>True if the character is a valid character.</returns>
private bool CheckValidCharacter(GameObject character, bool buildCharacter)
{
// A character is required in order to add or remove components from it.
if (character == null) {
// The first person perspective doesn't need a predefined Character GameObject.
if (buildCharacter && m_AddPerspective == Perspective.First) {
return true;
}
EditorGUILayout.HelpBox("Select the GameObject which will be used as the character. This object will have the majority of the components added to it.",
MessageType.Error);
return false;
}
var characterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
if (buildCharacter && characterLocomotion != null) {
EditorGUILayout.HelpBox("The character has already been created. Use the \"Existing Character\" tab to modify the character components.", MessageType.Error);
return false;
}
if (!buildCharacter && characterLocomotion == null) {
EditorGUILayout.HelpBox("The character hasn't been created. Use the \"New Character\" tab to build the character.", MessageType.Error);
return false;
}
if (EditorUtility.IsPersistent(character)) {
EditorGUILayout.HelpBox("Please drag your character into the scene. The Character Manager cannot add components to prefabs.", MessageType.Error);
return false;
}
return true;
}
/// <summary>
/// Draws the animator controls.
/// </summary>
private bool DrawAnimator(GameObject character, bool forceAdd, bool enableGUI, ref bool animator, ref ModelType modelType, ref RuntimeAnimatorController animatorController)
{
animator = EditorGUILayout.Toggle("Animator", animator || forceAdd);
GUI.enabled = enableGUI;
if (animator) {
if (character == null) {
if (enableGUI) {
EditorGUILayout.HelpBox("A rigged character must be selected in order for an Animator to be added.", MessageType.Error);
}
return false;
}
EditorGUI.indentLevel++;
var selectedModelType = (ModelType)EditorGUILayout.EnumPopup("Model Type", modelType);
if (selectedModelType != modelType) {
modelType = selectedModelType;
if (modelType == ModelType.Humanoid) {
// Humanoids support retargetting so can use the demo controller.
animatorController = ManagerUtility.FindAnimatorController(m_MainManagerWindow);
} else {
// Generic characters require a custom animator controller.
animatorController = null;
}
}
if (modelType == ModelType.Humanoid && !IsValidHumanoid(character)) {
animatorController = null;
if (character != null) {
EditorGUILayout.HelpBox("The specified character is not a humanoid.\nHumanoid characters should have the avatar is set to humanoid and have a head bone assigned.", MessageType.Error);
}
}
// The non-default animator controller can be selected.
animatorController = EditorGUILayout.ObjectField("Animator Controller", animatorController, typeof(RuntimeAnimatorController), false) as RuntimeAnimatorController;
EditorGUI.indentLevel--;
}
return !animator || animatorController != null;
}
/// <summary>
/// Is the character a valid humanoid?
/// </summary>
/// <param name="character">The character GameObject to check against.</param>
/// <returns>True if the character is a valid humanoid.</returns>
private bool IsValidHumanoid(GameObject character)
{
if (character == null) {
return false;
}
var spawnedCharacter = false;
// The character has to be spawned in order to be able to detect if it is a Humanoid.
if (AssetDatabase.GetAssetPath(character).Length > 0) {
character = GameObject.Instantiate(character) as GameObject;
spawnedCharacter = true;
}
var animator = character.GetComponent<Animator>();
var hasAnimator = animator != null;
if (!hasAnimator) {
animator = character.AddComponent<Animator>();
}
// A human will have a head.
var isHumanoid = animator.GetBoneTransform(HumanBodyBones.Head) != null;
// GetBoneTransform sometimes returns a false negative.
if (!isHumanoid) {
isHumanoid = animator.isHuman;
}
// Clean up.
if (!hasAnimator) {
UnityEngine.Object.DestroyImmediate(animator, true);
}
if (spawnedCharacter) {
UnityEngine.Object.DestroyImmediate(character, true);
}
return isHumanoid;
}
/// <summary>
/// Draws the controls for the objects that will act as the first person arms.
/// </summary>
private void DrawFirstPersonArms(ref GameObject[] firstPersonArms, ref RuntimeAnimatorController[] firstPersonArmsAnimator)
{
if (firstPersonArms == null || firstPersonArms.Length == 0) {
firstPersonArms = new GameObject[1];
firstPersonArmsAnimator = new RuntimeAnimatorController[1];
}
for (int i = 0; i < firstPersonArms.Length; ++i) {
GUILayout.BeginHorizontal();
var guiContent = new GUIContent(i == 0 ? "First Person Arms" : " ", "First person objects that are the base for the items. The second field contains a reference to the Animator Controller that the arms should use.");
firstPersonArms[i] = EditorGUILayout.ObjectField(guiContent, firstPersonArms[i], typeof(GameObject), true) as GameObject;
if (firstPersonArms[i] != null) {
firstPersonArmsAnimator[i] = EditorGUILayout.ObjectField(firstPersonArmsAnimator[i], typeof(RuntimeAnimatorController), true, GUILayout.MaxWidth(180)) as RuntimeAnimatorController;
}
if (i == firstPersonArms.Length - 1 && firstPersonArms[i] != null) {
Array.Resize(ref firstPersonArms, firstPersonArms.Length + 1);
Array.Resize(ref firstPersonArmsAnimator, firstPersonArmsAnimator.Length + 1);
break;
}
if (i != firstPersonArms.Length - 1 && GUILayout.Button(InspectorStyles.RemoveIcon, InspectorStyles.NoPaddingButtonStyle, GUILayout.Width(18))) {
var arms = new List<GameObject>(firstPersonArms);
arms.RemoveAt(i);
firstPersonArms = arms.ToArray();
var animators = new List<RuntimeAnimatorController>(firstPersonArmsAnimator);
animators.RemoveAt(i);
firstPersonArmsAnimator = animators.ToArray();
break;
}
GUILayout.EndHorizontal();
}
}
/// <summary>
/// Draws the controls for the objects that will be hidden while in first person view.
/// </summary>
private void DrawFirstPersonHiddenObjects(ref GameObject[] firstPersonObjects)
{
if (firstPersonObjects == null || firstPersonObjects.Length == 0) {
firstPersonObjects = new GameObject[1];
}
for (int i = 0; i < firstPersonObjects.Length; ++i) {
GUILayout.BeginHorizontal();
var guiContent = new GUIContent(i == 0 ? "Third Person Objects" : " ", "Third person objects that should be hidden when the first person view is active (character arms and head).");
firstPersonObjects[i] = EditorGUILayout.ObjectField(guiContent, firstPersonObjects[i], typeof(GameObject), true) as GameObject;
if (i == firstPersonObjects.Length - 1 && firstPersonObjects[i] != null) {
Array.Resize(ref firstPersonObjects, firstPersonObjects.Length + 1);
break;
}
if (i != firstPersonObjects.Length - 1 && GUILayout.Button(InspectorStyles.RemoveIcon, InspectorStyles.NoPaddingButtonStyle, GUILayout.Width(18))) {
var list = new List<GameObject>(firstPersonObjects);
list.RemoveAt(i);
firstPersonObjects = list.ToArray();
break;
}
GUILayout.EndHorizontal();
}
}
/// <summary>
/// Draws the controls for the advanced character components.
/// </summary>
private void DrawAdvancedComponents(bool addAnimator, ref bool aiAgent, ref bool navMeshAgent, ref bool items, ref Inventory.ItemCollection itemCollection, ref bool health,ref bool unityIK,
ref bool footEffects, bool drawRagdoll, bool showError, GameObject character)
{
aiAgent = EditorGUILayout.Toggle("AI Agent", aiAgent);
if (aiAgent) {
EditorGUI.indentLevel++;
navMeshAgent = EditorGUILayout.Toggle("NavMeshAgent", navMeshAgent);
EditorGUI.indentLevel--;
}
items = EditorGUILayout.Toggle("Items", items);
if (items) {
EditorGUI.indentLevel++;
itemCollection = EditorGUILayout.ObjectField("Item Collection", itemCollection, typeof(Inventory.ItemCollection), false) as Inventory.ItemCollection;
if (itemCollection == null) {
EditorGUILayout.HelpBox("An ItemCollection needs to be specified for the character to be created.", MessageType.Error);
}
EditorGUI.indentLevel--;
}
health = EditorGUILayout.Toggle("Health", health);
unityIK = EditorGUILayout.Toggle("Unity IK", unityIK);
if (unityIK && !IsValidHumanoid(character) && showError) {
EditorGUILayout.HelpBox("The Unity IK component requires a humanoid character with an Animator.", MessageType.Error);
}
footEffects = EditorGUILayout.Toggle("Foot Effects", footEffects);
if (footEffects && !addAnimator && showError) {
EditorGUILayout.HelpBox("The foot effects component requires an Animator.", MessageType.Error);
}
if (drawRagdoll) {
m_AddRagdoll = EditorGUILayout.Toggle("Ragdoll", m_AddRagdoll);
if (m_AddRagdoll && !IsValidHumanoid(character) && showError) {
EditorGUILayout.HelpBox("Unity's ragdoll system requires a humanoid character with an Animator.", MessageType.Error);
}
}
}
/// <summary>
/// Draws the fields related to the profile.
/// </summary>
private void DrawProfileFields(ref StateConfiguration stateConfiguration, ref int profileIndex, ref string profileName, GameObject character)
{
var updatedStateConfiguration = EditorGUILayout.ObjectField("State Configuration", stateConfiguration, typeof(StateConfiguration), false) as StateConfiguration;
if (updatedStateConfiguration != stateConfiguration) {
if (updatedStateConfiguration != null) {
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(updatedStateConfiguration)));
} else {
EditorPrefs.SetString(ManagerUtility.LastStateConfigurationGUIDString, string.Empty);
}
stateConfiguration = updatedStateConfiguration;
}
EditorGUI.indentLevel++;
if (stateConfiguration != null) {
var profiles = stateConfiguration.GetProfilesForGameObject(character, StateConfiguration.Profile.ProfileType.Character);
// The character can be added without any profiles.
profiles.Insert(0, "(None)");
profileIndex = EditorGUILayout.Popup("Profile", profileIndex, profiles.ToArray());
profileName = profiles[profileIndex];
}
EditorGUI.indentLevel--;
}
/// <summary>
/// Draws the controls for an existing character.
/// </summary>
private void DrawExistingCharacter()
{
var character = EditorGUILayout.ObjectField("Character", m_ExistingCharacter, typeof(GameObject), true) as GameObject;
if (character != m_ExistingCharacter) {
m_ExistingCharacter = character;
if (m_ExistingCharacter != null) {
m_ExistingAIAgent = IsAIAgent(m_ExistingCharacter);
if (m_ExistingAIAgent) {
m_ExistingNavMeshAgent = HasNavMeshAgent(m_ExistingCharacter);
} else {
m_ExistingNavMeshAgent = false;
}
if (!HasEssentials(m_ExistingCharacter, m_ExistingPerspective == Perspective.Both)) {
EditorGUILayout.HelpBox("Error: The character doesn't contain all of the essential components. Press \"Add\" to add the missing components.", MessageType.Error);
if (GUILayout.Button("Add")) {
CharacterBuilder.AddEssentials(m_ExistingCharacter, m_ExistingAnimator, m_ExistingAnimatorController, m_ExistingPerspective == Perspective.Both, m_InvisibleShadowCaster, m_ExistingAIAgent);
}
}
m_ExistingPerspective = CurrentPerspective(m_ExistingCharacter);
m_ExistingAnimator = HasAnimator(m_ExistingCharacter);
if (m_ExistingAnimator) {
var animator = m_ExistingCharacter.GetComponent<Animator>();
m_ExistingAnimatorController = animator.runtimeAnimatorController;
m_ExistingModelType = IsValidHumanoid(m_ExistingCharacter) ? ModelType.Humanoid : ModelType.Generic;
}
#if FIRST_PERSON_CONTROLLER
// Find any existing first person arms.
var firstPersonBaseObjects = m_ExistingCharacter.GetComponentsInChildren<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>();
var existingFirstPersonArms = new List<GameObject>();
m_ExistingFirstPersonArmsAnimatorController = new RuntimeAnimatorController[firstPersonBaseObjects.Length];
for (int i = 0; i < firstPersonBaseObjects.Length; ++i) {
existingFirstPersonArms.Add(firstPersonBaseObjects[i].gameObject);
var animator = firstPersonBaseObjects[i].GetComponent<Animator>();
if (animator != null) {
m_ExistingFirstPersonArmsAnimatorController[i] = animator.runtimeAnimatorController;
}
}
m_OriginalExistingFirstPersonArms = m_ExistingFirstPersonArms = existingFirstPersonArms.ToArray();
#endif
// Search for any existing first person hidden objects.
var renderers = m_ExistingCharacter.GetComponentsInChildren<Renderer>();
var existingFirstPersonObjects = new List<GameObject>();
for (int i = 0; i < renderers.Length; ++i) {
if (renderers[i].GetComponent<Character.Identifiers.ThirdPersonObject>() != null) {
existingFirstPersonObjects.Add(renderers[i].gameObject);
continue;
}
var addGameObject = false;
var materials = renderers[i].sharedMaterials;
for (int j = 0; j < materials.Length; ++j) {
if (materials[j] == m_InvisibleShadowCaster) {
addGameObject = true;
break;
}
}
if (addGameObject) {
existingFirstPersonObjects.Add(renderers[i].gameObject);
}
}
m_OriginalExistingFirstPersonHiddenObjects = m_ExistingFirstPersonHiddenObjects = existingFirstPersonObjects.ToArray();
m_ExistingItems = HasItems(m_ExistingCharacter, m_ExistingAIAgent, m_ExistingPerspective != Perspective.Third);
if (m_ExistingItems) {
var itemSetManager = m_ExistingCharacter.GetComponent<Inventory.ItemSetManager>();
if (itemSetManager != null) {
m_ExistingItemCollection = itemSetManager.ItemCollection;
}
}
m_ExistingHealth = HasHealth(m_ExistingCharacter);
m_ExistingUnityIK = HasUnityIK(m_ExistingCharacter);
m_ExistingFootEffects = HasFootEffects(m_ExistingCharacter);
} else {
m_OriginalExistingFirstPersonArms = m_ExistingFirstPersonArms = m_OriginalExistingFirstPersonHiddenObjects = m_ExistingFirstPersonHiddenObjects = null;
}
}
var validCharacter = CheckValidCharacter(m_ExistingCharacter, false);
GUI.enabled = validCharacter;
DrawPerspective(ref m_ExistingPerspective);
GUI.enabled = validCharacter && m_ExistingPerspective == Perspective.First;
DrawAnimator(m_ExistingCharacter, m_ExistingPerspective != Perspective.First, validCharacter, ref m_ExistingAnimator, ref m_ExistingModelType, ref m_ExistingAnimatorController);
GUI.enabled = validCharacter;
if (m_ExistingPerspective == Perspective.First || m_ExistingPerspective == Perspective.Both) {
GUILayout.Space(7);
DrawFirstPersonArms(ref m_ExistingFirstPersonArms, ref m_ExistingFirstPersonArmsAnimatorController);
if (m_ExistingCharacter != null) {
GUILayout.Space(5);
DrawFirstPersonHiddenObjects(ref m_ExistingFirstPersonHiddenObjects);
}
GUILayout.Space(7);
}
DrawAdvancedComponents(m_ExistingAnimator, ref m_ExistingAIAgent, ref m_ExistingNavMeshAgent, ref m_ExistingItems, ref m_ExistingItemCollection,
ref m_ExistingHealth, ref m_ExistingUnityIK, ref m_ExistingFootEffects, false, validCharacter, m_ExistingCharacter);
DrawProfileFields(ref m_ExistingStateConfiguration, ref m_ExistingProfileIndex, ref m_ExistingProfileName, m_ExistingCharacter);
GUILayout.Space(5);
if (GUILayout.Button("Update Character")) {
if (m_ExistingPerspective != CurrentPerspective(m_ExistingCharacter)) {
#if THIRD_PERSON_CONTROLLER
// If the perspective was switched from/to the both perspective then the perspective monitor needs to be added or removed.
var perspectiveMonitor = m_ExistingCharacter.GetComponent<UltimateCharacterController.ThirdPersonController.Character.PerspectiveMonitor>();
if (m_ExistingPerspective == Perspective.Both) {
if (perspectiveMonitor == null) {
m_ExistingCharacter.AddComponent<UltimateCharacterController.ThirdPersonController.Character.PerspectiveMonitor>();
}
} else if (perspectiveMonitor != null) {
UnityEngine.Object.DestroyImmediate(perspectiveMonitor, true);
}
#endif
#if FIRST_PERSON_CONTROLLER
// The First Person Objects component should also be added/removed if the character supports items.
if (HasItems(m_ExistingCharacter, m_ExistingAIAgent, false)) {
var firstPersonObjects = m_ExistingCharacter.GetComponentInChildren<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>();
if (m_ExistingPerspective != Perspective.Third && firstPersonObjects == null) {
var firstPersonObjectsGameObject = new GameObject("First Person Objects");
firstPersonObjectsGameObject.transform.parent = character.transform;
firstPersonObjectsGameObject.AddComponent<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>();
} else if (m_ExistingPerspective == Perspective.Third && firstPersonObjects != null) {
UnityEngine.Object.DestroyImmediate(firstPersonObjects, true);
}
}
#endif
}
if (m_ExistingAnimator != HasAnimator(m_ExistingCharacter)) {
if (m_ExistingAnimator) {
CharacterBuilder.AddAnimator(m_ExistingCharacter, m_ExistingAnimatorController, m_ExistingAIAgent);
} else {
CharacterBuilder.RemoveAnimator(m_ExistingCharacter);
}
} else if (m_ExistingAnimator) {
// The animator controller may have changed.
var animator = m_ExistingCharacter.GetComponent<Animator>();
if (animator != null && animator.runtimeAnimatorController != m_ExistingAnimatorController) {
animator.runtimeAnimatorController = m_ExistingAnimatorController;
}
}
#if FIRST_PERSON_CONTROLLER
// The arms may have changed.
var firstPersonArmsChange = (m_OriginalExistingFirstPersonArms != null && m_OriginalExistingFirstPersonArms.Length != (m_ExistingFirstPersonArms.Length - 1)) ||
(m_OriginalExistingFirstPersonArms == null && m_ExistingFirstPersonArms.Length > 1);
if (m_OriginalExistingFirstPersonArms != null && !firstPersonArmsChange) {
for (int i = 0; i < m_OriginalExistingFirstPersonArms.Length; ++i) {
var containsObject = false;
for (int j = 0; j < m_ExistingFirstPersonArms.Length; ++j) {
if (m_OriginalExistingFirstPersonArms[i] == m_ExistingFirstPersonArms[j]) {
containsObject = true;
break;
}
}
if (!containsObject) {
firstPersonArmsChange = true;
break;
}
}
}
if (firstPersonArmsChange) {
// Remove the original arms who are no longer used.
if (m_OriginalExistingFirstPersonArms != null) {
for (int i = 0; i < m_OriginalExistingFirstPersonArms.Length; ++i) {
if (m_OriginalExistingFirstPersonArms[i] == null) {
continue;
}
var remove = true;
for (int j = 0; j < m_ExistingFirstPersonArms.Length; ++j) {
if (m_OriginalExistingFirstPersonArms[i] == m_ExistingFirstPersonArms[j]) {
remove = false;
break;
}
}
if (remove) {
UnityEngine.Object.DestroyImmediate(m_OriginalExistingFirstPersonArms[i], true);
}
}
}
// Add the new objects.
var firstPersonObjects = m_ExistingCharacter.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
for (int i = 0; i < m_ExistingFirstPersonArms.Length; ++i) {
if (m_ExistingFirstPersonArms[i] == null) {
continue;
}
var add = true;
for (int j = 0; j < m_OriginalExistingFirstPersonArms.Length; ++j) {
if (m_ExistingFirstPersonArms[i] == m_OriginalExistingFirstPersonArms[j]) {
add = false;
break;
}
}
if (add) {
if (EditorUtility.IsPersistent(m_ExistingFirstPersonArms[i])) {
var name = m_ExistingFirstPersonArms[i].name;
m_ExistingFirstPersonArms[i] = GameObject.Instantiate(m_ExistingFirstPersonArms[i]) as GameObject;
m_ExistingFirstPersonArms[i].name = name;
}
ItemBuilder.AddFirstPersonArms(m_ExistingCharacter, m_ExistingFirstPersonArms[i], m_ExistingFirstPersonArmsAnimatorController[i]);
m_ExistingFirstPersonArms[i].transform.SetParentOrigin(firstPersonObjects.transform);
}
}
}
#endif
// Determine if the hidden objects have changed.
var firstPersonHiddenObjectChange = (m_OriginalExistingFirstPersonHiddenObjects != null && m_ExistingFirstPersonHiddenObjects.Length != (m_ExistingFirstPersonHiddenObjects.Length - 1)) ||
(m_OriginalExistingFirstPersonHiddenObjects == null && m_ExistingFirstPersonHiddenObjects.Length > 1);
if (m_OriginalExistingFirstPersonHiddenObjects != null && !firstPersonHiddenObjectChange) {
for (int i = 0; i < m_OriginalExistingFirstPersonHiddenObjects.Length; ++i) {
var containsObject = false;
for (int j = 0; j < m_ExistingFirstPersonHiddenObjects.Length; ++j) {
if (m_OriginalExistingFirstPersonHiddenObjects[i] == m_ExistingFirstPersonHiddenObjects[j]) {
containsObject = true;
break;
}
}
if (!containsObject) {
firstPersonHiddenObjectChange = true;
break;
}
}
}
if (firstPersonHiddenObjectChange) {
// Remove all of the original hidden objects before adding them back again.
if (m_OriginalExistingFirstPersonHiddenObjects != null) {
for (int i = 0; i < m_OriginalExistingFirstPersonHiddenObjects.Length; ++i) {
if (m_OriginalExistingFirstPersonHiddenObjects[i] == null) {
continue;
}
Character.Identifiers.ThirdPersonObject thirdPersonObject;
if ((thirdPersonObject = m_OriginalExistingFirstPersonHiddenObjects[i].GetComponent<Character.Identifiers.ThirdPersonObject>())) {
UnityEngine.Object.DestroyImmediate(thirdPersonObject, true);
continue;
}
var renderers = m_OriginalExistingFirstPersonHiddenObjects[i].GetComponents<Renderer>();
for (int j = 0; j < renderers.Length; ++j) {
var materials = renderers[j].sharedMaterials;
for (int k = 0; k < materials.Length; ++k) {
if (materials[k] == m_InvisibleShadowCaster) {
materials[k] = null;
}
}
renderers[j].sharedMaterials = materials;
}
}
}
var addThirdPersonObject = false;
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
var networkInfo = m_ExistingCharacter.GetComponent<Networking.INetworkInfo>();
if (networkInfo != null) {
addThirdPersonObject = true;
}
#endif
if (!addThirdPersonObject) {
var characterLocomotion = m_ExistingCharacter.GetComponent<UltimateCharacterLocomotion>();
characterLocomotion.DeserializeMovementTypes();
var movementTypes = characterLocomotion.MovementTypes;
for (int i = 0; i < movementTypes.Length; ++i) {
if (movementTypes[i].GetType().FullName.Contains("ThirdPerson")) {
addThirdPersonObject = true;
break;
}
}
}
// All of the original hidden objects have been removed. Add the new objects.
for (int i = 0; i < m_ExistingFirstPersonHiddenObjects.Length; ++i) {
if (m_ExistingFirstPersonHiddenObjects[i] == null) {
continue;
}
if (!addThirdPersonObject) {
var renderers = m_ExistingFirstPersonHiddenObjects[i].GetComponents<Renderer>();
for (int j = 0; j < renderers.Length; ++j) {
var materials = renderers[j].sharedMaterials;
for (int k = 0; k < materials.Length; ++k) {
materials[k] = m_InvisibleShadowCaster;
}
renderers[j].sharedMaterials = materials;
}
} else {
// The PerspectiveMonitor component is responsible for switching out the material.
m_ExistingFirstPersonHiddenObjects[i].AddComponent<Character.Identifiers.ThirdPersonObject>();
}
}
InspectorUtility.SetDirty(m_ExistingCharacter);
m_OriginalExistingFirstPersonHiddenObjects = m_ExistingFirstPersonHiddenObjects;
// An empty element will occupy the last existing slot.
if (m_OriginalExistingFirstPersonHiddenObjects != null && m_OriginalExistingFirstPersonHiddenObjects.Length > 0) {
Array.Resize(ref m_OriginalExistingFirstPersonHiddenObjects, m_OriginalExistingFirstPersonHiddenObjects.Length - 1);
}
}
if (m_ExistingAIAgent != IsAIAgent(m_ExistingCharacter)) {
if (m_ExistingAIAgent) {
CharacterBuilder.AddAIAgent(m_ExistingCharacter);
} else {
CharacterBuilder.RemoveAIAgent(m_ExistingCharacter);
}
}
if (m_ExistingNavMeshAgent != HasNavMeshAgent(m_ExistingCharacter)) {
if (m_ExistingNavMeshAgent) {
var characterLocomotion = m_ExistingCharacter.GetComponent<UltimateCharacterLocomotion>();
var abilities = characterLocomotion.Abilities;
var index = abilities != null ? abilities.Length : 0;
if (abilities != null) {
for (int i = 0; i < abilities.Length; ++i) {
if (abilities[i] is Character.Abilities.SpeedChange) {
index = i;
break;
}
}
}
// The ability should be positioned before the SpeedChange ability.
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.AI.NavMeshAgentMovement), index);
var navMeshAgent = m_ExistingCharacter.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (navMeshAgent != null) {
navMeshAgent.stoppingDistance = 0.1f;
}
} else {
AbilityBuilder.RemoveAbility<Character.Abilities.AI.NavMeshAgentMovement>(m_ExistingCharacter.GetComponent<UltimateCharacterLocomotion>());
var navMeshAgent = m_ExistingCharacter.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (navMeshAgent != null) {
GameObject.DestroyImmediate(navMeshAgent, true);
}
}
}
if (m_ExistingItems != HasItems(m_ExistingCharacter, m_ExistingAIAgent, m_ExistingPerspective != Perspective.Third)) {
if (m_ExistingItems) {
CharacterBuilder.AddItemSupport(m_ExistingCharacter, m_ExistingItemCollection, m_ExistingAIAgent, m_ExistingPerspective != Perspective.Third);
} else {
CharacterBuilder.RemoveItemSupport(m_ExistingCharacter);
}
}
if (m_ExistingHealth != HasHealth(m_ExistingCharacter)) {
if (m_ExistingHealth) {
CharacterBuilder.AddHealth(m_ExistingCharacter);
} else {
CharacterBuilder.RemoveHealth(m_ExistingCharacter);
}
}
if (m_ExistingUnityIK != HasUnityIK(m_ExistingCharacter)) {
if (m_ExistingUnityIK) {
if (IsValidHumanoid(m_ExistingCharacter)) {
CharacterBuilder.AddUnityIK(m_ExistingCharacter);
}
} else {
CharacterBuilder.RemoveUnityIK(m_ExistingCharacter);
}
}
if (m_ExistingFootEffects != HasFootEffects(m_ExistingCharacter)) {
if (m_ExistingFootEffects) {
CharacterBuilder.AddFootEffects(m_ExistingCharacter);
} else {
CharacterBuilder.RemoveFootEffects(m_ExistingCharacter);
}
}
if (m_ExistingStateConfiguration != null && m_ExistingProfileIndex > 0) {
m_ExistingStateConfiguration.AddStatesToGameObject(m_ExistingProfileName, m_ExistingCharacter);
InspectorUtility.SetDirty(m_ExistingCharacter);
}
}
GUI.enabled = true;
}
/// <summary>
/// Does the character have the essential components?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has the essential components.</returns>
private bool HasEssentials(GameObject character, bool usePerspectiveMonitor)
{
#if THIRD_PERSON_CONTROLLER
if (usePerspectiveMonitor && character.GetComponent<UltimateCharacterController.ThirdPersonController.Character.PerspectiveMonitor>() == null) {
return false;
}
#endif
return character.GetComponent<Rigidbody>() != null && character.GetComponent<UltimateCharacterLocomotion>() != null &&
character.GetComponent<UltimateCharacterLocomotionHandler>() && character.GetComponent<CharacterLayerManager>() != null;
}
/// <summary>
/// Retrieves the current perspective of the character.
/// </summary>
/// <param name="character">The character to determine the perspective of.</param>
/// <returns>The character's perspective.</returns>
private Perspective CurrentPerspective(GameObject character)
{
var hasBothComponents = false;
#if THIRD_PERSON_CONTROLLER
hasBothComponents = m_ExistingCharacter.GetComponentInChildren<UltimateCharacterController.ThirdPersonController.Character.PerspectiveMonitor>() != null;
#endif
if (hasBothComponents) {
// If the character has the perspective monitor then it can switch perspectives.
return Perspective.Both;
} else {
if (!m_ExistingAnimator) {
// If the character doesn't have an animator then it has to be in first person.
return Perspective.First;
} else {
// Use the movement types to determine the perspective.
var perspective = Perspective.Third;
var characterLocomotion = m_ExistingCharacter.GetComponent<UltimateCharacterLocomotion>();
if (characterLocomotion != null) {
characterLocomotion.DeserializeMovementTypes();
var movementTypes = characterLocomotion.MovementTypes;
for (int i = 0; i < movementTypes.Length; ++i) {
if (movementTypes[i].GetType().Namespace.Contains("FirstPersonController")) {
perspective = Perspective.First;
break;
}
}
}
return perspective;
}
}
}
/// <summary>
/// Does the character have an animator?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has an animator.</returns>
private bool HasAnimator(GameObject character)
{
return character.GetComponent<Animator>() && character.GetComponent<AnimatorMonitor>();
}
/// <summary>
/// Is the character an AI agent?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character is an AI agent.</returns>
private bool IsAIAgent(GameObject character)
{
return character.GetComponent<LocalLookSource>() && !character.GetComponent<UltimateCharacterLocomotionHandler>() && !character.GetComponent<ItemHandler>();
}
/// <summary>
/// Does the character have the NavMeshAgent components?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has the NavMeshAgent components.</returns>
private bool HasNavMeshAgent(GameObject character)
{
return character.GetComponent<UnityEngine.AI.NavMeshAgent>() != null && character.GetComponent<UltimateCharacterLocomotion>().GetAbility<Character.Abilities.AI.NavMeshAgentMovement>() != null;
}
/// <summary>
/// Does the character have the components required for items?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
/// <param name="checkFirstPersonObjects">Should the FirstPersonObjects component be checked?</param>
/// <returns>True if the character has the components required for items.</returns>
private bool HasItems(GameObject character, bool aiAgent, bool checkFirstPersonObjects)
{
if ((!aiAgent && character.GetComponent<ItemHandler>() == null) || character.GetComponentInChildren<Items.ItemPlacement>() == null || character.GetComponent<AnimatorMonitor>() == null) {
return false;
}
#if FIRST_PERSON_CONTROLLER
if (checkFirstPersonObjects && character.GetComponentInChildren<UltimateCharacterController.FirstPersonController.Character.FirstPersonObjects>() == null) {
return false;
}
#endif
var animator = character.GetComponent<Animator>();
if (animator != null) {
var head = animator.GetBoneTransform(HumanBodyBones.Head);
if (head != null) {
var leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
var rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
if (leftHand != null && rightHand != null) {
if (leftHand.GetComponentInChildren<Items.ItemSlot>() == null || rightHand.GetComponentInChildren<Items.ItemSlot>() == null) {
return false;
}
}
}
}
return character.GetComponent<Inventory.Inventory>() && character.GetComponent<Inventory.ItemSetManager>();
}
/// <summary>
/// Does the character have the health components?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has the health components.</returns>
private bool HasHealth(GameObject character)
{
return character.GetComponent<Traits.CharacterHealth>() && character.GetComponent<Traits.AttributeManager>() && character.GetComponent<Traits.CharacterRespawner>();
}
/// <summary>
/// Does the character have the CharacterIK component?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has the CharacterIK component.</returns>
private bool HasUnityIK(GameObject character)
{
return character.GetComponent<CharacterIK>();
}
/// <summary>
/// Does the character have the CharacterFootEffects component?
/// </summary>
/// <param name="character">The GameObject of the character to determine if it has the required components.</param>
/// <returns>True if the character has the CharacterFootEffects component.</returns>
private bool HasFootEffects(GameObject character)
{
return character.GetComponent<CharacterFootEffects>();
}
}
}