This commit is contained in:
2026-06-14 23:57:44 +07:00
parent 20f9010787
commit 78d7b2f5a7
5775 changed files with 4796241 additions and 5 deletions

View File

@@ -0,0 +1,754 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Utility.Builders
{
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Character.Abilities.Items;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.StateSystem;
using System;
using System.Collections.Generic;
/// <summary>
/// Adds and serializes UltimateCharacterLocomotion abilities.
/// </summary>
public static class AbilityBuilder
{
private static Dictionary<Type, UnityEngine.RequireComponent[]> s_RequiredComponents = new Dictionary<Type, UnityEngine.RequireComponent[]>();
private static Dictionary<Type, DefaultInputName[]> s_DefaultInputName = new Dictionary<Type, DefaultInputName[]>();
private static Dictionary<Type, DefaultStartType> s_DefaultStartType = new Dictionary<Type, DefaultStartType>();
private static Dictionary<Type, DefaultStopType> s_DefaultStopType = new Dictionary<Type, DefaultStopType>();
private static Dictionary<Type, DefaultAbilityIndex> s_DefaultAbilityIndex = new Dictionary<Type, DefaultAbilityIndex>();
private static Dictionary<Type, DefaultAbilityIntData> s_DefaultAbilityIntData = new Dictionary<Type, DefaultAbilityIntData>();
private static Dictionary<Type, DefaultItemStateIndex> s_DefaultItemStateIndex = new Dictionary<Type, DefaultItemStateIndex>();
private static Dictionary<Type, DefaultState> s_DefaultState = new Dictionary<Type, DefaultState>();
private static Dictionary<Type, DefaultAllowPositionalInput> s_DefaultAllowPositionalInput = new Dictionary<Type, DefaultAllowPositionalInput>();
private static Dictionary<Type, DefaultAllowRotationalInput> s_DefaultAllowRotationalInput = new Dictionary<Type, DefaultAllowRotationalInput>();
private static Dictionary<Type, DefaultUseGravity> s_DefaultUseGravity = new Dictionary<Type, DefaultUseGravity>();
private static Dictionary<Type, DefaultUseRootMotionPosition> s_DefaultUseRootMotionPosition = new Dictionary<Type, DefaultUseRootMotionPosition>();
private static Dictionary<Type, DefaultUseRootMotionRotation> s_DefaultUseRootMotionRotation = new Dictionary<Type, DefaultUseRootMotionRotation>();
private static Dictionary<Type, DefaultDetectHorizontalCollisions> s_DefaultDetectHorizontalCollisions = new Dictionary<Type, DefaultDetectHorizontalCollisions>();
private static Dictionary<Type, DefaultDetectVerticalCollisions> s_DefaultDetectVerticalCollisions = new Dictionary<Type, DefaultDetectVerticalCollisions>();
private static Dictionary<Type, DefaultObjectDetection> s_DefaultObjectDetection = new Dictionary<Type, DefaultObjectDetection>();
private static Dictionary<Type, DefaultUseLookDirection> s_DefaultUseLookDirection = new Dictionary<Type, DefaultUseLookDirection>();
private static Dictionary<Type, DefaultCastOffset> s_DefaultCastOffset = new Dictionary<Type, DefaultCastOffset>();
private static Dictionary<Type, DefaultEquippedSlots> s_DefaultEquippedSlots = new Dictionary<Type, DefaultEquippedSlots>();
private static Dictionary<Type, DefaultReequipSlots> s_DefaultReequipSlots = new Dictionary<Type, DefaultReequipSlots>();
private static Dictionary<Type, AddState[]> s_AddStates = new Dictionary<Type, AddState[]>();
/// <summary>
/// Adds the ability with the specified type.
/// </summary>
/// <param name="characterLocomotion">The character to add the ability to.</param>
/// <param name="abilityType">The type of ability to add.</param>
/// <returns>The added ability.</returns>
public static Ability AddAbility(UltimateCharacterLocomotion characterLocomotion, Type abilityType)
{
if (typeof(ItemAbility).IsAssignableFrom(abilityType)) {
return AddItemAbility(characterLocomotion, abilityType);
}
var abilities = characterLocomotion.GetSerializedAbilities();
var index = abilities == null ? 0 : abilities.Length;
return AddAbility(characterLocomotion, abilityType, index);
}
/// <summary>
/// Adds the ability with the specified type.
/// </summary>
/// <param name="characterLocomotion">The character to add the ability to.</param>
/// <param name="abilityType">The type of ability to add.</param>
/// <param name="index">The index to add the ability to.</param>
/// <returns>The added ability.</returns>
public static Ability AddAbility(UltimateCharacterLocomotion characterLocomotion, Type abilityType, int index)
{
var abilities = characterLocomotion.GetSerializedAbilities();
if (abilities == null) {
abilities = new Ability[1];
} else {
Array.Resize(ref abilities, abilities.Length + 1);
}
var ability = Activator.CreateInstance(abilityType) as Ability;
// Assign the default values specified by any added attribtes.
SetAbilityDefaultValues(ability);
for (int i = abilities.Length - 1; i > index; --i) {
abilities[i] = abilities[i - 1];
}
abilities[index] = ability;
characterLocomotion.Abilities = abilities;
SerializeAbilities(characterLocomotion);
// The ability may require other components in order to operate.
var requiredComponents = GetRequiredComponents(abilityType);
if (requiredComponents != null && requiredComponents.Length > 0) {
for (int i = 0; i < requiredComponents.Length; ++i) {
characterLocomotion.gameObject.AddComponent(requiredComponents[i].m_Type0);
}
}
return ability;
}
/// <summary>
/// Adds the item ability with the specified type.
/// </summary>
/// <param name="characterLocomotion">The character to add the ability to.</param>
/// <param name="abilityType">The type of ability to add.</param>
/// <returns>The added ability.</returns>
public static ItemAbility AddItemAbility(UltimateCharacterLocomotion characterLocomotion, Type abilityType)
{
var itemAbilities = characterLocomotion.GetSerializedItemAbilities();
var index = itemAbilities == null ? 0 : itemAbilities.Length;
return AddItemAbility(characterLocomotion, abilityType, index);
}
/// <summary>
/// Adds the item ability with the specified type.
/// </summary>
/// <param name="characterLocomotion">The character to add the ability to.</param>
/// <param name="abilityType">The type of ability to add.</param>
/// <returns>The added ability.</returns>
public static ItemAbility AddItemAbility(UltimateCharacterLocomotion characterLocomotion, Type abilityType, int index)
{
var itemAbilities = characterLocomotion.GetSerializedItemAbilities();
if (itemAbilities == null) {
itemAbilities = new ItemAbility[1];
} else {
Array.Resize(ref itemAbilities, itemAbilities.Length + 1);
}
var itemAbility = Activator.CreateInstance(abilityType) as ItemAbility;
// Assign the default values specified by any added attribtes.
SetAbilityDefaultValues(itemAbility);
for (int i = itemAbilities.Length - 1; i > index; --i) {
itemAbilities[i] = itemAbilities[i - 1];
}
itemAbilities[itemAbilities.Length - 1] = itemAbility;
characterLocomotion.ItemAbilities = itemAbilities;
SerializeItemAbilities(characterLocomotion);
return itemAbility;
}
/// <summary>
/// Serialize all of the abilities to the AbilityData array.
/// </summary>
/// <param name="characterLocomotion">The character to serialize.</param>
public static void SerializeAbilities(UltimateCharacterLocomotion characterLocomotion)
{
var abilities = characterLocomotion.Abilities == null ? new List<Ability>() : new List<Ability>(characterLocomotion.Abilities);
characterLocomotion.AbilityData = Shared.Utility.Serialization.Serialize<Ability>(abilities);
characterLocomotion.Abilities = abilities.ToArray();
#if UNITY_EDITOR
UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(characterLocomotion);
#endif
}
/// <summary>
/// Serialize all of the item abilities to the ItemAbilityData array.
/// </summary>
/// <param name="characterLocomotion">The character to serialize.</param>
public static void SerializeItemAbilities(UltimateCharacterLocomotion characterLocomotion)
{
var itemAbilities = characterLocomotion.ItemAbilities == null ? new List<ItemAbility>() : new List<ItemAbility>(characterLocomotion.ItemAbilities);
characterLocomotion.ItemAbilityData = Shared.Utility.Serialization.Serialize<ItemAbility>(itemAbilities);
characterLocomotion.ItemAbilities = itemAbilities.ToArray();
#if UNITY_EDITOR
UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(characterLocomotion);
#endif
}
/// <summary>
/// Removes the specified ability from the ability array.
/// </summary>
/// <param name="characterLocomotion">The character to remove the ability from.</param>
public static void RemoveAbility<T>(UltimateCharacterLocomotion characterLocomotion) where T : Ability
{
var ability = characterLocomotion.GetAbility<T>();
if (ability != null) {
RemoveAbility(characterLocomotion, ability);
}
}
/// <summary>
/// Removes the specified ability from the ability array.
/// </summary>
/// <param name="characterLocomotion">The character to remove the ability from.</param>
/// <param name="ability">The ability to remove.</param>
public static void RemoveAbility(UltimateCharacterLocomotion characterLocomotion, Ability ability)
{
if (ability == null) {
return;
}
if (typeof(ItemAbility).IsAssignableFrom(ability.GetType())) {
RemoveItemAbility(characterLocomotion, ability);
return;
}
var abilities = new Ability[characterLocomotion.Abilities.Length - 1];
var index = 0;
for (int i = 0; i < characterLocomotion.Abilities.Length; ++i) {
if (characterLocomotion.Abilities[i] != ability) {
abilities[index] = characterLocomotion.Abilities[i];
index++;
}
}
characterLocomotion.Abilities = abilities;
SerializeAbilities(characterLocomotion);
}
/// <summary>
/// Removes the specified ability from the item ability array.
/// </summary>
/// <param name="characterLocomotion">The character to remove the ability from.</param>
/// <param name="ability">The ability to remove.</param>
public static void RemoveItemAbility(UltimateCharacterLocomotion characterLocomotion, Ability ability)
{
var abilities = new ItemAbility[characterLocomotion.ItemAbilities.Length - 1];
var index = 0;
for (int i = 0; i < characterLocomotion.ItemAbilities.Length; ++i) {
if (characterLocomotion.ItemAbilities[i] != ability) {
abilities[index] = characterLocomotion.ItemAbilities[i];
}
}
characterLocomotion.ItemAbilities = abilities;
SerializeItemAbilities(characterLocomotion);
}
/// <summary>
/// Returns the RequiredComponent of the specified ability type.
/// </summary>
/// <param name="abilityType">The type of ability.</param>
/// <returns>The RequiredComponent of the specified ability type. Can be null.</returns>
private static UnityEngine.RequireComponent[] GetRequiredComponents(Type type)
{
UnityEngine.RequireComponent[] requiredComponents;
if (s_RequiredComponents.TryGetValue(type, out requiredComponents)) {
return requiredComponents;
}
if (type.GetCustomAttributes(typeof(UnityEngine.RequireComponent), true).Length > 0) {
requiredComponents = type.GetCustomAttributes(typeof(UnityEngine.RequireComponent), true) as UnityEngine.RequireComponent[];
}
s_RequiredComponents.Add(type, requiredComponents);
return requiredComponents;
}
/// <summary>
/// Sets the default values for the ability.
/// </summary>
/// <param name="ability">The ability to set the default values of.</param>
private static void SetAbilityDefaultValues(Ability ability)
{
var abilityType = ability.GetType();
var defaultInputNames = GetDefaultInputNames(abilityType);
if (defaultInputNames != null && defaultInputNames.Length > 0) {
ability.InputNames = new string[defaultInputNames.Length];
for (int i = 0; i < defaultInputNames.Length; ++i) {
ability.InputNames[defaultInputNames[i].Index] = defaultInputNames[i].InputName;
}
}
var defaultStartType = GetDefaultStartType(abilityType);
if (defaultStartType != null) {
ability.StartType = defaultStartType.StartType;
}
var defaultStopType = GetDefaultStopType(abilityType);
if (defaultStopType != null) {
ability.StopType = defaultStopType.StopType;
}
var defaultAbilityIndex = GetDefaultAbilityIndex(abilityType);
if (defaultAbilityIndex != null) {
ability.AbilityIndexParameter = defaultAbilityIndex.Value;
}
var defaultAbilityIntData = GetDefaultAbilityIntData(abilityType);
if (defaultAbilityIntData != null) {
ability.AbilityIntData = defaultAbilityIntData.Value;
}
var defaultState = GetDefaultState(abilityType);
if (defaultState != null) {
ability.State = defaultState.Value;
}
if (typeof(ItemAbility).IsAssignableFrom(abilityType)) {
var defaultItemStateIndex = GetDefaultItemStateIndex(abilityType);
if (defaultItemStateIndex != null) {
(ability as ItemAbility).ItemStateIndex = defaultItemStateIndex.Value;
}
}
var defaultAllowPositionalInput = GetDefaultAllowPositionalInput(abilityType);
if (defaultAllowPositionalInput != null) {
ability.AllowPositionalInput = defaultAllowPositionalInput.Value;
}
var defaultAllowRotationalInput = GetDefaultAllowRotationalInput(abilityType);
if (defaultAllowRotationalInput != null) {
ability.AllowRotationalInput = defaultAllowRotationalInput.Value;
}
var defaultUseGravity = GetDefaultUseGravity(abilityType);
if (defaultUseGravity != null) {
ability.UseGravity = defaultUseGravity.Value;
}
var defaultUseRootMotionPosition = GetDefaultUseRootMotionPosition(abilityType);
if (defaultUseRootMotionPosition != null) {
ability.UseRootMotionPosition = defaultUseRootMotionPosition.Value;
}
var defaultUseRootMotionRotation = GetDefaultUseRootMotionRotation(abilityType);
if (defaultUseRootMotionRotation != null) {
ability.UseRootMotionRotation = defaultUseRootMotionRotation.Value;
}
var defaultDetectHorizontalCollisions = GetDefaultDetectHorizontalCollisions(abilityType);
if (defaultDetectHorizontalCollisions != null) {
ability.DetectHorizontalCollisions = defaultDetectHorizontalCollisions.Value;
}
var defaultDetectVerticalCollisions = GetDefaultDetectVerticalCollisions(abilityType);
if (defaultDetectVerticalCollisions != null) {
ability.DetectVerticalCollisions = defaultDetectVerticalCollisions.Value;
}
if (ability is DetectObjectAbilityBase) {
var defaultObjectDetection = GetDefaultObjectDetection(abilityType);
if (defaultObjectDetection != null) {
(ability as DetectObjectAbilityBase).ObjectDetection = defaultObjectDetection.Value;
// If the detection layer is a trigger then the layer should include the ignore layer.
if ((defaultObjectDetection.Value & DetectObjectAbilityBase.ObjectDetectionMode.Trigger) != 0) {
(ability as DetectObjectAbilityBase).DetectLayers |= 1 << LayerManager.IgnoreRaycast;
}
}
var defaultUseLookDirection = GetDefaultUseLookDirection(abilityType);
if (defaultUseLookDirection != null) {
(ability as DetectObjectAbilityBase).UseLookDirection = defaultUseLookDirection.Value;
}
var defaultCastOffset = GetDefaultCastOffset(abilityType);
if (defaultCastOffset != null) {
(ability as DetectObjectAbilityBase).CastOffset = defaultCastOffset.Value;
}
var defaultEquippedSlots = GetDefaultEquippedSlots(abilityType);
if (defaultEquippedSlots != null) {
(ability as DetectObjectAbilityBase).AllowEquippedSlotsMask = defaultEquippedSlots.Value;
}
var defaultReequipSlots = GetDefaultReequipSlots(abilityType);
if (defaultReequipSlots != null) {
(ability as DetectObjectAbilityBase).ReequipSlots = defaultReequipSlots.Value;
}
}
#if UNITY_EDITOR
var addStates = GetAddStates(abilityType);
if (addStates != null && addStates.Length > 0) {
var states = ability.States;
var addedStates = 0;
var stateLength = states.Length;
Array.Resize(ref states, stateLength + addStates.Length);
// Default must always be at the end.
states[states.Length - 1] = states[0];
for (int i = 0; i < addStates.Length; ++i) {
var presetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(addStates[i].PresetGUID);
if (!string.IsNullOrEmpty(presetPath)) {
var preset = UnityEditor.AssetDatabase.LoadAssetAtPath(presetPath, typeof(PersistablePreset)) as PersistablePreset;
if (preset != null) {
states[i] = new State(addStates[i].Name, preset, null);
addedStates++;
}
}
}
if (addedStates != addStates.Length) {
Array.Resize(ref states, stateLength + addedStates);
}
ability.States = states;
}
#endif
}
/// <summary>
/// Returns the DefaultInputName of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultInputName of the specified ability type. Can be null.</returns>
private static DefaultInputName[] GetDefaultInputNames(Type type)
{
DefaultInputName[] defaultInputNames;
if (s_DefaultInputName.TryGetValue(type, out defaultInputNames)) {
return defaultInputNames;
}
if (type.GetCustomAttributes(typeof(DefaultInputName), true).Length > 0) {
defaultInputNames = type.GetCustomAttributes(typeof(DefaultInputName), true) as DefaultInputName[];
}
s_DefaultInputName.Add(type, defaultInputNames);
return defaultInputNames;
}
/// <summary>
/// Returns the DefaultStartType of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultStartType of the specified ability type. Can be null.</returns>
private static DefaultStartType GetDefaultStartType(Type type)
{
DefaultStartType defaultStartType;
if (s_DefaultStartType.TryGetValue(type, out defaultStartType)) {
return defaultStartType;
}
if (type.GetCustomAttributes(typeof(DefaultStartType), true).Length > 0) {
defaultStartType = type.GetCustomAttributes(typeof(DefaultStartType), true)[0] as DefaultStartType;
}
s_DefaultStartType.Add(type, defaultStartType);
return defaultStartType;
}
/// <summary>
/// Returns the DefaultStopType of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultStopType of the specified ability type. Can be null.</returns>
private static DefaultStopType GetDefaultStopType(Type type)
{
DefaultStopType defaultStopType;
if (s_DefaultStopType.TryGetValue(type, out defaultStopType)) {
return defaultStopType;
}
if (type.GetCustomAttributes(typeof(DefaultStopType), true).Length > 0) {
defaultStopType = type.GetCustomAttributes(typeof(DefaultStopType), true)[0] as DefaultStopType;
}
s_DefaultStopType.Add(type, defaultStopType);
return defaultStopType;
}
/// <summary>
/// Returns the DefaultAbilityIndex of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultAbilityIndex of the specified ability type. Can be null.</returns>
private static DefaultAbilityIndex GetDefaultAbilityIndex(Type type)
{
DefaultAbilityIndex defaultAbilityIndex;
if (s_DefaultAbilityIndex.TryGetValue(type, out defaultAbilityIndex)) {
return defaultAbilityIndex;
}
if (type.GetCustomAttributes(typeof(DefaultAbilityIndex), true).Length > 0) {
defaultAbilityIndex = type.GetCustomAttributes(typeof(DefaultAbilityIndex), true)[0] as DefaultAbilityIndex;
}
s_DefaultAbilityIndex.Add(type, defaultAbilityIndex);
return defaultAbilityIndex;
}
/// <summary>
/// Returns the DefaultAbilityIntData of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultAbilityIntData of the specified ability type. Can be null.</returns>
private static DefaultAbilityIntData GetDefaultAbilityIntData(Type type)
{
DefaultAbilityIntData defaultStateIndex;
if (s_DefaultAbilityIntData.TryGetValue(type, out defaultStateIndex)) {
return defaultStateIndex;
}
if (type.GetCustomAttributes(typeof(DefaultAbilityIntData), true).Length > 0) {
defaultStateIndex = type.GetCustomAttributes(typeof(DefaultAbilityIntData), true)[0] as DefaultAbilityIntData;
}
s_DefaultAbilityIntData.Add(type, defaultStateIndex);
return defaultStateIndex;
}
/// <summary>
/// Returns the DefaultItemStateIndex of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultItemStateIndex of the specified ability type. Can be null.</returns>
private static DefaultItemStateIndex GetDefaultItemStateIndex(Type type)
{
DefaultItemStateIndex defaultItemStateIndex;
if (s_DefaultItemStateIndex.TryGetValue(type, out defaultItemStateIndex)) {
return defaultItemStateIndex;
}
if (type.GetCustomAttributes(typeof(DefaultItemStateIndex), true).Length > 0) {
defaultItemStateIndex = type.GetCustomAttributes(typeof(DefaultItemStateIndex), true)[0] as DefaultItemStateIndex;
}
s_DefaultItemStateIndex.Add(type, defaultItemStateIndex);
return defaultItemStateIndex;
}
/// <summary>
/// Returns the DefaultState of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultState of the specified ability type. Can be null.</returns>
private static DefaultState GetDefaultState(Type type)
{
DefaultState defaultState;
if (s_DefaultState.TryGetValue(type, out defaultState)) {
return defaultState;
}
if (type.GetCustomAttributes(typeof(DefaultState), true).Length > 0) {
defaultState = type.GetCustomAttributes(typeof(DefaultState), true)[0] as DefaultState;
}
s_DefaultState.Add(type, defaultState);
return defaultState;
}
/// <summary>
/// Returns the DefaultAllowPositionalInput of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultAllowPositionalInput of the specified ability type. Can be null.</returns>
private static DefaultAllowPositionalInput GetDefaultAllowPositionalInput(Type type)
{
DefaultAllowPositionalInput defaultAllowPositionalInput;
if (s_DefaultAllowPositionalInput.TryGetValue(type, out defaultAllowPositionalInput)) {
return defaultAllowPositionalInput;
}
if (type.GetCustomAttributes(typeof(DefaultAllowPositionalInput), true).Length > 0) {
defaultAllowPositionalInput = type.GetCustomAttributes(typeof(DefaultAllowPositionalInput), true)[0] as DefaultAllowPositionalInput;
}
s_DefaultAllowPositionalInput.Add(type, defaultAllowPositionalInput);
return defaultAllowPositionalInput;
}
/// <summary>
/// Returns the DefaultAllowRotationalInput of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultAllowRotationalInput of the specified ability type. Can be null.</returns>
private static DefaultAllowRotationalInput GetDefaultAllowRotationalInput(Type type)
{
DefaultAllowRotationalInput defaultAllowRotationalInput;
if (s_DefaultAllowRotationalInput.TryGetValue(type, out defaultAllowRotationalInput)) {
return defaultAllowRotationalInput;
}
if (type.GetCustomAttributes(typeof(DefaultAllowRotationalInput), true).Length > 0) {
defaultAllowRotationalInput = type.GetCustomAttributes(typeof(DefaultAllowRotationalInput), true)[0] as DefaultAllowRotationalInput;
}
s_DefaultAllowRotationalInput.Add(type, defaultAllowRotationalInput);
return defaultAllowRotationalInput;
}
/// <summary>
/// Returns the DefaultUseGravity of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultUseGravity of the specified ability type. Can be null.</returns>
private static DefaultUseGravity GetDefaultUseGravity(Type type)
{
DefaultUseGravity defaultUseGravity;
if (s_DefaultUseGravity.TryGetValue(type, out defaultUseGravity)) {
return defaultUseGravity;
}
if (type.GetCustomAttributes(typeof(DefaultUseGravity), true).Length > 0) {
defaultUseGravity = type.GetCustomAttributes(typeof(DefaultUseGravity), true)[0] as DefaultUseGravity;
}
s_DefaultUseGravity.Add(type, defaultUseGravity);
return defaultUseGravity;
}
/// <summary>
/// Returns the DefaultUseRootMotionPosition of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultUseRootMotionPosition of the specified ability type. Can be null.</returns>
private static DefaultUseRootMotionPosition GetDefaultUseRootMotionPosition(Type type)
{
DefaultUseRootMotionPosition defaultUseRootMotionPosition;
if (s_DefaultUseRootMotionPosition.TryGetValue(type, out defaultUseRootMotionPosition)) {
return defaultUseRootMotionPosition;
}
if (type.GetCustomAttributes(typeof(DefaultUseRootMotionPosition), true).Length > 0) {
defaultUseRootMotionPosition = type.GetCustomAttributes(typeof(DefaultUseRootMotionPosition), true)[0] as DefaultUseRootMotionPosition;
}
s_DefaultUseRootMotionPosition.Add(type, defaultUseRootMotionPosition);
return defaultUseRootMotionPosition;
}
/// <summary>
/// Returns the DefaultUseRootMotionRotation of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultUseRootMotionRotation of the specified ability type. Can be null.</returns>
private static DefaultUseRootMotionRotation GetDefaultUseRootMotionRotation(Type type)
{
DefaultUseRootMotionRotation defaultUseRootMotionRotation;
if (s_DefaultUseRootMotionRotation.TryGetValue(type, out defaultUseRootMotionRotation)) {
return defaultUseRootMotionRotation;
}
if (type.GetCustomAttributes(typeof(DefaultUseRootMotionRotation), true).Length > 0) {
defaultUseRootMotionRotation = type.GetCustomAttributes(typeof(DefaultUseRootMotionRotation), true)[0] as DefaultUseRootMotionRotation;
}
s_DefaultUseRootMotionRotation.Add(type, defaultUseRootMotionRotation);
return defaultUseRootMotionRotation;
}
/// <summary>
/// Returns the DefaultDetectHorizontalCollisions of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultDetectHorizontalCollisions of the specified ability type. Can be null.</returns>
private static DefaultDetectHorizontalCollisions GetDefaultDetectHorizontalCollisions(Type type)
{
DefaultDetectHorizontalCollisions defaultDetectHorizontalCollisions;
if (s_DefaultDetectHorizontalCollisions.TryGetValue(type, out defaultDetectHorizontalCollisions)) {
return defaultDetectHorizontalCollisions;
}
if (type.GetCustomAttributes(typeof(DefaultDetectHorizontalCollisions), true).Length > 0) {
defaultDetectHorizontalCollisions = type.GetCustomAttributes(typeof(DefaultDetectHorizontalCollisions), true)[0] as DefaultDetectHorizontalCollisions;
}
s_DefaultDetectHorizontalCollisions.Add(type, defaultDetectHorizontalCollisions);
return defaultDetectHorizontalCollisions;
}
/// <summary>
/// Returns the DefaultDetectVerticalCollisions of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultDetectVerticalCollisions of the specified ability type. Can be null.</returns>
private static DefaultDetectVerticalCollisions GetDefaultDetectVerticalCollisions(Type type)
{
DefaultDetectVerticalCollisions defaultDetectVerticalCollisions;
if (s_DefaultDetectVerticalCollisions.TryGetValue(type, out defaultDetectVerticalCollisions)) {
return defaultDetectVerticalCollisions;
}
if (type.GetCustomAttributes(typeof(DefaultDetectVerticalCollisions), true).Length > 0) {
defaultDetectVerticalCollisions = type.GetCustomAttributes(typeof(DefaultDetectVerticalCollisions), true)[0] as DefaultDetectVerticalCollisions;
}
s_DefaultDetectVerticalCollisions.Add(type, defaultDetectVerticalCollisions);
return defaultDetectVerticalCollisions;
}
/// <summary>
/// Returns the DefaultObjectDetection of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultObjectDetection of the specified ability type. Can be null.</returns>
private static DefaultObjectDetection GetDefaultObjectDetection(Type type)
{
DefaultObjectDetection defaultObjectDetection;
if (s_DefaultObjectDetection.TryGetValue(type, out defaultObjectDetection)) {
return defaultObjectDetection;
}
if (type.GetCustomAttributes(typeof(DefaultObjectDetection), true).Length > 0) {
defaultObjectDetection = type.GetCustomAttributes(typeof(DefaultObjectDetection), true)[0] as DefaultObjectDetection;
}
s_DefaultObjectDetection.Add(type, defaultObjectDetection);
return defaultObjectDetection;
}
/// <summary>
/// Returns the DefaultUseLookDirection of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultUseLookDirection of the specified ability type. Can be null.</returns>
private static DefaultUseLookDirection GetDefaultUseLookDirection(Type type)
{
DefaultUseLookDirection defaultUseLookDirection;
if (s_DefaultUseLookDirection.TryGetValue(type, out defaultUseLookDirection)) {
return defaultUseLookDirection;
}
if (type.GetCustomAttributes(typeof(DefaultUseLookDirection), true).Length > 0) {
defaultUseLookDirection = type.GetCustomAttributes(typeof(DefaultUseLookDirection), true)[0] as DefaultUseLookDirection;
}
s_DefaultUseLookDirection.Add(type, defaultUseLookDirection);
return defaultUseLookDirection;
}
/// <summary>
/// Returns the DefaultCastOffset of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultCastOffset of the specified ability type. Can be null.</returns>
private static DefaultCastOffset GetDefaultCastOffset(Type type)
{
DefaultCastOffset defaultCastOffset;
if (s_DefaultCastOffset.TryGetValue(type, out defaultCastOffset)) {
return defaultCastOffset;
}
if (type.GetCustomAttributes(typeof(DefaultCastOffset), true).Length > 0) {
defaultCastOffset = type.GetCustomAttributes(typeof(DefaultCastOffset), true)[0] as DefaultCastOffset;
}
s_DefaultCastOffset.Add(type, defaultCastOffset);
return defaultCastOffset;
}
/// <summary>
/// Returns the DefaultEquippedSlots of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultEquippedSlots of the specified ability type. Can be null.</returns>
private static DefaultEquippedSlots GetDefaultEquippedSlots(Type type)
{
DefaultEquippedSlots defaultEquippedSlots;
if (s_DefaultEquippedSlots.TryGetValue(type, out defaultEquippedSlots)) {
return defaultEquippedSlots;
}
if (type.GetCustomAttributes(typeof(DefaultEquippedSlots), true).Length > 0) {
defaultEquippedSlots = type.GetCustomAttributes(typeof(DefaultEquippedSlots), true)[0] as DefaultEquippedSlots;
}
s_DefaultEquippedSlots.Add(type, defaultEquippedSlots);
return defaultEquippedSlots;
}
/// <summary>
/// Returns the DefaultReequipSlots of the specified ability type.
/// </summary>
/// <param name="type">The type of ability.</param>
/// <returns>The DefaultReequipSlots of the specified ability type. Can be null.</returns>
private static DefaultReequipSlots GetDefaultReequipSlots(Type type)
{
DefaultReequipSlots defaultReequipSlots;
if (s_DefaultReequipSlots.TryGetValue(type, out defaultReequipSlots)) {
return defaultReequipSlots;
}
if (type.GetCustomAttributes(typeof(DefaultReequipSlots), true).Length > 0) {
defaultReequipSlots = type.GetCustomAttributes(typeof(DefaultReequipSlots), true)[0] as DefaultReequipSlots;
}
s_DefaultReequipSlots.Add(type, defaultReequipSlots);
return defaultReequipSlots;
}
/// <summary>
/// Returns the AddState of the specified ability type.
/// </summary>
/// <param name="type">The view type.</param>
/// <returns>The AddState of the specified ability type. Can be null.</returns>
private static AddState[] GetAddStates(Type type)
{
AddState[] addStates;
if (s_AddStates.TryGetValue(type, out addStates)) {
return addStates;
}
if (type.GetCustomAttributes(typeof(AddState), true).Length > 0) {
addStates = type.GetCustomAttributes(typeof(AddState), true) as AddState[];
}
s_AddStates.Add(type, addStates);
return addStates;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 16526568bd0b93842984441fd97bc59f
timeCreated: 1513110789
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,726 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Utility.Builders
{
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities;
using Opsive.UltimateCharacterController.Character.Identifiers;
using Opsive.UltimateCharacterController.Character.MovementTypes;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.Inventory;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Allows for the Ultimate Character Controller components to be added/removed at runtime.
/// </summary>
public static class CharacterBuilder
{
private const string c_MovingStateGUID = "527d884c54f1a4b4a82fed73411305a8";
/// <summary>
/// Adds the essnetial components to the specified character and sets the MovementType.
/// </summary>
/// <param name="character">The GameObject of the character.</param>
/// <param name="addAnimator">Should the animator components be added?</param>
/// <param name="animatorController">A reference to the animator controller.</param>
/// <param name="firstPersonMovementType">The first person MovementType that should be added.</param>
/// <param name="thirdPersonMovementType">The third person MovementType that should be added.</param>
/// <param name="startFirstPersonPerspective">Should the character start in a first person perspective?</param>
/// <param name="firstPersonHiddenObjects">The objects that should be hidden in first person view.</param>
/// <param name="invisibleShadowCasterMaterial">The shadow caster material applied to the invisible first person objects.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
public static void BuildCharacter(GameObject character, bool addAnimator, RuntimeAnimatorController animatorController, string firstPersonMovementType, string thirdPersonMovementType, bool startFirstPersonPerspective,
GameObject[] firstPersonHiddenObjects, Material invisibleShadowCasterMaterial, bool aiAgent)
{
// Determine if the ThirdPersonObject component should be added or the invisible object renderer should be directly set to the invisible shadow caster.
if (firstPersonHiddenObjects != null) {
for (int i = 0; i < firstPersonHiddenObjects.Length; ++i) {
if (firstPersonHiddenObjects[i] == null) {
continue;
}
if (string.IsNullOrEmpty(thirdPersonMovementType)) {
var renderers = firstPersonHiddenObjects[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] = invisibleShadowCasterMaterial;
}
renderers[j].sharedMaterials = materials;
}
}
firstPersonHiddenObjects[i].AddComponent<ThirdPersonObject>();
}
}
AddEssentials(character, addAnimator, animatorController, !string.IsNullOrEmpty(firstPersonMovementType) && !string.IsNullOrEmpty(thirdPersonMovementType), invisibleShadowCasterMaterial, aiAgent);
// The last added MovementType is starting movement type.
if (startFirstPersonPerspective) {
if (!string.IsNullOrEmpty(thirdPersonMovementType)) {
AddMovementType(character, thirdPersonMovementType);
}
if (!string.IsNullOrEmpty(firstPersonMovementType)) {
AddMovementType(character, firstPersonMovementType);
}
} else {
if (!string.IsNullOrEmpty(firstPersonMovementType)) {
AddMovementType(character, firstPersonMovementType);
}
if (!string.IsNullOrEmpty(thirdPersonMovementType)) {
AddMovementType(character, thirdPersonMovementType);
}
}
}
/// <summary>
/// Adds the Ultimate Character Controller essential components to the specified character.
/// </summary>
/// <param name="character">The character to add the components to.</param>
/// <param name="addAnimator">Should the animator components be added?</param>
/// <param name="animatorController">A reference to the animator controller.</param>
/// <param name="addPerspectiveMonitor">Should the perspective monitor be added?</param>
/// <param name="invisibleShadowCasterMaterial">The shadow caster material applied to the invisible first person objects.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
public static void AddEssentials(GameObject character, bool addAnimator, RuntimeAnimatorController animatorController, bool addPerspectiveMonitor, Material invisibleShadowCasterMaterial, bool aiAgent)
{
if (!aiAgent) {
character.tag = "Player";
}
character.layer = LayerManager.Character;
if (character.GetComponent<CharacterLayerManager>() == null) {
character.AddComponent<CharacterLayerManager>();
}
var rigidbody = character.GetComponent<Rigidbody>();
if (rigidbody == null) {
rigidbody = character.AddComponent<Rigidbody>();
}
rigidbody.useGravity = false;
rigidbody.isKinematic = true;
rigidbody.constraints = RigidbodyConstraints.FreezeAll;
GameObject collider = null;
var colliderIdentifier = character.GetComponent<CharacterColliderBaseIdentifier>();
if (colliderIdentifier == null) {
var colliders = new GameObject("Colliders");
colliders.layer = LayerManager.Character;
colliders.transform.SetParentOrigin(character.transform);
collider = new GameObject("CapsuleCollider");
collider.layer = LayerManager.Character;
collider.transform.SetParentOrigin(colliders.transform);
var capsuleCollider = collider.AddComponent<CapsuleCollider>();
capsuleCollider.center = new Vector3(0, 1, 0);
capsuleCollider.height = 2;
capsuleCollider.radius = 0.4f;
}
if (addAnimator) {
AddAnimator(character, animatorController, aiAgent);
}
if (character.GetComponent<UltimateCharacterLocomotion>() == null) {
#if UNITY_EDITOR
var characterLocomotion = character.AddComponent<UltimateCharacterLocomotion>();
if (!Application.isPlaying) {
// The Moving state should automatically be added.
var presetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(c_MovingStateGUID);
if (!string.IsNullOrEmpty(presetPath)) {
var preset = UnityEditor.AssetDatabase.LoadAssetAtPath(presetPath, typeof(StateSystem.PersistablePreset)) as StateSystem.PersistablePreset;
if (preset != null) {
var states = characterLocomotion.States;
System.Array.Resize(ref states, states.Length + 1);
// Default must always be at the end.
states[states.Length - 1] = states[0];
states[states.Length - 2] = new StateSystem.State("Moving", preset, null);
characterLocomotion.States = states;
}
}
}
#else
character.AddComponent<UltimateCharacterLocomotion>();
#endif
}
if (collider != null) {
var positioner = collider.AddComponent<CapsuleColliderPositioner>();
positioner.FirstEndCapTarget = character.transform;
var animator = character.GetComponent<Animator>();
if (animator != null) {
// The CapsuleColliderPositioner should follow the character's movements.
var head = animator.GetBoneTransform(HumanBodyBones.Head);
if (head != null) {
positioner.SecondEndCapTarget = head;
positioner.RotationBone = positioner.PositionBone = animator.GetBoneTransform(HumanBodyBones.Hips);
}
}
}
if (aiAgent) {
AddAIAgent(character);
} else {
AddUnityInput(character);
if (character.GetComponent<UltimateCharacterLocomotionHandler>() == null) {
character.AddComponent<UltimateCharacterLocomotionHandler>();
}
}
#if THIRD_PERSON_CONTROLLER
if (addPerspectiveMonitor && character.GetComponent<ThirdPersonController.Character.PerspectiveMonitor>() == null) {
var perspectiveMonitor = character.AddComponent<ThirdPersonController.Character.PerspectiveMonitor>();
if (perspectiveMonitor.InvisibleMaterial == null) {
perspectiveMonitor.InvisibleMaterial = invisibleShadowCasterMaterial;
}
}
#endif
// All of the child GameObjects should be set to the SubCharacter layer to prevent any added-colliders from interferring with the locomotion.
SetRecursiveLayer(character, LayerManager.SubCharacter, LayerManager.Character);
}
/// <summary>
/// Adds the animator with the specified controller to the character.
/// </summary>
/// <param name="character">The character to add the animator to.</param>
/// <param name="animatorController">A reference to the animator controller.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
public static void AddAnimator(GameObject character, RuntimeAnimatorController animatorController, bool aiAgent)
{
Animator animator;
if ((animator = character.GetComponent<Animator>()) == null) {
animator = character.AddComponent<Animator>();
}
animator.runtimeAnimatorController = animatorController;
if (!aiAgent) {
animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
}
if (character.GetComponent<AnimatorMonitor>() == null) {
character.AddComponent<AnimatorMonitor>();
}
}
/// <summary>
/// Removes the animator from the character.
/// </summary>
/// <param name="character">The character to remove the animator from.</param>
public static void RemoveAnimator(GameObject character)
{
var animator = character.GetComponent<Animator>();
if (animator != null) {
GameObject.DestroyImmediate(animator, true);
}
var animatorMonitor = character.GetComponent<AnimatorMonitor>();
if (animatorMonitor != null) {
GameObject.DestroyImmediate(animatorMonitor, true);
}
}
/// <summary>
/// Sets the GameObject to the specified layer. Will recursively set the children unless the child contains a component that shouldn't be set.
/// </summary>
/// <param name="gameObject">The GameObject to set.</param>
/// <param name="layer">The layer to set the GameObject to.</param>
/// <param name="characterLayer">The layer of the character. GameObjects with this layer will not be set to the specified layer.</param>
private static void SetRecursiveLayer(GameObject gameObject, int layer, int characterLayer)
{
var children = gameObject.transform.childCount;
for (int i = 0; i < gameObject.transform.childCount; ++i) {
var child = gameObject.transform.GetChild(i);
// Do not set the layer if the child is already set to the Character layer or contains the item identifier components.
if (child.gameObject.layer == characterLayer || child.GetComponent<Items.ItemPlacement>() != null) {
continue;
}
#if FIRST_PERSON_CONTROLLER
// First person objects do not need to be set.
if (child.GetComponent<FirstPersonController.Character.FirstPersonObjects>() != null) {
continue;
}
#endif
// Set the layer.
child.gameObject.layer = layer;
SetRecursiveLayer(child.gameObject, layer, characterLayer);
}
}
/// <summary>
/// Removes the Ultimate Character Controller essential components from the specified character.
/// </summary>
/// <param name="character">The character to remove the components from.</param>
public static void RemoveEssentials(GameObject character)
{
var rigidbody = character.GetComponent<Rigidbody>();
if (rigidbody != null) {
GameObject.DestroyImmediate(rigidbody, true);
}
var collider = character.GetComponent<CharacterColliderBaseIdentifier>();
if (collider != null) {
GameObject.DestroyImmediate(collider, true);
}
var ultimateCharacterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
if (ultimateCharacterLocomotion != null) {
GameObject.DestroyImmediate(ultimateCharacterLocomotion, true);
}
var ultimateCharacterLocomotionHandler = character.GetComponent<UltimateCharacterLocomotionHandler>();
if (ultimateCharacterLocomotionHandler != null) {
GameObject.DestroyImmediate(ultimateCharacterLocomotionHandler, true);
}
var localLookSource = character.GetComponent<LocalLookSource>();
if (localLookSource != null) {
GameObject.DestroyImmediate(localLookSource, true);
}
var layerManager = character.GetComponent<CharacterLayerManager>();
if (layerManager != null) {
GameObject.DestroyImmediate(layerManager, true);
}
#if THIRD_PERSON_CONTROLLER
var perspectiveMonitor = character.GetComponent<ThirdPersonController.Character.PerspectiveMonitor>();
if (perspectiveMonitor != null) {
GameObject.DestroyImmediate(perspectiveMonitor, true);
}
#endif
}
/// <summary>
/// Adds the specified MovementType to the character.
/// </summary>
/// <param name="character">The character to add the MovementType to.</param>
/// <param name="movementType">The MovementType to add.</param>
public static void AddMovementType(GameObject character, string movementType)
{
var ultimateCharacterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
if (ultimateCharacterLocomotion != null) {
// Don't allow duplicate MovementTypes.
var type = System.Type.GetType(movementType);
ultimateCharacterLocomotion.DeserializeMovementTypes();
var movementTypes = ultimateCharacterLocomotion.MovementTypes;
var add = true;
if (movementTypes != null) {
for (int i = 0; i < movementTypes.Length; ++i) {
if (movementTypes[i].GetType() == type) {
add = false;
}
}
}
if (add) {
var movementTypesList = new List<MovementType>();
if (movementTypes != null) {
movementTypesList.AddRange(movementTypes);
}
var movementTypeObj = System.Activator.CreateInstance(type) as MovementType;
movementTypesList.Add(movementTypeObj);
ultimateCharacterLocomotion.MovementTypes = movementTypesList.ToArray();
ultimateCharacterLocomotion.MovementTypeData = Shared.Utility.Serialization.Serialize<MovementType>(movementTypesList);
// If the character has already been initialized then the movement type should be initialized.
if (Application.isPlaying) {
movementTypeObj.Initialize(ultimateCharacterLocomotion);
movementTypeObj.Awake();
}
}
// Set the added movement type as the default.
ultimateCharacterLocomotion.SetMovementType(type);
}
}
/// <summary>
/// Adds the non-essential Ultimate Character Controller components to the character.
/// </summary>
/// <param name="character">The character to add the components to.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
/// <param name="addItems">Should the item components be added?</param>
/// <param name="itemCollection">A reference to the ItemCollection component.</param>
/// <param name="firstPersonItems">Does the character support first person items?</param>
/// <param name="addHealth">Should the health components be added?</param>
/// <param name="addUnityIK">Should the CharacterIK component be added?</param>
/// <param name="addFootEffects">Should the CharacterFootEffects component be added?</param>
/// <param name="addStandardAbilities">Should the standard abilities be added?</param>
/// <param name="addNavMeshAgent">Should the NavMeshAgent component be added?</param>
public static void BuildCharacterComponents(GameObject character, bool aiAgent, bool addItems,
ItemCollection itemCollection, bool firstPersonItems, bool addHealth, bool addUnityIK, bool addFootEffects, bool addStandardAbilities, bool addNavMeshAgent)
{
if (addItems) {
AddItemSupport(character, itemCollection, aiAgent, firstPersonItems);
}
if (addHealth) {
AddHealth(character);
}
if (addUnityIK) {
AddUnityIK(character);
}
if (addFootEffects) {
AddFootEffects(character);
}
if (addStandardAbilities) {
// Add the Jump, Fall, Speed Change, and Height Change abilities.
var characterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
var jump = AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.Jump));
if (characterLocomotion.GetComponent<Animator>() == null) {
(jump as Jump).JumpEvent = new AnimationEventTrigger(false, 0);
AbilityBuilder.SerializeAbilities(characterLocomotion);
}
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.Fall));
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.MoveTowards));
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.SpeedChange));
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.HeightChange));
// The abilities should not use an input related start type.
if (aiAgent) {
var abilities = characterLocomotion.GetAbilities<Character.Abilities.Ability>();
for (int i = 0; i < abilities.Length; ++i) {
if (abilities[i].StartType != Character.Abilities.Ability.AbilityStartType.Automatic &&
abilities[i].StartType != Character.Abilities.Ability.AbilityStartType.Manual) {
abilities[i].StartType = Character.Abilities.Ability.AbilityStartType.Manual;
}
if (abilities[i].StopType != Character.Abilities.Ability.AbilityStopType.Automatic &&
abilities[i].StopType != Character.Abilities.Ability.AbilityStopType.Manual) {
abilities[i].StopType = Character.Abilities.Ability.AbilityStopType.Manual;
}
if (abilities[i] is Character.Abilities.Items.Use) {
abilities[i].StopType = Character.Abilities.Ability.AbilityStopType.Manual;
}
}
AbilityBuilder.SerializeAbilities(characterLocomotion);
}
}
if (addNavMeshAgent) {
var characterLocomotion = character.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 = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (navMeshAgent != null) {
navMeshAgent.stoppingDistance = 0.1f;
}
}
if (addItems) {
// Add the Equip, Aim, Use, and Reload item abilities.
var characterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.Reload));
#endif
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.Use));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.EquipUnequip));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.ToggleEquip));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.EquipNext));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.EquipPrevious));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.EquipScroll));
AbilityBuilder.AddItemAbility(characterLocomotion, typeof(Character.Abilities.Items.Aim));
// The buttons should not use an input related start type.
if (aiAgent) {
var itemAbilities = characterLocomotion.GetAbilities<Character.Abilities.Items.ItemAbility>();
for (int i = 0; i < itemAbilities.Length; ++i) {
if (itemAbilities[i].StartType != Character.Abilities.Ability.AbilityStartType.Automatic &&
itemAbilities[i].StartType != Character.Abilities.Ability.AbilityStartType.Manual) {
itemAbilities[i].StartType = Character.Abilities.Ability.AbilityStartType.Manual;
}
if (itemAbilities[i].StopType != Character.Abilities.Ability.AbilityStopType.Automatic &&
itemAbilities[i].StopType != Character.Abilities.Ability.AbilityStopType.Manual) {
itemAbilities[i].StopType = Character.Abilities.Ability.AbilityStopType.Manual;
}
}
AbilityBuilder.SerializeItemAbilities(characterLocomotion);
}
// The ItemEquipVerifier needs to be added after the item abilities.
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.ItemEquipVerifier));
AbilityBuilder.SerializeAbilities(characterLocomotion);
}
}
/// <summary>
/// Adds the ai agent components to the character.
/// </summary>
/// <param name="character">The character to add the ai agent components to.</param>
public static void AddAIAgent(GameObject character)
{
if (character.GetComponent<LocalLookSource>() == null) {
character.AddComponent<LocalLookSource>();
}
var locomotionHandler = character.GetComponent<UltimateCharacterLocomotionHandler>();
if (locomotionHandler != null) {
GameObject.DestroyImmediate(locomotionHandler, true);
}
var itemHandler = character.GetComponent<ItemHandler>();
if (itemHandler != null) {
GameObject.DestroyImmediate(itemHandler, true);
}
RemoveUnityInput(character);
}
/// <summary>
/// Removes the ai agent components from the character.
/// </summary>
/// <param name="character">The character to remove the ai agent components to.</param>
public static void RemoveAIAgent(GameObject character)
{
var localLookSource = character.GetComponent<LocalLookSource>();
if (localLookSource != null) {
GameObject.DestroyImmediate(localLookSource, true);
}
if (character.GetComponent<UltimateCharacterLocomotionHandler>() == null) {
character.AddComponent<UltimateCharacterLocomotionHandler>();
}
if (character.GetComponent<ItemHandler>() == null) {
character.AddComponent<ItemHandler>();
}
AddUnityInput(character);
AbilityBuilder.RemoveAbility<Character.Abilities.AI.NavMeshAgentMovement>(character.GetComponent<UltimateCharacterLocomotion>());
var navMeshAgent = character.GetComponent<UnityEngine.AI.NavMeshAgent>();
if (navMeshAgent != null) {
GameObject.DestroyImmediate(navMeshAgent, true);
}
}
/// <summary>
/// Adds the UnityInput component to the character.
/// </summary>
/// <param name="character">The character to add the UnityInput component to.</param>
public static void AddUnityInput(GameObject character)
{
if (character.GetComponent<UltimateCharacterController.Input.UnityInput>() == null) {
character.AddComponent<UltimateCharacterController.Input.UnityInput>();
}
}
/// <summary>
/// Removes the UnityInput component from the character.
/// </summary>
/// <param name="character">The character to remove the UnityInput component from.</param>
public static void RemoveUnityInput(GameObject character)
{
var unityInput = character.GetComponent<UltimateCharacterController.Input.UnityInput>();
if (unityInput != null) {
GameObject.DestroyImmediate(unityInput, true);
}
}
/// <summary>
/// Adds support for items to the character.
/// </summary>
/// <param name="character">The character to add support for items to.</param>
/// <param name="itemCollection">A reference to the inventory's ItemCollection.</param>
/// <param name="aiAgent">Is the character an AI agent?</param>
/// <param name="firstPersonItems">Does the character support first person items?</param>
public static void AddItemSupport(GameObject character, ItemCollection itemCollection, bool aiAgent, bool firstPersonItems)
{
// Even if the character doesn't have an animator the items may make use of one.
if (character.GetComponent<AnimatorMonitor>() == null) {
character.AddComponent<AnimatorMonitor>();
}
if (character.GetComponentInChildren<Items.ItemPlacement>() == null) {
var items = new GameObject("Items");
items.transform.parent = character.transform;
items.AddComponent<Items.ItemPlacement>();
}
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) {
var items = new GameObject("Items");
items.transform.SetParentOrigin(leftHand.transform);
var itemSlot = items.AddComponent<Items.ItemSlot>();
itemSlot.ID = 1;
}
if (rightHand.GetComponentInChildren<Items.ItemSlot>() == null) {
var items = new GameObject("Items");
items.transform.SetParentOrigin(rightHand.transform);
items.AddComponent<Items.ItemSlot>();
}
}
}
}
// Items use the inventory for being equip/unequip.
if (character.GetComponent<Inventory>() == null) {
character.AddComponent<Inventory>();
}
#if FIRST_PERSON_CONTROLLER
if (firstPersonItems && character.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>() == null) {
var firstPersonObjects = new GameObject("First Person Objects");
firstPersonObjects.transform.parent = character.transform;
firstPersonObjects.AddComponent<FirstPersonController.Character.FirstPersonObjects>();
}
#endif
ItemSetManager itemSetManager;
if ((itemSetManager = character.GetComponent<ItemSetManager>()) == null) {
itemSetManager = character.AddComponent<ItemSetManager>();
}
itemSetManager.ItemCollection = itemCollection;
if (!aiAgent && character.GetComponent<ItemHandler>() == null) {
character.AddComponent<ItemHandler>();
}
}
/// <summary>
/// Removes support for items from the character.
/// </summary>
/// <param name="character">The character to remove support for the items from.</param>
public static void RemoveItemSupport(GameObject character)
{
var animatorMonitor = character.GetComponent<ItemHandler>();
if (animatorMonitor != null && character.GetComponent<Animator>() == null) {
character.AddComponent<Animator>();
}
var itemHandler = character.GetComponent<ItemHandler>();
if (itemHandler != null) {
GameObject.DestroyImmediate(itemHandler, true);
}
var itemPlacement = character.GetComponentInChildren<Items.ItemPlacement>();
if (itemPlacement != null) {
GameObject.DestroyImmediate(itemPlacement.gameObject, true);
}
#if FIRST_PERSON_CONTROLLER
var firstPersonObjects = character.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
if (firstPersonObjects != null) {
GameObject.DestroyImmediate(firstPersonObjects, true);
}
#endif
var itemSlots = character.GetComponentsInChildren<Items.ItemSlot>();
if (itemSlots != null && itemSlots.Length > 0) {
for (int i = itemSlots.Length - 1; i >= 0; --i) {
GameObject.DestroyImmediate(itemSlots[i].gameObject, true);
}
}
var inventory = character.GetComponent<Inventory>();
if (inventory != null) {
GameObject.DestroyImmediate(inventory, true);
}
var itemSetManager = character.GetComponent<ItemSetManager>();
if (itemSetManager != null) {
GameObject.DestroyImmediate(itemSetManager, true);
}
}
/// <summary>
/// Adds the health components to the character.
/// </summary>
/// <param name="character">The character to add the health components to.</param>
public static void AddHealth(GameObject character)
{
if (character.GetComponent<Traits.AttributeManager>() == null) {
character.AddComponent<Traits.AttributeManager>();
}
if (character.GetComponent<Traits.CharacterHealth>() == null) {
character.AddComponent<Traits.CharacterHealth>();
}
if (character.GetComponent<Traits.CharacterRespawner>() == null) {
character.AddComponent<Traits.CharacterRespawner>();
}
}
/// <summary>
/// Removes the health components from the character.
/// </summary>
/// <param name="character">The character to remove the health components from.</param>
public static void RemoveHealth(GameObject character)
{
var health = character.GetComponent<Traits.CharacterHealth>();
if (health != null) {
GameObject.DestroyImmediate(health, true);
}
var attributeManager = character.GetComponent<Traits.AttributeManager>();
if (attributeManager != null) {
GameObject.DestroyImmediate(attributeManager, true);
}
var respawner = character.GetComponent<Traits.CharacterRespawner>();
if (respawner != null) {
GameObject.DestroyImmediate(respawner, true);
}
}
/// <summary>
/// Adds the CharacterIK component to the character.
/// </summary>
/// <param name="character">The character to add the CharacterIK component to.</param>
public static void AddUnityIK(GameObject character)
{
if (character.GetComponent<CharacterIK>() == null) {
character.AddComponent<CharacterIK>();
}
}
/// <summary>
/// Removes the CharacterIK component from the character.
/// </summary>
/// <param name="character">The character to remove the CharacterIK component from.</param>
public static void RemoveUnityIK(GameObject character)
{
var characterIK = character.GetComponent<CharacterIK>();
if (characterIK != null) {
GameObject.DestroyImmediate(characterIK, true);
}
}
/// <summary>
/// Adds the CharacterFootEffects component to the character.
/// </summary>
/// <param name="character">The character to add the CharacterFootEffects component to.</param>
public static void AddFootEffects(GameObject character)
{
if (character.GetComponent<CharacterFootEffects>() == null) {
var footEffects = character.AddComponent<CharacterFootEffects>();
footEffects.InitializeHumanoidFeet();
}
}
/// <summary>
/// Removes the CharacterFootEffects component from the character.
/// </summary>
/// <param name="character">The character to remove the CharacterFootEffects component from.</param>
public static void RemoveFootEffects(GameObject character)
{
var footEffects = character.GetComponent<CharacterFootEffects>();
if (footEffects != null) {
GameObject.DestroyImmediate(footEffects, true);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c8e62d4b86ca89c40801df9a6e4900d9
timeCreated: 1503625699
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,936 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Utility.Builders
{
using Opsive.Shared.Inventory;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Game;
using Opsive.UltimateCharacterController.Items;
using Opsive.UltimateCharacterController.Items.Actions;
using Opsive.UltimateCharacterController.Items.Actions.PerspectiveProperties;
using Opsive.UltimateCharacterController.Inventory;
using UnityEngine;
/// <summary>
/// Builds a new item.
/// </summary>
public class ItemBuilder
{
/// <summary>
/// The type of action to create.
/// </summary>
public enum ActionType {
ShootableWeapon, // The item uses a ShootableWeapon.
MeleeWeapon, // The item uses a MeleeWeapon.
Shield, // The item uses a Shield.
MagicItem, // The item uses a MagicItem.
ThrowableItem, // The item uses a ThrowableItem.
GrenadeItem, // The item uses a GrenadeItem.
Flashlight, // The item uses a Flashlight.
Nothing // The item doesn't have any actions.
}
/// <summary>
/// Builds the item with the specified parameters.
/// </summary>
/// <param name="name">The name of the item.</param>
/// <param name="itemDefinition">The ItemDefinition that the item uses (optional).</param>
/// <param name="animatorItemID">The ID of the item within the animator.</param>
/// <param name="character">The character that the item should be attached to (optional).</param>
/// <param name="slotID">The ID of the slot that the item is parented to.</param>
/// <param name="addToDefaultLoadout">Should the item be added to the character's default loadout?</param>
/// <param name="addFirstPersonPerspective">Should the first person perspective be added?</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonObjectAnimatorController">A reference to the animator controller added to the first person object. Can be null.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item. Can be null.</param>
/// <param name="firstPersonItemSlot">A reference to the ItemSlot to add the visible item to.</param>
/// <param name="firstPersonVisibleItemAnimatorController">A reference to the animator controller added to the first person visible item. Can be null.</param>
/// <param name="addThirdPersonPerspective">Should the third person perspective be added?</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
/// <param name="thirdPersonItemSlot">A reference to the ItemSlot to add the third person item to.</param>
/// <param name="thirdPersonObjectAnimatorController">A reference to the animator controller added to the third person object. Can be null.</param>
/// <param name="invisibleShadowCasterMaterial">A reference to the invisible shadow caster material. This is only used for first person characters.</param>
/// <param name="actionType">The type of item to create.</param>
/// <param name="actionItemDefinition">The ItemDefinition that the action uses (optional).</param>
public static GameObject BuildItem(string name, ItemDefinitionBase itemDefinition, int animatorItemID, GameObject character, int slotID, bool addToDefaultLoadout, bool addFirstPersonPerspective,
GameObject firstPersonObject, RuntimeAnimatorController firstPersonObjectAnimatorController, GameObject firstPersonVisibleItem, ItemSlot firstPersonItemSlot,
RuntimeAnimatorController firstPersonVisibleItemAnimatorController, bool addThirdPersonPerspective, GameObject thirdPersonObject, ItemSlot thirdPersonItemSlot,
RuntimeAnimatorController thirdPersonObjectAnimatorController, Material invisibleShadowCasterMaterial, ActionType actionType, ItemDefinitionBase actionItemDefinition)
{
var itemGameObject = new GameObject(name);
var itemSlotID = (character == null || (firstPersonItemSlot == null && thirdPersonItemSlot == null)) ? slotID :
(firstPersonItemSlot != null ? firstPersonItemSlot.ID : thirdPersonItemSlot.ID);
// If character is null then a prefab will be created.
if (character != null) {
// The attach to object must have an ItemPlacement component.
var itemPlacement = character.GetComponentInChildren<ItemPlacement>();
if (itemPlacement == null) {
Debug.LogError("Error: Unable to find the ItemPlacement component within " + character.name + ".");
return null;
}
// Organize the main item GameObject under the ItemPlacement GameObject.
itemGameObject.transform.SetParentOrigin(itemPlacement.transform);
// The item can automatically be added to the inventory's default loadout.
if (itemDefinition != null && addToDefaultLoadout) {
var inventory = character.GetComponent<Inventory>();
var defaultLoadout = inventory.DefaultLoadout;
if (defaultLoadout == null) {
defaultLoadout = new ItemDefinitionAmount[0];
}
var hasItemDefinition = false;
for (int i = 0; i < defaultLoadout.Length; ++i) {
// If the ItemIdentifier has already been added then a new ItemIdentifier doesn't need to be added.
if (defaultLoadout[i].ItemDefinition == itemDefinition) {
defaultLoadout[i].Amount++;
hasItemDefinition = true;
break;
}
}
if (!hasItemDefinition) {
System.Array.Resize(ref defaultLoadout, defaultLoadout.Length + 1);
defaultLoadout[defaultLoadout.Length - 1] = new ItemDefinitionAmount(itemDefinition, 1);
}
// The actionItemIdentifier should also be added.
if (actionItemDefinition != null) {
hasItemDefinition = false;
for (int i = 0; i < defaultLoadout.Length; ++i) {
// If the ItemIdentifier has already been added then a new action ItemDefinition doesn't need to be added.
if (defaultLoadout[i].ItemDefinition == actionItemDefinition) {
hasItemDefinition = true;
break;
}
}
if (!hasItemDefinition) {
System.Array.Resize(ref defaultLoadout, defaultLoadout.Length + 1);
defaultLoadout[defaultLoadout.Length - 1] = new ItemDefinitionAmount(actionItemDefinition, 100);
}
}
inventory.DefaultLoadout = defaultLoadout;
// The ItemIdentifier should be added to the ItemSetManager as well.
var itemSetManager = character.GetComponent<ItemSetManager>();
if (itemSetManager != null && itemDefinition.GetItemCategory() != null) {
itemSetManager.Initialize(false);
var index = itemSetManager.CategoryToIndex(itemDefinition.GetItemCategory());
if (index > -1) {
var category = itemSetManager.CategoryItemSets[index];
hasItemDefinition = false;
for (int j = 0; j < category.ItemSetList.Count; ++j) {
if (category.ItemSetList[j].Slots[itemSlotID] == itemDefinition) {
hasItemDefinition = true;
break;
}
}
if (!hasItemDefinition) {
category.ItemSetList.Add(new ItemSet(Mathf.Max(inventory.SlotCount, itemSlotID + 1), itemSlotID, itemDefinition, null, string.Empty));
}
}
}
}
}
var item = itemGameObject.AddComponent<Item>();
item.ItemDefinition = itemDefinition;
item.SlotID = itemSlotID;
item.AnimatorItemID = animatorItemID;
#if FIRST_PERSON_CONTROLLER
// Add the first person object.
if (addFirstPersonPerspective) {
AddFirstPersonObject(character, name, itemGameObject, ref firstPersonObject, firstPersonObjectAnimatorController, ref firstPersonVisibleItem, firstPersonItemSlot,
firstPersonVisibleItemAnimatorController);
// If the character doesn't have an animator then the item should be equipped by a timer.
if (character != null && character.GetComponent<Animator>() == null) {
item.EquipEvent.WaitForAnimationEvent = false;
}
}
#endif
// Add the third person object. The character will always have a third person object if the character has an animator.
if (addThirdPersonPerspective) {
AddThirdPersonObject(character, name, itemGameObject, ref thirdPersonObject, thirdPersonItemSlot, thirdPersonObjectAnimatorController, invisibleShadowCasterMaterial,
!addFirstPersonPerspective || firstPersonObject != null || firstPersonVisibleItem != null);
}
// Add the specified action type.
AddAction(itemGameObject, addFirstPersonPerspective, firstPersonObject, firstPersonVisibleItem, addThirdPersonPerspective, thirdPersonObject, actionType, actionItemDefinition);
return itemGameObject;
}
/// <summary>
/// Creates a GameObject as the child of the parent.
/// </summary>
/// <param name="name">The name of the GameObject.</param>
/// <param name="parent">The parent of the new GameObject.</param>
/// <returns>The Trasnform of the non duplicate GameObject.</returns>
private static Transform CreateGameObject(string name, Transform parent)
{
var gameObject = new GameObject(name);
gameObject.transform.SetParentOrigin(parent);
return gameObject.transform;
}
#if FIRST_PERSON_CONTROLLER
/// <summary>
/// Adds the first person object to the specified item.
/// </summary>
/// <param name="character">The character that the first person object is being added to.</param>
/// <param name="name">The name of the item.</param>
/// <param name="itemGameObject">A reference to the item's GameObject.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonObjectAnimatorController">A reference to the animator controller added to the first person object. Can be null.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item. Can be null.</param>
/// <param name="firstPersonItemSlot">A reference to the ItemSlot to add the visible item to.</param>
/// <param name="firstPersonVisibleItemAnimatorController">A reference to the animator controller added to the first person visible item. Can be null.</param>
public static void AddFirstPersonObject(GameObject character, string name, GameObject itemGameObject,
ref GameObject firstPersonObject, RuntimeAnimatorController firstPersonObjectAnimatorController, ref GameObject firstPersonVisibleItem, ItemSlot firstPersonItemSlot,
RuntimeAnimatorController firstPersonVisibleItemAnimatorController)
{
var parentFirstPersonObject = false;
if (firstPersonObject != null && (character == null || !firstPersonObject.transform.IsChildOf(character.transform))) {
parentFirstPersonObject = true;
var origFirstPersonPerspectiveItem = firstPersonVisibleItem;
var visibleItemName = string.Empty;
var visibleItemSearchName = string.Empty;
// The visible item is a child of the object. When the object is instantiated the new visible item should be found again.
// This is done by giving the visible item a unique name.
if (firstPersonVisibleItem != null) {
visibleItemName = firstPersonVisibleItem.name;
firstPersonVisibleItem.name += Random.value.ToString();
// Remember the path so the newly created visible item can be found again.
var parent = firstPersonVisibleItem.transform.parent;
visibleItemSearchName = firstPersonVisibleItem.name;
while (parent != firstPersonObject.transform && parent != null) {
visibleItemSearchName = parent.name + "/" + visibleItemSearchName;
parent = parent.parent;
}
}
firstPersonObject = GameObject.Instantiate(firstPersonObject);
if (character == null) {
firstPersonObject.name = "First Person " + name;
} else {
firstPersonObject.name = firstPersonObject.name.Substring(0, firstPersonObject.name.Length - 7); // Remove "(Clone)".
}
AddFirstPersonArms(character, firstPersonObject, firstPersonObjectAnimatorController);
// An ItemSlot must also be added to the base object if no visible item exists.
if (firstPersonVisibleItem == null) {
firstPersonObject.AddComponent<ItemSlot>();
}
// A new visible item would have been created.
if (firstPersonVisibleItem != null) {
var foundVisibleItem = firstPersonObject.transform.Find(visibleItemSearchName);
if (foundVisibleItem != null) {
// The newly created visible item is now the main visible item.
firstPersonVisibleItem = foundVisibleItem.gameObject;
} else {
// The visible item may not have been a child of the first person object GameObject.
firstPersonVisibleItem = GameObject.Instantiate(firstPersonVisibleItem);
// The ItemSlot reference also needs to be updated.
var itemSlots = firstPersonObject.GetComponentsInChildren<ItemSlot>();
for (int i = 0; i < itemSlots.Length; ++i) {
if (itemSlots[i].ID == firstPersonItemSlot.ID) {
firstPersonItemSlot = itemSlots[i];
break;
}
}
firstPersonVisibleItem.transform.SetParentOrigin(firstPersonItemSlot.transform);
}
origFirstPersonPerspectiveItem.name = firstPersonVisibleItem.name = visibleItemName;
}
} else if (firstPersonVisibleItem != null) {
firstPersonVisibleItem = GameObject.Instantiate(firstPersonVisibleItem);
firstPersonVisibleItem.name = (character == null ? "First Person " : "") + name;
}
var perspectiveItem = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonPerspectiveItem>();
perspectiveItem.Object = firstPersonObject;
perspectiveItem.VisibleItem = firstPersonVisibleItem;
if (firstPersonVisibleItem != null) {
if (firstPersonVisibleItem.GetComponent<AudioSource>() == null) {
var audioSource = firstPersonVisibleItem.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
audioSource.spatialBlend = 1;
audioSource.maxDistance = 20;
}
}
// The visible item can use an animator.
if (firstPersonVisibleItemAnimatorController != null && firstPersonVisibleItem != null) {
Animator animator;
if ((animator = firstPersonVisibleItem.GetComponent<Animator>()) == null) {
animator = firstPersonVisibleItem.AddComponent<Animator>();
}
animator.applyRootMotion = false;
animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
animator.runtimeAnimatorController = firstPersonVisibleItemAnimatorController;
if (firstPersonVisibleItem.GetComponent<ChildAnimatorMonitor>() == null) {
firstPersonVisibleItem.AddComponent<ChildAnimatorMonitor>();
}
}
Transform parentTransform = null;
if (character != null) {
// The object should be a child of the First Person Objects GameObject.
if (firstPersonObject != null && parentFirstPersonObject) {
var firstPersonObjects = character.GetComponentInChildren<FirstPersonController.Character.FirstPersonObjects>();
if (firstPersonObjects == null) {
Debug.LogError("Error: Unable to find the FirstPersonObjects component within " + character.name + ".");
return;
} else {
parentTransform = firstPersonObjects.transform;
}
} else if (firstPersonVisibleItem != null) {
parentTransform = firstPersonItemSlot.transform;
}
} else {
// The object should be a child of the item GameObject.
parentTransform = itemGameObject.transform;
}
// Assign the transform. The object will contain the visible item if it exists.
var obj = firstPersonObject && parentFirstPersonObject ? firstPersonObject : firstPersonVisibleItem;
if (obj != null) {
obj.transform.SetParentOrigin(parentTransform);
// The item's object should be on the first person overlay layer so it'll render over all other objects.
obj.transform.SetLayerRecursively(LayerManager.Overlay);
} else if (firstPersonVisibleItem != null) {
firstPersonVisibleItem.transform.SetLayerRecursively(LayerManager.Overlay);
}
// Add any properties for actions which have already been added.
AddPropertiesToActions(itemGameObject, firstPersonObject, firstPersonVisibleItem, null);
}
/// <summary>
/// Adds the FirstPersonBaseObject to the arms.
/// </summary>
/// <param name="character">The character that contains the FirstPersonObject.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonObjectAnimatorController">A reference to the animator controller added to the first person object. Can be null.</param>
public static void AddFirstPersonArms(GameObject character, GameObject firstPersonObject, RuntimeAnimatorController firstPersonObjectAnimatorController)
{
var maxID = -1;
if (character != null && firstPersonObject.GetComponent<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>() == null) {
// The base object ID must be unique.
var baseObjects = character.GetComponentsInChildren<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>();
for (int i = 0; i < baseObjects.Length; ++i) {
if (baseObjects[i].ID > maxID) {
maxID = baseObjects[i].ID;
}
}
}
var baseObject = firstPersonObject.AddComponent<FirstPersonController.Character.Identifiers.FirstPersonBaseObject>();
baseObject.ID = maxID + 1;
firstPersonObject.transform.SetLayerRecursively(LayerManager.Overlay);
if (firstPersonObjectAnimatorController != null) {
Animator animator;
if ((animator = firstPersonObject.GetComponent<Animator>()) == null) {
animator = firstPersonObject.AddComponent<Animator>();
}
animator.applyRootMotion = false;
animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
animator.runtimeAnimatorController = firstPersonObjectAnimatorController;
if (firstPersonObject.GetComponent<ChildAnimatorMonitor>() == null) {
firstPersonObject.AddComponent<ChildAnimatorMonitor>();
}
}
}
/// <summary>
/// Removes the third person item.
/// </summary>
/// <param name="firstPersonPerspectiveItem">The item to remove.</param>
public static void RemoveFirstPersonObject(FirstPersonController.Items.FirstPersonPerspectiveItem firstPersonPerspectiveItem)
{
// Remove any properties which use the first person object.
var itemProperties = firstPersonPerspectiveItem.GetComponents<FirstPersonController.Items.FirstPersonItemProperties>();
for (int i = itemProperties.Length - 1; i > -1; --i) {
Object.DestroyImmediate(itemProperties[i], true);
}
if (firstPersonPerspectiveItem.VisibleItem != null) {
Object.DestroyImmediate(firstPersonPerspectiveItem.VisibleItem, true);
}
Object.DestroyImmediate(firstPersonPerspectiveItem, true);
}
#endif
/// <summary>
/// Adds the third person object to the specified item.
/// </summary>
/// <param name="character">The character that the third person object is being added to.</param>
/// <param name="name">The name of the item.</param>
/// <param name="itemGameObject">A reference to the item's GameObject.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
/// <param name="thirdPersonItemSlot">A reference to the ItemSlot to add the third person item to.</param>
/// <param name="thirdPersonObjectAnimatorController">A reference to the animator controller added to the third person object. Can be null.</param>
/// <param name="invisibleShadowCasterMaterial">A reference to the invisible shadow caster material. This is only used for first person characters.</param>
/// <param name="defaultAddThirdPersonObject">Should the ThirdPersonObject component be added to the object?</param>
public static void AddThirdPersonObject(GameObject character, string name, GameObject itemGameObject, ref GameObject thirdPersonObject, ItemSlot thirdPersonItemSlot,
RuntimeAnimatorController thirdPersonObjectAnimatorController, Material invisibleShadowCasterMaterial, bool defaultAddThirdPersonObject)
{
var visibleItem = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonPerspectiveItem>();
if (thirdPersonObject != null) {
thirdPersonObject = GameObject.Instantiate(thirdPersonObject);
thirdPersonObject.name = (character == null ? "Third Person " : "") + name;
visibleItem.Object = thirdPersonObject;
var addThirdPersonObject = defaultAddThirdPersonObject;
#if THIRD_PERSON_CONTROLLER
if (character != null && !addThirdPersonObject) {
var characterLocomotion = character.GetComponent<UltimateCharacterLocomotion>();
var movementTypes = characterLocomotion.GetSerializedMovementTypes();
if (movementTypes != null) {
for (int i = 0; i < movementTypes.Length; ++i) {
if (characterLocomotion.MovementTypes[i].GetType().FullName.Contains("ThirdPerson")) {
addThirdPersonObject = true;
break;
}
}
}
#if ULTIMATE_CHARACTER_CONTROLLER_MULTIPLAYER
var networkInfo = character.GetComponent<Networking.INetworkInfo>();
if (networkInfo != null) {
addThirdPersonObject = true;
}
#endif
}
#else
addThirdPersonObject = false;
#endif
if (addThirdPersonObject) {
// The ThirdPersonObject component is added so the PerspectiveMonitor knows what objects should use the invisible shadow caster material.
thirdPersonObject.AddComponent<Character.Identifiers.ThirdPersonObject>();
} else {
// If the ThirdPersonObject isn't added then the renderer should be directly attached.
var renderers = thirdPersonObject.GetComponentsInChildren<Renderer>();
for (int i = 0; i < renderers.Length; ++i) {
var materials = renderers[i].sharedMaterials;
for (int j = 0; j < materials.Length; ++j) {
materials[j] = invisibleShadowCasterMaterial;
}
renderers[i].sharedMaterials = materials;
}
}
if (thirdPersonObject.GetComponent<AudioSource>() == null) {
var audioSource = thirdPersonObject.AddComponent<AudioSource>();
audioSource.playOnAwake = false;
audioSource.spatialBlend = 1;
audioSource.maxDistance = 20;
}
// Optionally add the animator.
if (thirdPersonObjectAnimatorController != null) {
Animator animator;
if ((animator = thirdPersonObject.GetComponent<Animator>()) == null) {
animator = thirdPersonObject.AddComponent<Animator>();
}
animator.applyRootMotion = false;
animator.cullingMode = AnimatorCullingMode.AlwaysAnimate;
animator.runtimeAnimatorController = thirdPersonObjectAnimatorController;
if (thirdPersonObject.GetComponent<ChildAnimatorMonitor>() == null) {
thirdPersonObject.AddComponent<ChildAnimatorMonitor>();
}
}
Transform parentTransform = null;
if (character != null) {
parentTransform = thirdPersonItemSlot.transform;
} else {
// The object should be a child of the item GameObject.
parentTransform = itemGameObject.transform;
}
// Assign the transform position and layer.
thirdPersonObject.transform.SetParentOrigin(parentTransform);
thirdPersonObject.transform.SetLayerRecursively(LayerManager.SubCharacter);
}
// Add any properties for actions which have already been added.
AddPropertiesToActions(itemGameObject, null, null, thirdPersonObject);
}
/// <summary>
/// Adds the properties to any actions already created.
/// </summary>
/// <param name="itemGameObject">A reference to the item's GameObject.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddPropertiesToActions(GameObject itemGameObject, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
var actions = itemGameObject.GetComponents<ItemAction>();
for (int i = 0; i < actions.Length; ++i) {
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
if (actions[i] is ShootableWeapon) {
AddShootableWeaponProperties(itemGameObject, actions[i].ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
continue;
}
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
if (actions[i] is MeleeWeapon) {
AddMeleeWeaponProperties(itemGameObject, actions[i].ID, (firstPersonObject != null || firstPersonVisibleItem != null), firstPersonVisibleItem, thirdPersonObject != null, thirdPersonObject);
continue;
}
#endif
if (actions[i] is GrenadeItem) {
AddGrenadeItemProperties(itemGameObject, actions[i].ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
continue;
}
if (actions[i] is ThrowableItem) {
AddThrowableItemProperties(itemGameObject, actions[i].ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
continue;
}
if (actions[i] is Flashlight) {
AddFlashlightProperties(itemGameObject, actions[i].ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
continue;
}
}
}
/// <summary>
/// Removes the third person item.
/// </summary>
/// <param name="thirdPersonVisibleItem">The item to remove.</param>
public static void RemoveThirdPersonObject(ThirdPersonController.Items.ThirdPersonPerspectiveItem thirdPersonVisibleItem)
{
// Remove any properties which use the third person object.
var itemProperties = thirdPersonVisibleItem.GetComponents<ThirdPersonController.Items.ThirdPersonItemProperties>();
for (int i = itemProperties.Length - 1; i > -1; --i) {
Object.DestroyImmediate(itemProperties[i], true);
}
Object.DestroyImmediate(thirdPersonVisibleItem.Object, true);
Object.DestroyImmediate(thirdPersonVisibleItem, true);
}
/// <summary>
/// Adds the specified ActionType to the item.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the action to.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
/// <param name="actionType">The type of action to add.</param>
/// <param name="actionItemDefinition">The ItemDefinition that the action uses (optional).</param>
public static void AddAction(GameObject itemGameObject, bool addFirstPersonPerspective, GameObject firstPersonObject, GameObject firstPersonVisibleItem,
bool addThirdPersonPerspective, GameObject thirdPersonObject, ActionType actionType, ItemDefinitionBase actionItemDefinition)
{
// The action ID must be unique.
var maxID = -1;
var actions = itemGameObject.GetComponents<ItemAction>();
for (int i = 0; i < actions.Length; ++i) {
if (actions[i].ID > maxID) {
maxID = actions[i].ID;
}
}
switch (actionType) {
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
case ActionType.ShootableWeapon:
var shootableWeapon = itemGameObject.AddComponent<ShootableWeapon>();
shootableWeapon.ID = maxID + 1;
shootableWeapon.ConsumableItemDefinition = actionItemDefinition;
AddShootableWeaponProperties(itemGameObject, shootableWeapon.ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
break;
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
case ActionType.MeleeWeapon:
var meleeWeapon = itemGameObject.AddComponent<MeleeWeapon>();
meleeWeapon.ID = maxID + 1;
meleeWeapon.FaceTarget = false;
AddMeleeWeaponProperties(itemGameObject, meleeWeapon.ID, addFirstPersonPerspective, firstPersonVisibleItem, addThirdPersonPerspective, thirdPersonObject);
break;
case ActionType.Shield:
var shield = itemGameObject.AddComponent<Shield>();
shield.ID = maxID + 1;
var shieldAttributeManager = itemGameObject.AddComponent<Traits.AttributeManager>();
shieldAttributeManager.Attributes[0].Name = "Durability"; // Rename the Health attribute to Durability.
AddShieldProperties(shield, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
// The Block ability should be added if it isn't already.
var characterLocomotion = itemGameObject.GetComponentInParent<UltimateCharacterLocomotion>();
if (characterLocomotion != null) {
var blockAbility = characterLocomotion.GetAbility<Character.Abilities.Items.Block>();
if (blockAbility == null) {
AbilityBuilder.AddAbility(characterLocomotion, typeof(Character.Abilities.Items.Block));
}
}
break;
#endif
case ActionType.MagicItem:
var magicItem = itemGameObject.AddComponent<MagicItem>();
var item = itemGameObject.GetComponent<Item>();
item.EquipEvent = new AnimationEventTrigger(false, 0);
item.UnequipEvent = new AnimationEventTrigger(false, 0);
AddMagicItemProperties(itemGameObject, magicItem.ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
break;
case ActionType.ThrowableItem:
var throwableItem = itemGameObject.AddComponent<ThrowableItem>();
throwableItem.ID = maxID + 1;
throwableItem.CanEquipEmptyItem = false;
AddThrowableItemProperties(itemGameObject, throwableItem.ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
break;
case ActionType.GrenadeItem:
var grenadeItem = itemGameObject.AddComponent<GrenadeItem>();
grenadeItem.ID = maxID + 1;
grenadeItem.CanEquipEmptyItem = false;
AddGrenadeItemProperties(itemGameObject, grenadeItem.ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
break;
case ActionType.Flashlight:
var flashLight = itemGameObject.AddComponent<Flashlight>();
flashLight.ID = maxID + 1;
flashLight.UseEvent = new AnimationEventTrigger(false, 0);
flashLight.UseCompleteEvent = new AnimationEventTrigger(false, 0);
var flashlightAttributeManager = itemGameObject.AddComponent<Traits.AttributeManager>();
flashlightAttributeManager.Attributes[0].Name = "Battery"; // Rename the Health attribute to Battery.
AddFlashlightProperties(itemGameObject, flashLight.ID, firstPersonObject, firstPersonVisibleItem, thirdPersonObject);
break;
}
}
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
/// <summary>
/// Adds the ShootableWeaponProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddShootableWeaponProperties(GameObject itemGameObject, int actionID, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_SHOOTER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var parent = firstPersonVisibleItem != null ? firstPersonVisibleItem.transform : firstPersonObject.transform;
var shootableProperties = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonShootableWeaponProperties>();
// Setup the standard references.
shootableProperties.ActionID = actionID;
shootableProperties.FirePointLocation = CreateGameObject("Fire Point", parent);
shootableProperties.MuzzleFlashLocation = CreateGameObject("Muzzle Flash", parent);
shootableProperties.ShellLocation = CreateGameObject("Shell Eject Point", parent);
}
#endif
if (thirdPersonObject != null) {
var shootableProperties = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonShootableWeaponProperties>();
// Setup the standard references.
shootableProperties.ActionID = actionID;
shootableProperties.FirePointLocation = CreateGameObject("Fire Point", thirdPersonObject.transform);
shootableProperties.MuzzleFlashLocation = CreateGameObject("Muzzle Flash", thirdPersonObject.transform);
shootableProperties.ShellLocation = CreateGameObject("Shell Eject Point", thirdPersonObject.transform);
}
}
#endif
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
/// <summary>
/// Adds the MeleeWeaponProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="addFirstPersonPerspective">Should the first person perspective be added?</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="addThirdPersonPerspective">Should the third person perspective be added?</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddMeleeWeaponProperties(GameObject itemGameObject, int actionID, bool addFirstPersonPerspective, GameObject firstPersonVisibleItem,
bool addThirdPersonPerspective, GameObject thirdPersonObject)
{
#if FIRST_PERSON_MELEE
if (itemGameObject) {
var meleeWeaponProperties = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonMeleeWeaponProperties>();
meleeWeaponProperties.ActionID = actionID;
if (firstPersonVisibleItem != null) {
BoxCollider boxCollider;
if ((boxCollider = firstPersonVisibleItem.GetComponent<BoxCollider>()) == null) {
boxCollider = firstPersonVisibleItem.AddComponent<BoxCollider>();
}
meleeWeaponProperties.Hitboxes = new MeleeWeapon.MeleeHitbox[] { new MeleeWeapon.MeleeHitbox(boxCollider) };
}
}
#endif
if (addThirdPersonPerspective) {
var meleeWeaponProperties = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonMeleeWeaponProperties>();
meleeWeaponProperties.ActionID = actionID;
if (thirdPersonObject != null) {
BoxCollider boxCollider;
if ((boxCollider = thirdPersonObject.GetComponent<BoxCollider>()) == null) {
boxCollider = thirdPersonObject.AddComponent<BoxCollider>();
}
meleeWeaponProperties.Hitboxes = new MeleeWeapon.MeleeHitbox[] { new MeleeWeapon.MeleeHitbox(boxCollider) };
}
}
}
/// <summary>
/// Adds the shield properties to the specified GameObject.
/// </summary>
/// <param name="shield">A reference to the parent Shield component.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddShieldProperties(Shield shield, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var shieldCollider = firstPersonVisibleItem.AddComponent<Objects.ItemAssist.ShieldCollider>();
shieldCollider.Shield = shield;
shieldCollider.FirstPersonPerspective = true;
if (firstPersonVisibleItem.GetComponent<BoxCollider>() == null) {
firstPersonVisibleItem.AddComponent<BoxCollider>();
}
}
#endif
if (thirdPersonObject != null) {
var shieldCollider = thirdPersonObject.AddComponent<Objects.ItemAssist.ShieldCollider>();
shieldCollider.Shield = shield;
if (thirdPersonObject.GetComponent<BoxCollider>() == null) {
thirdPersonObject.AddComponent<BoxCollider>();
}
}
}
#endif
/// <summary>
/// Adds the MagicItemProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddMagicItemProperties(GameObject itemGameObject, int actionID, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var parent = firstPersonVisibleItem != null ? firstPersonVisibleItem.transform : firstPersonObject.transform;
var magicItemProperties = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonMagicItemProperties>();
// Setup the standard references.
magicItemProperties.ActionID = actionID;
magicItemProperties.OriginLocation = CreateGameObject("Origin", parent);
}
#endif
var character = itemGameObject.GetComponentInParent<UltimateCharacterLocomotion>();
if (thirdPersonObject != null || (character != null && character.GetComponent<Animator>() != null)) {
var magicItemProperties = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonMagicItemProperties>();
// Setup the standard references.
magicItemProperties.ActionID = actionID;
magicItemProperties.OriginLocation = CreateGameObject("Origin", thirdPersonObject.transform);
}
}
/// <summary>
/// Adds the ThrowableItemProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddThrowableItemProperties(GameObject itemGameObject, int actionID, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var throwableProperties = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonThrowableItemProperties>();
// Setup the standard references.
throwableProperties.ActionID = actionID;
throwableProperties.ThrowLocation = throwableProperties.TrajectoryLocation = (firstPersonVisibleItem != null ? firstPersonVisibleItem : firstPersonObject).transform;
}
#endif
if (thirdPersonObject != null) {
var throwableProperties = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonThrowableItemProperties>();
// Setup the standard references.
throwableProperties.ActionID = actionID;
throwableProperties.ThrowLocation = throwableProperties.TrajectoryLocation = thirdPersonObject.transform;
}
// Throwable items should be completely dropped.
var item = itemGameObject.GetComponent<Item>();
item.FullInventoryDrop = true;
}
/// <summary>
/// Adds the GrenadeItemProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddGrenadeItemProperties(GameObject itemGameObject, int actionID, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var grenadeProperties = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonGrenadeItemProperties>();
// Setup the standard references.
grenadeProperties.ActionID = actionID;
grenadeProperties.ThrowLocation = grenadeProperties.TrajectoryLocation = (firstPersonVisibleItem != null ? firstPersonVisibleItem : firstPersonObject).transform;
// The Grenade component should not exist on the first person visible item.
if (firstPersonVisibleItem != null && firstPersonVisibleItem.GetComponent<Objects.Grenade>() != null) {
GameObject.DestroyImmediate(firstPersonVisibleItem.GetComponent<Objects.Grenade>(), true);
// If the grenade component exists then a collider does as well.
if (firstPersonVisibleItem.GetComponent<Collider>() != null) {
GameObject.DestroyImmediate(firstPersonVisibleItem.GetComponent<Collider>(), true);
}
}
}
#endif
if (thirdPersonObject != null) {
var grenadeProperties = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonGrenadeItemProperties>();
// Setup the standard references.
grenadeProperties.ActionID = actionID;
grenadeProperties.ThrowLocation = grenadeProperties.TrajectoryLocation = thirdPersonObject.transform;
// The Grenade component should not exist on the third person object.
if (thirdPersonObject.GetComponent<Objects.Grenade>() != null) {
GameObject.DestroyImmediate(thirdPersonObject.GetComponent<Objects.Grenade>(), true);
// If the grenade component exists then a collider does as well.
if (thirdPersonObject.GetComponent<Collider>() != null) {
GameObject.DestroyImmediate(thirdPersonObject.GetComponent<Collider>(), true);
}
}
}
// Grenades should be completely dropped.
var item = itemGameObject.GetComponent<Item>();
item.FullInventoryDrop = true;
}
/// <summary>
/// Adds the FlashlightProperties to the specified GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the properties to.</param>
/// <param name="actionID">The ActionID of the properties.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void AddFlashlightProperties(GameObject itemGameObject, int actionID, GameObject firstPersonObject, GameObject firstPersonVisibleItem, GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
if (firstPersonObject != null || firstPersonVisibleItem != null) {
var flashlight = itemGameObject.AddComponent<FirstPersonController.Items.FirstPersonFlashlightProperties>();
// Setup the standard references.
flashlight.ActionID = actionID;
var lightGameObject = new GameObject("Light", typeof(Light));
lightGameObject.transform.SetParentOrigin((firstPersonVisibleItem != null ? firstPersonVisibleItem : firstPersonObject).transform);
flashlight.Light = lightGameObject;
}
#endif
if (thirdPersonObject != null) {
var flashlight = itemGameObject.AddComponent<ThirdPersonController.Items.ThirdPersonFlashlightProperties>();
// Setup the standard references.
flashlight.ActionID = actionID;
var lightGameObject = new GameObject("Light", typeof(Light));
lightGameObject.transform.SetParentOrigin(thirdPersonObject.transform);
flashlight.Light = lightGameObject;
}
}
/// <summary>
/// Adds the specified ActionType to the item.
/// </summary>
/// <param name="itemGameObject">The GameObject to add the action to.</param>
/// <param name="actionType">The type of action to add.</param>
/// <param name="actionItemDefinition">The ItemDefinition that the action uses (optional).</param>
public static void AddAction(GameObject itemGameObject, ActionType actionType, ItemDefinitionBase actionItemDefinition)
{
GameObject firstPersonObject = null, firstPersonVisibleItemGameObject = null, thirdPersonObject = null;
PopulatePerspectiveObjects(itemGameObject, ref firstPersonObject, ref firstPersonVisibleItemGameObject, ref thirdPersonObject);
AddAction(itemGameObject, (firstPersonObject != null || firstPersonVisibleItemGameObject != null), firstPersonObject, firstPersonVisibleItemGameObject, thirdPersonObject != null, thirdPersonObject, actionType, actionItemDefinition);
}
/// <summary>
/// Populates the first and third person objects for the specified item GameObject.
/// </summary>
/// <param name="itemGameObject">The GameObject to get the first and third person references of.</param>
/// <param name="firstPersonObject">A reference to the GameObject used in first person view.</param>
/// <param name="firstPersonVisibleItem">A reference to the visible first person item.</param>
/// <param name="thirdPersonObject">A reference to the GameObject used in third person view.</param>
private static void PopulatePerspectiveObjects(GameObject itemGameObject, ref GameObject firstPersonObject, ref GameObject firstPersonVisibleItemGameObject, ref GameObject thirdPersonObject)
{
#if FIRST_PERSON_CONTROLLER
var firstPersonVisibleItem = itemGameObject.GetComponent<FirstPersonController.Items.FirstPersonPerspectiveItem>();
if (firstPersonVisibleItem != null) {
firstPersonObject = firstPersonVisibleItem.Object;
firstPersonVisibleItemGameObject = firstPersonVisibleItem.VisibleItem;
}
#endif
var thirdPersonVisibleItem = itemGameObject.GetComponent<ThirdPersonController.Items.ThirdPersonPerspectiveItem>();
if (thirdPersonVisibleItem != null) {
thirdPersonObject = thirdPersonVisibleItem.Object;
}
}
/// <summary>
/// Removes the specified action.
/// </summary>
/// <param name="itemAction">The action to remove.</param>
public static void RemoveAction(ItemAction itemAction)
{
// Remove the matching perspective properties first so the ID can be matched.
RemovePerspectiveProperties(itemAction.gameObject, itemAction.ID);
Object.DestroyImmediate(itemAction, true);
}
/// <summary>
/// Removes the perspective properties on the item with the specified ID.
/// </summary>
/// <param name="itemGameObject">The GameObject which has the ItemPerpsectiveProperties.</param>
private static void RemovePerspectiveProperties(GameObject itemGameObject, int actionID)
{
var perspectiveProperties = itemGameObject.GetComponents<ItemPerspectiveProperties>();
for (int i = perspectiveProperties.Length - 1; i > -1; --i) {
if (perspectiveProperties[i].ActionID != actionID) {
continue;
}
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
var shootableWeaponPerspectiveProperties = perspectiveProperties[i] as IShootableWeaponPerspectiveProperties;
if (shootableWeaponPerspectiveProperties != null) {
var propertyTransform = shootableWeaponPerspectiveProperties.FirePointLocation;
if (propertyTransform != null) {
Object.DestroyImmediate(propertyTransform.gameObject, true);
}
propertyTransform = shootableWeaponPerspectiveProperties.MuzzleFlashLocation;
if (propertyTransform != null) {
Object.DestroyImmediate(propertyTransform.gameObject, true);
}
propertyTransform = shootableWeaponPerspectiveProperties.ShellLocation;
if (propertyTransform != null) {
Object.DestroyImmediate(propertyTransform.gameObject, true);
}
propertyTransform = shootableWeaponPerspectiveProperties.SmokeLocation;
if (propertyTransform != null) {
Object.DestroyImmediate(propertyTransform.gameObject, true);
}
}
#endif
Object.DestroyImmediate(perspectiveProperties[i], true);
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c0c054c10eb2cd343bd52134acc1df50
timeCreated: 1513169106
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,157 @@
/// ---------------------------------------------
/// Ultimate Character Controller
/// Copyright (c) Opsive. All Rights Reserved.
/// https://www.opsive.com
/// ---------------------------------------------
namespace Opsive.UltimateCharacterController.Utility.Builders
{
using Opsive.UltimateCharacterController.Camera;
using Opsive.UltimateCharacterController.Camera.ViewTypes;
using Opsive.UltimateCharacterController.StateSystem;
using System;
using System.Collections.Generic;
/// <summary>
/// Adds and serializes CameraController view types.
/// </summary>
public static class ViewTypeBuilder
{
private static Dictionary<Type, AddState[]> s_AddStates = new Dictionary<Type, AddState[]>();
/// <summary>
/// Adds the view type with the specified type.
/// </summary>
/// <param name="cameraController">The camera to add the ability to.</param>
/// <param name="viewType">The type of view type to add.</param>
/// <returns>The added view type.</returns>
public static ViewType AddViewType(CameraController cameraController, Type viewType)
{
var viewTypes = cameraController.ViewTypes;
if (viewTypes == null) {
viewTypes = new ViewType[1];
} else {
Array.Resize(ref viewTypes, viewTypes.Length + 1);
}
var viewTypeObj = Activator.CreateInstance(viewType) as ViewType;
viewTypes[viewTypes.Length - 1] = viewTypeObj;
cameraController.ViewTypes = viewTypes;
#if FIRST_PERSON_CONTROLLER
if (viewTypeObj is FirstPersonController.Camera.ViewTypes.FirstPerson) {
AddFirstPersonCamera(cameraController, viewTypeObj as FirstPersonController.Camera.ViewTypes.FirstPerson);
}
#endif
#if UNITY_EDITOR
var addStates = GetAddStates(viewType);
if (addStates != null && addStates.Length > 0) {
var states = viewTypeObj.States;
var addedStates = 0;
var stateLength = states.Length;
Array.Resize(ref states, stateLength + addStates.Length);
// Default must always be at the end.
states[states.Length - 1] = states[0];
for (int i = 0; i < addStates.Length; ++i) {
var presetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(addStates[i].PresetGUID);
if (!string.IsNullOrEmpty(presetPath)) {
var preset = UnityEditor.AssetDatabase.LoadAssetAtPath(presetPath, typeof(PersistablePreset)) as PersistablePreset;
if (preset != null) {
states[i] = new State(addStates[i].Name, preset, null);
addedStates++;
}
}
}
if (addedStates != addStates.Length) {
Array.Resize(ref states, stateLength + addedStates);
}
viewTypeObj.States = states;
}
#endif
SerializeViewTypes(cameraController);
if (!(viewTypeObj is Transition)) {
cameraController.SetViewType(viewType, false);
}
return viewTypeObj;
}
#if FIRST_PERSON_CONTROLLER
/// <summary>
/// Adds a first person camera to the view type.
/// </summary>
/// <param name="cameraController">The camera controller that contains the view type.</param>
/// <param name="viewType">The first person view type.</param>
public static void AddFirstPersonCamera(CameraController cameraController, FirstPersonController.Camera.ViewTypes.FirstPerson viewType)
{
// A first person camera must be added to the first peron view types.
cameraController.DeserializeViewTypes();
var viewTypes = cameraController.ViewTypes;
UnityEngine.Camera firstPersonCamera = null;
FirstPersonController.Camera.ViewTypes.FirstPerson firstPersonViewType;
for (int i = 0; i < viewTypes.Length; ++i) {
if ((firstPersonViewType = viewTypes[i] as FirstPersonController.Camera.ViewTypes.FirstPerson) != null &&
firstPersonViewType.FirstPersonCamera != null) {
firstPersonCamera = firstPersonViewType.FirstPersonCamera;
break;
}
}
// If the camera is null then a new first person camera should be created.
if (firstPersonCamera == null) {
UnityEngine.Transform firstPersonCameraTransform;
if ((firstPersonCameraTransform = cameraController.transform.Find("First Person Camera")) != null) {
firstPersonCamera = firstPersonCameraTransform.GetComponent<UnityEngine.Camera>();
}
if (firstPersonCamera == null) {
var cameraGameObject = new UnityEngine.GameObject("First Person Camera");
cameraGameObject.transform.SetParentOrigin(cameraController.transform);
firstPersonCamera = cameraGameObject.AddComponent<UnityEngine.Camera>();
firstPersonCamera.clearFlags = UnityEngine.CameraClearFlags.Depth;
firstPersonCamera.fieldOfView = 60f;
firstPersonCamera.nearClipPlane = 0.01f;
firstPersonCamera.depth = 0;
firstPersonCamera.renderingPath = cameraController.GetComponent<UnityEngine.Camera>().renderingPath;
}
}
viewType.FirstPersonCamera = firstPersonCamera;
}
#endif
/// <summary>
/// Serialize all of the view types to the ViewTypeData array.
/// </summary>
/// <param name="cameraController">The camera controller to serialize.</param>
public static void SerializeViewTypes(CameraController cameraController)
{
var viewTypes = new List<ViewType>(cameraController.ViewTypes);
cameraController.ViewTypeData = Shared.Utility.Serialization.Serialize<ViewType>(viewTypes);
#if UNITY_EDITOR
UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(cameraController);
#endif
cameraController.ViewTypes = viewTypes.ToArray();
}
/// <summary>
/// Returns the AddState of the specified view type.
/// </summary>
/// <param name="type">The view type.</param>
/// <returns>The AddState of the specified ability type. Can be null.</returns>
private static AddState[] GetAddStates(Type type)
{
AddState[] addStates;
if (s_AddStates.TryGetValue(type, out addStates)) {
return addStates;
}
if (type.GetCustomAttributes(typeof(AddState), true).Length > 0) {
addStates = type.GetCustomAttributes(typeof(AddState), true) as AddState[];
}
s_AddStates.Add(type, addStates);
return addStates;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 42c0264a57605f24684775571453dda2
timeCreated: 1513110789
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: