update
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
#if NET_4_6 || UNITY_2018_3_OR_NEWER || UNITY_WEBGL || UNITY_IOS || UNITY_ANDROID || UNITY_WII || UNITY_WIIU || UNITY_SWITCH || UNITY_PS3 || UNITY_PS4 || UNITY_XBOXONE || UNITY_WSA
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
// This class is required in order for the preset system to work with AOT platforms. The preset system uses reflection to generate the delegates
|
||||
// and reflection doesn't play well with AOT because the classes need to be defined ahead of time. Define the classes here so the compiler will
|
||||
// add in the correct type. This code is not actually used anywhere, it is purely for the compiler.
|
||||
public class AOTLinker : MonoBehaviour
|
||||
{
|
||||
public void Linker()
|
||||
{
|
||||
#pragma warning disable 0219
|
||||
var intGenericDelegate = new Preset.GenericDelegate<int>();
|
||||
var intFuncDelegate = new Func<int>(() => { return 0; });
|
||||
var intActionDelegate = new Action<int>((int value) => { });
|
||||
var floatGenericDelegate = new Preset.GenericDelegate<float>();
|
||||
var floatFuncDelegate = new Func<float>(() => { return 0; });
|
||||
var floatActionDelegate = new Action<float>((float value) => { });
|
||||
var uintGenericDelegate = new Preset.GenericDelegate<uint>();
|
||||
var uintFuncDelegate = new Func<uint>(() => { return 0; });
|
||||
var uintActionDelegate = new Action<uint>((uint value) => { });
|
||||
var doubleGenericDelegate = new Preset.GenericDelegate<double>();
|
||||
var doubleFuncDelegate = new Func<double>(() => { return 0; });
|
||||
var doubleActionDelegate = new Action<double>((double value) => { });
|
||||
var longGenericDelegate = new Preset.GenericDelegate<long>();
|
||||
var longFuncDelegate = new Func<long>(() => { return 0; });
|
||||
var longActionDelegate = new Action<long>((long value) => { });
|
||||
var boolGenericDelegate = new Preset.GenericDelegate<bool>();
|
||||
var boolFuncDelegate = new Func<bool>(() => { return true; });
|
||||
var boolActionDelegate = new Action<bool>((bool value) => { });
|
||||
var stringGenericDelegate = new Preset.GenericDelegate<string>();
|
||||
var stringFuncDelegate = new Func<string>(() => { return string.Empty; });
|
||||
var stringActionDelegate = new Action<string>((string value) => { });
|
||||
var byteGenericDelegate = new Preset.GenericDelegate<byte>();
|
||||
var byteFuncDelegate = new Func<byte>(() => { return new byte(); });
|
||||
var byteActionDelegate = new Action<byte>((byte value) => { });
|
||||
var vector2GenericDelegate = new Preset.GenericDelegate<Vector2>();
|
||||
var vector2FuncDelegate = new Func<Vector2>(() => { return Vector2.zero; });
|
||||
var vector2ActionDelegate = new Action<Vector2>((Vector2 value) => { });
|
||||
var vector3GenericDelegate = new Preset.GenericDelegate<Vector3>();
|
||||
var vector3FuncDelegate = new Func<Vector3>(() => { return Vector3.zero; });
|
||||
var vector3ActionDelegate = new Action<Vector3>((Vector3 value) => { });
|
||||
var vector4GenericDelegate = new Preset.GenericDelegate<Vector4>();
|
||||
var vector4FuncDelegate = new Func<Vector4>(() => { return Vector4.zero; });
|
||||
var vector4ActionDelegate = new Action<Vector4>((Vector4 value) => { });
|
||||
var quaternionGenericDelegate = new Preset.GenericDelegate<Quaternion>();
|
||||
var quaternionFuncDelegate = new Func<Quaternion>(() => { return Quaternion.identity; });
|
||||
var quaternionActionDelegate = new Action<Quaternion>((Quaternion value) => { });
|
||||
var colorGenericDelegate = new Preset.GenericDelegate<Color>();
|
||||
var colorFuncDelegate = new Func<Color>(() => { return Color.white; });
|
||||
var colorActionDelegate = new Action<Color>((Color value) => { });
|
||||
var rectGenericDelegate = new Preset.GenericDelegate<Rect>();
|
||||
var rectFuncDelegate = new Func<Rect>(() => { return Rect.zero; });
|
||||
var rectActionDelegate = new Action<Rect>((Rect value) => { });
|
||||
var matrix4x4GenericDelegate = new Preset.GenericDelegate<Matrix4x4>();
|
||||
var matrix4x4FuncDelegate = new Func<Matrix4x4>(() => { return Matrix4x4.zero; });
|
||||
var matrix4x4ActionDelegate = new Action<Matrix4x4>((Matrix4x4 value) => { });
|
||||
var animationCurveGenericDelegate = new Preset.GenericDelegate<AnimationCurve>();
|
||||
var animationCurveFuncDelegate = new Func<AnimationCurve>(() => { return new AnimationCurve(); });
|
||||
var animationCurveActionDelegate = new Action<AnimationCurve>((AnimationCurve value) => { });
|
||||
var layerMaskGenericDelegate = new Preset.GenericDelegate<LayerMask>();
|
||||
var layerMaskFuncDelegate = new Func<LayerMask>(() => { return new LayerMask(); });
|
||||
var layerMaskActionDelegate = new Action<LayerMask>((LayerMask value) => { });
|
||||
var humanBodyBonesGenericDelegate = new Preset.GenericDelegate<HumanBodyBones>();
|
||||
var humanBodyBonesFuncDelegate = new Func<HumanBodyBones>(() => { return 0; });
|
||||
var humanBodyBonesActionDelegate = new Action<HumanBodyBones>((HumanBodyBones value) => { });
|
||||
var queryTriggerInteractionGenericDelegate = new Preset.GenericDelegate<QueryTriggerInteraction>();
|
||||
var queryTriggerInteractionFuncDelegate = new Func<QueryTriggerInteraction>(() => { return 0; });
|
||||
var queryTriggerInteractionActionDelegate = new Action<QueryTriggerInteraction>((QueryTriggerInteraction value) => { });
|
||||
var forceModeGenericDelegate = new Preset.GenericDelegate<ForceMode>();
|
||||
var forceModeFuncDelegate = new Func<ForceMode>(() => { return 0; });
|
||||
var forceModeActionDelegate = new Action<ForceMode>((ForceMode value) => { });
|
||||
var unityObjectGenericDelegate = new Preset.GenericDelegate<UnityEngine.Object>();
|
||||
var unityObjectFuncDelegate = new Func<UnityEngine.Object>(() => { return new UnityEngine.Object(); });
|
||||
var unityObjectActionDelegate = new Action<UnityEngine.Object>((UnityEngine.Object value) => { });
|
||||
var gameObjectGenericDelegate = new Preset.GenericDelegate<GameObject>();
|
||||
var gameObjectFuncDelegate = new Func<GameObject>(() => { return null; });
|
||||
var gameObjectActionDelegate = new Action<GameObject>((GameObject value) => { });
|
||||
var transformGenericDelegate = new Preset.GenericDelegate<Transform>();
|
||||
var transformFuncDelegate = new Func<Transform>(() => { return null; });
|
||||
var transformActionDelegate = new Action<Transform>((Transform value) => { });
|
||||
var minMaxFloatGenericDelegate = new Preset.GenericDelegate<Utility.MinMaxFloat>();
|
||||
var minMaxFloatFuncDelegate = new Func<Utility.MinMaxFloat>(() => { return new Utility.MinMaxFloat(); });
|
||||
var minMaxFloatActionDelegate = new Action<Utility.MinMaxFloat>((Utility.MinMaxFloat value) => { });
|
||||
var minMaxVector3GenericDelegate = new Preset.GenericDelegate<Utility.MinMaxVector3>();
|
||||
var minMaxVector3FuncDelegate = new Func<Utility.MinMaxVector3>(() => { return new Utility.MinMaxVector3(); });
|
||||
var minMaxVector3ActionDelegate = new Action<Utility.MinMaxVector3>((Utility.MinMaxVector3 value) => { });
|
||||
var lookVectorModeGenericDelegate = new Preset.GenericDelegate<UltimateCharacterController.Input.PlayerInput.LookVectorMode>();
|
||||
var lookVectorModeFuncDelegate = new Func<UltimateCharacterController.Input.PlayerInput.LookVectorMode>(() => { return 0; });
|
||||
var lookVectorModeActionDelegate = new Action<UltimateCharacterController.Input.PlayerInput.LookVectorMode>((UltimateCharacterController.Input.PlayerInput.LookVectorMode value) => { });
|
||||
var preloadedPrefabGenericDelegate = new Preset.GenericDelegate<Shared.Game.ObjectPool.PreloadedPrefab>();
|
||||
var preloadedPrefabFuncDelegate = new Func<Shared.Game.ObjectPool.PreloadedPrefab>(() => { return new Shared.Game.ObjectPool.PreloadedPrefab(); });
|
||||
var preloadedPrefabActionDelegate = new Action<Shared.Game.ObjectPool.PreloadedPrefab>((Shared.Game.ObjectPool.PreloadedPrefab value) => { });
|
||||
var abilityStartTypeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Ability.AbilityStartType>();
|
||||
var abilityStartTypeFuncDelegate = new Func<Character.Abilities.Ability.AbilityStartType>(() => { return 0; });
|
||||
var abilityStartTypeActionDelegate = new Action<Character.Abilities.Ability.AbilityStartType>((Character.Abilities.Ability.AbilityStartType value) => { });
|
||||
var abilityStopTypeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Ability.AbilityStopType>();
|
||||
var abilityStopTypeFuncDelegate = new Func<Character.Abilities.Ability.AbilityStopType>(() => { return 0; });
|
||||
var abilityStopTypeActionDelegate = new Action<Character.Abilities.Ability.AbilityStopType>((Character.Abilities.Ability.AbilityStopType value) => { });
|
||||
var abilityBoolOverrideGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Ability.AbilityBoolOverride>();
|
||||
var abilityBoolOverrideFuncDelegate = new Func<Character.Abilities.Ability.AbilityBoolOverride>(() => { return 0; });
|
||||
var abilityBoolOverrideActionDelegate = new Action<Character.Abilities.Ability.AbilityBoolOverride>((Character.Abilities.Ability.AbilityBoolOverride value) => { });
|
||||
var comboInputElementGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Starters.ComboTimeout.ComboInputElement>();
|
||||
var comboInputElementFuncDelegate = new Func<Character.Abilities.Starters.ComboTimeout.ComboInputElement>(() => { return new Character.Abilities.Starters.ComboTimeout.ComboInputElement(); });
|
||||
var comboInputElementActionDelegate = new Action<Character.Abilities.Starters.ComboTimeout.ComboInputElement>((Character.Abilities.Starters.ComboTimeout.ComboInputElement value) => { });
|
||||
var restrictionTypeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.RestrictPosition.RestrictionType>();
|
||||
var restrictionTypeFuncDelegate = new Func<Character.Abilities.RestrictPosition.RestrictionType>(() => { return 0; });
|
||||
var restrictionTypeActionDelegate = new Action<Character.Abilities.RestrictPosition.RestrictionType>((Character.Abilities.RestrictPosition.RestrictionType value) => { });
|
||||
var objectDetectionModeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.DetectObjectAbilityBase.ObjectDetectionMode>();
|
||||
var objectDetectionModeTypeFuncDelegate = new Func<Character.Abilities.DetectObjectAbilityBase.ObjectDetectionMode>(() => { return 0; });
|
||||
var objectDetectionModeTypeActionDelegate = new Action<Character.Abilities.DetectObjectAbilityBase.ObjectDetectionMode>((Character.Abilities.DetectObjectAbilityBase.ObjectDetectionMode value) => { });
|
||||
var autoEquipTypeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Items.EquipUnequip.AutoEquipType>();
|
||||
var autoEquipTypeFuncDelegate = new Func<Character.Abilities.Items.EquipUnequip.AutoEquipType>(() => { return 0; });
|
||||
var autoEquipTypeActionDelegate = new Action<Character.Abilities.Items.EquipUnequip.AutoEquipType>((Character.Abilities.Items.EquipUnequip.AutoEquipType value) => { });
|
||||
var shakeTargetGenericDelegate = new Preset.GenericDelegate<Character.Effects.Shake.ShakeTarget>();
|
||||
var shakeTargetFuncDelegate = new Func<Character.Effects.Shake.ShakeTarget>(() => { return 0; });
|
||||
var shakeTargetActionDelegate = new Action<Character.Effects.Shake.ShakeTarget>((Character.Effects.Shake.ShakeTarget value) => { });
|
||||
var attributeAutoUpdateValueTypeGenericDelegate = new Preset.GenericDelegate<Traits.Attribute.AutoUpdateValue>();
|
||||
var attributeAutoUpdateFuncDelegate = new Func<Traits.Attribute.AutoUpdateValue>(() => { return 0; });
|
||||
var attributeAutoUpdateActionDelegate = new Action<Traits.Attribute.AutoUpdateValue>((Traits.Attribute.AutoUpdateValue value) => { });
|
||||
var surfaceImpactGenericDelegate = new Preset.GenericDelegate<SurfaceSystem.SurfaceImpact>();
|
||||
var surfaceImpactFuncDelegate = new Func<SurfaceSystem.SurfaceImpact>(() => { return null; });
|
||||
var surfaceImpactActionDelegate = new Action<SurfaceSystem.SurfaceImpact>((SurfaceSystem.SurfaceImpact value) => { });
|
||||
var uvTextureGenericDelegate = new Preset.GenericDelegate<SurfaceSystem.UVTexture>();
|
||||
var uvTextureFuncDelegate = new Func<SurfaceSystem.UVTexture>(() => { return new SurfaceSystem.UVTexture(); });
|
||||
var uvTextureActionDelegate = new Action<SurfaceSystem.UVTexture>((SurfaceSystem.UVTexture value) => { });
|
||||
var objectSurfaceGenericDelegate = new Preset.GenericDelegate<SurfaceSystem.ObjectSurface>();
|
||||
var objectSurfaceFuncDelegate = new Func<SurfaceSystem.ObjectSurface>(() => { return new SurfaceSystem.ObjectSurface(); });
|
||||
var objectSurfaceActionDelegate = new Action<SurfaceSystem.ObjectSurface>((SurfaceSystem.ObjectSurface value) => { });
|
||||
var objectSpawnInfoGenericDelegate = new Preset.GenericDelegate<Utility.ObjectSpawnInfo>();
|
||||
var objectSpawnInfoFuncDelegate = new Func<Utility.ObjectSpawnInfo>(() => { return null; });
|
||||
var objectSpawnInfoActionDelegate = new Action<Utility.ObjectSpawnInfo>((Utility.ObjectSpawnInfo value) => { });
|
||||
var animationEventTriggerGenericDelegate = new Preset.GenericDelegate<Utility.AnimationEventTrigger>();
|
||||
var animationEventTriggerFuncDelegate = new Func<Utility.AnimationEventTrigger>(() => { return null; });
|
||||
var animationEventTriggerActionDelegate = new Action<Utility.AnimationEventTrigger>((Utility.AnimationEventTrigger value) => { });
|
||||
var characterFootEffectsFootGenericDelegate = new Preset.GenericDelegate<Character.CharacterFootEffects.Foot>();
|
||||
var characterFootEffectsFootFuncDelegate = new Func<Character.CharacterFootEffects.Foot>(() => { return new Character.CharacterFootEffects.Foot(); });
|
||||
var characterFootEffectsFootActionDelegate = new Action<Character.CharacterFootEffects.Foot>((Character.CharacterFootEffects.Foot value) => { });
|
||||
var characterFootEffectsFootstepPlacementModeGenericDelegate = new Preset.GenericDelegate<Character.CharacterFootEffects.FootstepPlacementMode>();
|
||||
var characterFootEffectsFootstepPlacementModeFuncDelegate = new Func<Character.CharacterFootEffects.FootstepPlacementMode>(() => { return 0; });
|
||||
var characterFootEffectsFootstepPlacementModeActionDelegate = new Action<Character.CharacterFootEffects.FootstepPlacementMode>((Character.CharacterFootEffects.FootstepPlacementMode value) => { });
|
||||
var spawnPointSpawnShapeGenericDelegate = new Preset.GenericDelegate<Game.SpawnPoint.SpawnShape>();
|
||||
var spawnShapeFuncDelegate = new Func<Game.SpawnPoint.SpawnShape>(() => { return 0; });
|
||||
var spawnShapeActionDelegate = new Action<Game.SpawnPoint.SpawnShape>((Game.SpawnPoint.SpawnShape value) => { });
|
||||
var respawnerSpawnPositioningModeGenericDelegate = new Preset.GenericDelegate<Traits.Respawner.SpawnPositioningMode>();
|
||||
var respawnerSpawnPositioningFuncDelegate = new Func<Traits.Respawner.SpawnPositioningMode>(() => { return 0; });
|
||||
var respawnerSpawnPositioningActionDelegate = new Action<Traits.Respawner.SpawnPositioningMode>((Traits.Respawner.SpawnPositioningMode value) => { });
|
||||
var movingPlatformWaypointGenericDelegate = new Preset.GenericDelegate<Objects.MovingPlatform.Waypoint>();
|
||||
var movingPlatformWaypointFuncDelegate = new Func<Objects.MovingPlatform.Waypoint>(() => { return new Objects.MovingPlatform.Waypoint(); });
|
||||
var movingPlatformWaypointActionDelegate = new Action<Objects.MovingPlatform.Waypoint>((Objects.MovingPlatform.Waypoint value) => { });
|
||||
var movingPlatformPathMovementTypeGenericDelegate = new Preset.GenericDelegate<Objects.MovingPlatform.PathMovementType>();
|
||||
var movingPlatformPathMovementTypeFuncDelegate = new Func<Objects.MovingPlatform.PathMovementType> (() => { return 0; });
|
||||
var movingPlatformPathMovementTypeActionDelegate = new Action<Objects.MovingPlatform.PathMovementType>((Objects.MovingPlatform.PathMovementType value) => { });
|
||||
var movingPlatformPathDirectionGenericDelegate = new Preset.GenericDelegate<Objects.MovingPlatform.PathDirection>();
|
||||
var movingPlatformPathDirectionFuncDelegate = new Func<Objects.MovingPlatform.PathDirection>(() => { return 0; });
|
||||
var movingPlatformPathDirectionActionDelegate = new Action<Objects.MovingPlatform.PathDirection>((Objects.MovingPlatform.PathDirection value) => { });
|
||||
var movingPlatformMovementInterpolationModeGenericDelegate = new Preset.GenericDelegate<Objects.MovingPlatform.MovementInterpolationMode>();
|
||||
var movingPlatformMovementInterpolationModeFuncDelegate = new Func<Objects.MovingPlatform.MovementInterpolationMode>(() => { return 0; });
|
||||
var movingPlatformMovementInterpolationModeActionDelegate = new Action<Objects.MovingPlatform.MovementInterpolationMode>((Objects.MovingPlatform.MovementInterpolationMode value) => { });
|
||||
var movingPlatformRotateInterpolationModeGenericDelegate = new Preset.GenericDelegate<Objects.MovingPlatform.RotateInterpolationMode>();
|
||||
var movingPlatformRotateInterpolationModeFuncDelegate = new Func<Objects.MovingPlatform.RotateInterpolationMode>(() => { return 0; });
|
||||
var movingPlatformRotateInterpolationModeActionDelegate = new Action<Objects.MovingPlatform.RotateInterpolationMode>((Objects.MovingPlatform.RotateInterpolationMode value) => { });
|
||||
var audioClipSetGenericDelegate = new Preset.GenericDelegate<Audio.AudioClipSet>();
|
||||
var audioClipSetFuncDelegate = new Func<Audio.AudioClipSet>(() => { return null; });
|
||||
var audioClipSetActionDelegate = new Action<Audio.AudioClipSet>((Audio.AudioClipSet value) => { });
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_SHOOTER
|
||||
var autoReloadTypeGenericDelegate = new Preset.GenericDelegate<Character.Abilities.Items.Reload.AutoReloadType>();
|
||||
var autoReloadTypeFuncDelegate = new Func<Character.Abilities.Items.Reload.AutoReloadType>(() => { return 0; });
|
||||
var autoReloadTypeModeActionDelegate = new Action<Character.Abilities.Items.Reload.AutoReloadType>((Character.Abilities.Items.Reload.AutoReloadType value) => { });
|
||||
var shootableWeaponFireModeGenericDelegate = new Preset.GenericDelegate<Items.Actions.ShootableWeapon.FireMode>();
|
||||
var shootableWeaponFireModeFuncDelegate = new Func<Items.Actions.ShootableWeapon.FireMode>(() => { return 0; });
|
||||
var shootableWeaponFireModeActionDelegate = new Action<Items.Actions.ShootableWeapon.FireMode>((Items.Actions.ShootableWeapon.FireMode value) => { });
|
||||
var shootableWeaponFireTypeGenericDelegate = new Preset.GenericDelegate<Items.Actions.ShootableWeapon.FireType>();
|
||||
var shootableWeaponFireTypeFuncDelegate = new Func<Items.Actions.ShootableWeapon.FireType>(() => { return 0; });
|
||||
var shootableWeaponFireTypeActionDelegate = new Action<Items.Actions.ShootableWeapon.FireType>((Items.Actions.ShootableWeapon.FireType value) => { });
|
||||
var shootableWeaponProjectileVisibilityGenericDelegate = new Preset.GenericDelegate<Items.Actions.ShootableWeapon.ProjectileVisiblityType>();
|
||||
var shootableWeaponProjectileVisiblityTypeFuncDelegate = new Func<Items.Actions.ShootableWeapon.ProjectileVisiblityType>(() => { return 0; });
|
||||
var shootableWeaponProjectileVisiblityTypeActionDelegate = new Action<Items.Actions.ShootableWeapon.ProjectileVisiblityType>((Items.Actions.ShootableWeapon.ProjectileVisiblityType value) => { });
|
||||
var shootableWeaponReloadClipTypeGenericDelegate = new Preset.GenericDelegate<Items.Actions.ShootableWeapon.ReloadClipType>();
|
||||
var shootableWeaponReloadClipTypeFuncDelegate = new Func<Items.Actions.ShootableWeapon.ReloadClipType>(() => { return 0; });
|
||||
var shootableWeaponReloadClipTypeActionDelegate = new Action<Items.Actions.ShootableWeapon.ReloadClipType>((Items.Actions.ShootableWeapon.ReloadClipType value) => { });
|
||||
#endif
|
||||
#if ULTIMATE_CHARACTER_CONTROLLER_MELEE
|
||||
var meleeWeaponTrailVisibilityGenericDelegate = new Preset.GenericDelegate<Items.Actions.MeleeWeapon.TrailVisibilityType>();
|
||||
var meleeWeaponTrailVisibilityFuncDelegate = new Func<Items.Actions.MeleeWeapon.TrailVisibilityType>(() => { return 0; });
|
||||
var meleeWeaponTrailVisibilityActionDelegate = new Action<Items.Actions.MeleeWeapon.TrailVisibilityType>((Items.Actions.MeleeWeapon.TrailVisibilityType value) => { });
|
||||
#endif
|
||||
var magicItemCastDirectionGenericDelegate = new Preset.GenericDelegate<Items.Actions.MagicItem.CastDirection>();
|
||||
var magicItemCastDirectionFuncDelegate = new Func<Items.Actions.MagicItem.CastDirection>(() => { return 0; });
|
||||
var magicItemCastDirectionActionDelegate = new Action<Items.Actions.MagicItem.CastDirection>((Items.Actions.MagicItem.CastDirection value) => { });
|
||||
var magicItemCastUseTypeGenericDelegate = new Preset.GenericDelegate<Items.Actions.MagicItem.CastUseType>();
|
||||
var magicItemCastUseTypeFuncDelegate = new Func<Items.Actions.MagicItem.CastUseType>(() => { return 0; });
|
||||
var magicItemCastUseTypeActionDelegate = new Action<Items.Actions.MagicItem.CastUseType>((Items.Actions.MagicItem.CastUseType value) => { });
|
||||
var magicItemCastInterruptSourceGenericDelegate = new Preset.GenericDelegate<Items.Actions.MagicItem.CastInterruptSource>();
|
||||
var magicItemCastInterruptSourceFuncDelegate = new Func<Items.Actions.MagicItem.CastInterruptSource>(() => { return 0; });
|
||||
var magicItemCastInterruptSourceActionDelegate = new Action<Items.Actions.MagicItem.CastInterruptSource>((Items.Actions.MagicItem.CastInterruptSource value) => { });
|
||||
var healthFlashMonitorFlashGenericDelegate = new Preset.GenericDelegate<UI.HealthFlashMonitor.Flash>();
|
||||
var healthFlashMonitorFlashFuncDelegate = new Func<UI.HealthFlashMonitor.Flash>(() => { return new UI.HealthFlashMonitor.Flash(); });
|
||||
var healthFlashMonitorFlashActionDelegate = new Action<UI.HealthFlashMonitor.Flash>((UI.HealthFlashMonitor.Flash value) => { });
|
||||
#pragma warning restore 0219
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 076144a8918352549981a20b956086ee
|
||||
timeCreated: 1486426095
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,59 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
/// <summary>
|
||||
/// Used by the state system for the default preset. The default preset will only set the property value when there has been a change from another preset.
|
||||
/// </summary>
|
||||
public class DefaultPreset : Preset
|
||||
{
|
||||
private Dictionary<MethodInfo, int> m_DelegateIndexMap;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a default preset.
|
||||
/// </summary>
|
||||
/// <returns>The created preset.</returns>
|
||||
public static DefaultPreset CreateDefaultPreset()
|
||||
{
|
||||
var preset = CreateInstance<DefaultPreset>();
|
||||
preset.hideFlags = UnityEngine.HideFlags.HideAndDontSave;
|
||||
return preset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the preset with the specified visiblity. The preset must be initialized before the preset values are applied so the delegates can be created.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to map the delegates to.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public override void Initialize(object obj, MemberVisibility visibility)
|
||||
{
|
||||
base.Initialize(obj, visibility);
|
||||
|
||||
m_DelegateIndexMap = new Dictionary<MethodInfo, int>();
|
||||
for (int i = 0; i < m_Delegates.Length; ++i) {
|
||||
m_DelegateIndexMap.Add(m_Delegates[i].SetMethod, i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the values to the component specified by the delegates.
|
||||
/// </summary>
|
||||
/// <param name="delegates">The properties that were changed.</param>
|
||||
public override void ApplyValues(BaseDelegate[] delegates)
|
||||
{
|
||||
// Only apply the properties that were changed. This is determined by the delegates array.
|
||||
for (int i = 0; i < delegates.Length; ++i) {
|
||||
var index = m_DelegateIndexMap[delegates[i].SetMethod];
|
||||
m_Delegates[index].ApplyValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf4578a7142c06d46b296d998c7c0b45
|
||||
timeCreated: 1481960214
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: e2150fcaaf9a0a34baf8e5554d64da37, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for any object which uses the StateSystem. Allows the StateManager to interact with a common object.
|
||||
/// </summary>
|
||||
public interface IStateOwner
|
||||
{
|
||||
/// <summary>
|
||||
/// Callback when the StateManager will change the active state on the current object.
|
||||
/// </summary>
|
||||
void StateWillChange();
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the StateManager has changed the active state on the current object.
|
||||
/// </summary>
|
||||
void StateChange();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 24863ed59b5907a4f9eb7f3c9850b9db
|
||||
timeCreated: 1497724626
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Allows the Preset component to serialized the property value.
|
||||
/// </summary>
|
||||
public class PersistablePreset : Preset
|
||||
{
|
||||
[Tooltip("The serialized properties.")]
|
||||
[SerializeField] protected Serialization m_Data;
|
||||
|
||||
public Serialization Data { get { return m_Data; } set { m_Data = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a persistable preset based off of the specified component.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to retrieve the property values of.</param>
|
||||
/// <returns>The created preset. Null if no properties have been found to create the preset with.</returns>
|
||||
public static PersistablePreset CreatePreset(object obj)
|
||||
{
|
||||
return CreatePreset(obj, MemberVisibility.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a persistable preset based off of the specified component and visibility.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to retrieve the property values of.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
/// <returns>The created preset. Null if no properties have been found to create the preset with.</returns>
|
||||
public static PersistablePreset CreatePreset(object obj, MemberVisibility visibility)
|
||||
{
|
||||
var data = new Serialization();
|
||||
data.Serialize(obj, false, visibility);
|
||||
var preset = CreateInstance<PersistablePreset>();
|
||||
preset.Data = data;
|
||||
return preset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the preset with the specified visiblity. The preset must be initialized before the preset values are applied so the delegates can be created.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to map the delegates to.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public override void Initialize(object obj, MemberVisibility visibility)
|
||||
{
|
||||
m_Delegates = new BaseDelegate[m_Data.ValueHashes.Length];
|
||||
var valuePositionMap = new Dictionary<int, int>(m_Data.ValueHashes.Length);
|
||||
for (int i = 0; i < m_Data.ValueHashes.Length; ++i) {
|
||||
valuePositionMap.Add(m_Data.ValueHashes[i], i);
|
||||
}
|
||||
|
||||
var valueCount = 0;
|
||||
var properties = Serialization.GetSerializedProperties(obj.GetType(), visibility);
|
||||
for (int i = 0; i < properties.Length; ++i) {
|
||||
var hash = Serialization.StringHash(properties[i].PropertyType.FullName) + Serialization.StringHash(properties[i].Name);
|
||||
int position;
|
||||
if (!valuePositionMap.TryGetValue(hash, out position)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a generic delegate based on the property type.
|
||||
var genericDelegateType = typeof(GenericDelegate<>).MakeGenericType(properties[i].PropertyType);
|
||||
m_Delegates[valueCount] = Activator.CreateInstance(genericDelegateType) as BaseDelegate;
|
||||
|
||||
// Initialize the delegate.
|
||||
if (m_Delegates[valueCount] != null) {
|
||||
m_Delegates[valueCount].Initialize(obj, properties[i], valuePositionMap, m_Data, visibility);
|
||||
} else {
|
||||
Debug.LogWarning("Warning: Unable to create preset of type " + properties[i].PropertyType);
|
||||
}
|
||||
valueCount++;
|
||||
}
|
||||
|
||||
// The delegate length may not match if a property has been added but no longer exists.
|
||||
if (m_Delegates.Length != valueCount) {
|
||||
Array.Resize(ref m_Delegates, valueCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 114f4adff47823d4aadb77159ef6731f
|
||||
timeCreated: 1481960214
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: e2150fcaaf9a0a34baf8e5554d64da37, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,313 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a set of values for any number of component properties. In order for the value to be applied to a property a getter and setter must exist,
|
||||
/// along with a derived class from BaseDelegate which creates the delegate which interfaces with the property getter and setter. Properties can be
|
||||
/// ignored with the [Opsive.UltimateCharacterController.Opsive.Shared.Utility.NonSerialized] attribute.
|
||||
/// </summary>
|
||||
public class Preset : ScriptableObject
|
||||
{
|
||||
protected BaseDelegate[] m_Delegates;
|
||||
|
||||
public bool IsInitialized { get { return m_Delegates != null; } }
|
||||
public BaseDelegate[] Delegates { get { return m_Delegates; } }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a preset based off of the specified component.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to retrieve the property values of.</param>
|
||||
/// <returns>The created preset. Null if no properties have been found to create the preset with.</returns>
|
||||
public static Preset CreatePreset()
|
||||
{
|
||||
var preset = CreateInstance<Preset>();
|
||||
preset.hideFlags = HideFlags.HideAndDontSave;
|
||||
return preset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the preset. The preset must be initialized before the preset values are applied so the delegates can be created.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to map the delegates to.</param>
|
||||
public void Initialize(object obj)
|
||||
{
|
||||
Initialize(obj, MemberVisibility.Public);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the preset with the specified visiblity. The preset must be initialized before the preset values are applied so the delegates can be created.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to map the delegates to.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public virtual void Initialize(object obj, MemberVisibility visibility)
|
||||
{
|
||||
var properties = Serialization.GetSerializedProperties(obj.GetType(), visibility);
|
||||
var valueCount = 0;
|
||||
m_Delegates = new BaseDelegate[properties.Length];
|
||||
for (int i = 0; i < properties.Length; ++i) {
|
||||
// The property may not be valid.
|
||||
if (Serialization.GetValidGetMethod(properties[i], visibility) == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a generic delegate based on the property type.
|
||||
var genericDelegateType = typeof(GenericDelegate<>).MakeGenericType(properties[i].PropertyType);
|
||||
m_Delegates[valueCount] = Activator.CreateInstance(genericDelegateType) as BaseDelegate;
|
||||
|
||||
// Initialize the delegate.
|
||||
if (m_Delegates[valueCount] != null) {
|
||||
m_Delegates[valueCount].Initialize(obj, properties[i], visibility);
|
||||
} else {
|
||||
Debug.LogWarning("Warning: Unable to create preset of type " + properties[i].PropertyType);
|
||||
}
|
||||
valueCount++;
|
||||
}
|
||||
if (m_Delegates.Length != valueCount) {
|
||||
Array.Resize(ref m_Delegates, valueCount);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the stored value with the current property value.
|
||||
/// </summary>
|
||||
public virtual void UpdateValue()
|
||||
{
|
||||
for (int i = 0; i < m_Delegates.Length; ++i) {
|
||||
m_Delegates[i].UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the values to the component.
|
||||
/// </summary>
|
||||
public void ApplyValues()
|
||||
{
|
||||
for (int i = 0; i < m_Delegates.Length; ++i) {
|
||||
m_Delegates[i].ApplyValue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the values to the component specified by the delegates.
|
||||
/// </summary>
|
||||
/// <param name="delegates">The properties that were changed.</param>
|
||||
public virtual void ApplyValues(BaseDelegate[] delegates) { }
|
||||
|
||||
/// <summary>
|
||||
/// Abstract class which allows for a delegate to be created which can be called on when the preset value should be applied.
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public abstract class BaseDelegate
|
||||
{
|
||||
public abstract MethodInfo SetMethod { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the delegate and value.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object which the delegate operates on.</param>
|
||||
/// <param name="property">The property that the delegate will invoke.</param>
|
||||
/// <param name="valuePositionMap">A mapping between the value hash and position.</param>
|
||||
/// <param name="data">The serialization data which contains the values for the property (as well as all other properties).</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public abstract void Initialize(object obj, PropertyInfo property, Dictionary<int, int> valuePositionMap, Serialization data, MemberVisibility visibility);
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the delegate.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object which the delegate operates on.</param>
|
||||
/// <param name="property">The property that the delegate will invoke.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public abstract void Initialize(object obj, PropertyInfo property, MemberVisibility visibility);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the stored value with the current property value.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object which the delegate operates on.</param>
|
||||
/// <param name="property">The property that the delegate will invoke.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public abstract void UpdateValue();
|
||||
|
||||
/// <summary>
|
||||
/// Applies the preset value to the delegate.
|
||||
/// </summary>
|
||||
public abstract void ApplyValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generic class which implements a type specific delegate and value that can be called on when the preset value should be applied.
|
||||
/// See AOTLinker for an explanation of why a different class name is used for AOT platforms.
|
||||
/// </summary>
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
public class GenericDelegate<T> : BaseDelegate
|
||||
{
|
||||
private T m_Value;
|
||||
private MethodInfo m_SetMethod;
|
||||
private Action<T> m_Setter;
|
||||
private Func<T> m_Getter;
|
||||
private bool m_IsIList;
|
||||
|
||||
public override MethodInfo SetMethod { get { return m_SetMethod; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the delegate and value.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object which the delegate operates on.</param>
|
||||
/// <param name="property">The property that the delegate will invoke.</param>
|
||||
/// <param name="valuePositionMap">A mapping between the value hash and position.</param>
|
||||
/// <param name="data">The serialization data which contains the values for the property (as well as all other properties).</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public override void Initialize(object obj, PropertyInfo property, Dictionary<int, int> valuePositionMap, Serialization data, MemberVisibility visibility)
|
||||
{
|
||||
m_SetMethod = property.GetSetMethod(visibility != MemberVisibility.Public);
|
||||
if (m_SetMethod != null) {
|
||||
m_Setter = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), obj, m_SetMethod);
|
||||
var bitwiseHash = new Version(data.Version).CompareTo(new Version("3.1")) >= 0;
|
||||
var value = Serializer.BytesToValue(typeof(T), property.Name, valuePositionMap, 0, data.Values, data.ValuePositions, data.UnityObjects, false, visibility, bitwiseHash);
|
||||
if (value != null && !value.Equals(null)) {
|
||||
m_Value = (T)value;
|
||||
}
|
||||
var type = typeof(T);
|
||||
m_IsIList = typeof(IList).IsAssignableFrom(type);
|
||||
if (m_IsIList) {
|
||||
// The Get method only needs to be assigned if the type is an IList because the actual object isn't copied by reference for arrays.
|
||||
// Each individual element within the array needs to be interated on.
|
||||
var getMethod = property.GetGetMethod(visibility != MemberVisibility.Public);
|
||||
if (getMethod != null) {
|
||||
m_Getter = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), obj, getMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the delegate.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object which the delegate operates on.</param>
|
||||
/// <param name="property">The property that the delegate will invoke.</param>
|
||||
/// <param name="visibility">Specifies the visibility of the field/properties that should be retrieved.</param>
|
||||
public override void Initialize(object obj, PropertyInfo property, MemberVisibility visibility)
|
||||
{
|
||||
m_SetMethod = property.GetSetMethod(visibility != MemberVisibility.Public);
|
||||
if (m_SetMethod != null) {
|
||||
m_Setter = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), obj, m_SetMethod);
|
||||
}
|
||||
|
||||
var getMethod = property.GetGetMethod(visibility != MemberVisibility.Public);
|
||||
if (getMethod != null) {
|
||||
m_Getter = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), obj, getMethod);
|
||||
|
||||
// Create an instance of the value if it is an array or a list. This will allow a snapshot of the array/list elements to be saved without having the
|
||||
// array/list change because it is later modified by reference.
|
||||
var type = typeof(T);
|
||||
m_IsIList = typeof(IList).IsAssignableFrom(type);
|
||||
if (m_IsIList) {
|
||||
if (typeof(T).IsArray) {
|
||||
var value = m_Getter() as Array;
|
||||
m_Value = (T)(object)Array.CreateInstance(type.GetElementType(), value == null ? 0 : value.Length);
|
||||
} else {
|
||||
var baseType = type;
|
||||
while (!baseType.IsGenericType) {
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
var elementType = baseType.GetGenericArguments()[0];
|
||||
if (type.IsGenericType) {
|
||||
m_Value = (T)Activator.CreateInstance(typeof(List<>).MakeGenericType(elementType));
|
||||
} else {
|
||||
m_Value = (T)Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The value should be set at the same time the delegate is initailized.
|
||||
UpdateValue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the stored value with the current property value.
|
||||
/// </summary>
|
||||
public override void UpdateValue()
|
||||
{
|
||||
if (m_Getter == null) {
|
||||
Debug.LogError("Error: Unable to retrieve an updated value - the Get method is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the individual elements if the value is a list or an array. This will prevent the array/list from being changed because it is
|
||||
// later modified by reference.
|
||||
if (m_IsIList) {
|
||||
UpdateIList(m_Getter(), m_Value);
|
||||
} else { // Not an array/list.
|
||||
m_Value = m_Getter();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the preset value to the delegate.
|
||||
/// </summary>
|
||||
public override void ApplyValue()
|
||||
{
|
||||
if (m_IsIList) {
|
||||
UpdateIList(m_Value, m_Getter());
|
||||
} else {
|
||||
m_Setter(m_Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the source array/list elements to the destination elements.
|
||||
/// </summary>
|
||||
/// <param name="source">The array/list to copy the references from.</param>
|
||||
/// <param name="destination">The array/list to copy the references to.</param>
|
||||
private void UpdateIList(T source, T destination)
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (type.IsArray) {
|
||||
var sourceArray = source as Array;
|
||||
var destinationArray = destination as Array;
|
||||
if (sourceArray != null && destinationArray != null) {
|
||||
// The array sizes need to match.
|
||||
if (destinationArray != null && sourceArray.Length != destinationArray.Length) {
|
||||
destinationArray = Array.CreateInstance(typeof(T).GetElementType(), sourceArray.Length);
|
||||
// There's no way to avoid the boxing/unboxing. It is recommended that arrays are not changed to avoid this.
|
||||
m_Setter((T)(object)destinationArray);
|
||||
}
|
||||
for (int i = 0; i < sourceArray.Length; ++i) {
|
||||
destinationArray.SetValue(sourceArray.GetValue(i), i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var sourceList = source as IList<T>;
|
||||
var destinationList = destination as IList<T>;
|
||||
// Remove any extra elements.
|
||||
if (destinationList.Count > sourceList.Count) {
|
||||
var removeCount = destinationList.Count - sourceList.Count;
|
||||
for (int i = 0; i < removeCount; ++i) {
|
||||
destinationList.RemoveAt(destinationList.Count - 1);
|
||||
}
|
||||
}
|
||||
// Update the element referance.
|
||||
for (int i = 0; i < sourceList.Count; ++i) {
|
||||
if (i < destinationList.Count) {
|
||||
destinationList[i] = sourceList[i];
|
||||
} else {
|
||||
destinationList.Add(sourceList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9bd6539f57969b4284097c894d4f578
|
||||
timeCreated: 1481960214
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: e2150fcaaf9a0a34baf8e5554d64da37, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,165 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// A State contains a preset which can change property values at runtime. The state has a name associated with it which allows for easy reference to it.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class State
|
||||
{
|
||||
[Tooltip("The name of the state.")]
|
||||
[SerializeField] protected string m_Name;
|
||||
[Tooltip("The preset used by the state.")]
|
||||
[SerializeField] protected Preset m_Preset;
|
||||
[Tooltip("A list of other states that the current state can prevent from being enabled if the current state is enabled.")]
|
||||
[SerializeField] protected string[] m_BlockList;
|
||||
[Tooltip("Is the state the default state?")]
|
||||
[SerializeField] protected bool m_Default;
|
||||
[Tooltip("Is the state active?")]
|
||||
[System.NonSerialized] [SerializeField] protected bool m_Active;
|
||||
|
||||
private IStateOwner m_Owner;
|
||||
public IStateOwner Owner { get { return m_Owner; } }
|
||||
|
||||
public string Name { get { return m_Name; }
|
||||
#if UNITY_EDITOR
|
||||
set { m_Name = value; }
|
||||
#endif
|
||||
}
|
||||
public Preset Preset { get { return m_Preset; } set { m_Preset = value; } }
|
||||
#if UNITY_EDITOR
|
||||
public string[] BlockList { get { return m_BlockList; } set { m_BlockList = value; } }
|
||||
#endif
|
||||
public bool Default { get { return m_Default; }
|
||||
#if UNITY_EDITOR
|
||||
set { m_Default = value; }
|
||||
#endif
|
||||
}
|
||||
public bool Active { get { return m_Active; } set { m_Active = value; } }
|
||||
|
||||
[System.NonSerialized] private State[] m_BlockStates;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor for State.
|
||||
/// </summary>
|
||||
public State() { }
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for State. Used by the component inspector.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the state.</param>
|
||||
/// <param name="defaultState">Is the state the default state?</param>
|
||||
public State(string name, bool defaultState)
|
||||
{
|
||||
m_Name = name;
|
||||
m_Default = defaultState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for State. Used by the State Configuration.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the state.</param>
|
||||
/// <param name="preset">The preset that the state uses.</param>
|
||||
/// <param name="blockList">The list of blocked states.</param>
|
||||
public State(string name, Preset preset, string[] blockList)
|
||||
{
|
||||
m_Name = name;
|
||||
m_Preset = preset;
|
||||
m_BlockList = blockList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the state - binds the object and applies any blocking rules.
|
||||
/// </summary>
|
||||
/// <param name="owner">The object which is bound to the state.</param>
|
||||
/// <param name="nameStateMap">A mapping between the state name and the state object.</param>
|
||||
public void Initialize(IStateOwner owner, Dictionary<string, State> nameStateMap)
|
||||
{
|
||||
// The preset can be null if the Component has no valid properties that can be changed.
|
||||
if (m_Preset != null) {
|
||||
// The preset may be used by another object of the same type.
|
||||
// Initialize a new preset to prevent the delegates from conflicting with each other.
|
||||
if (m_Preset.IsInitialized) {
|
||||
m_Preset = Object.Instantiate(m_Preset);
|
||||
}
|
||||
m_Preset.Initialize(owner, MemberVisibility.Public);
|
||||
}
|
||||
m_Owner = owner;
|
||||
UpdateBlockList(nameStateMap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the block list to point to the state object.
|
||||
/// </summary>
|
||||
/// <param name="nameStateMap">A mapping between the state name and the state object.</param>
|
||||
private void UpdateBlockList(Dictionary<string, State> nameStateMap)
|
||||
{
|
||||
if (m_BlockList != null && m_BlockList.Length > 0) {
|
||||
m_BlockStates = new State[m_BlockList.Length];
|
||||
State state;
|
||||
var count = 0;
|
||||
for (int i = 0; i < m_BlockList.Length; ++i) {
|
||||
if (m_BlockList[i] == null) {
|
||||
continue;
|
||||
}
|
||||
if (nameStateMap.TryGetValue(m_BlockList[count], out state)) {
|
||||
m_BlockStates[count] = state;
|
||||
} else {
|
||||
Debug.LogWarning("Error: Unable to find block state with name \"" + m_BlockList[count] + "\" within state " + m_Name + " on object " + m_Owner);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (m_BlockList.Length != count) {
|
||||
System.Array.Resize(ref m_BlockList, count);
|
||||
System.Array.Resize(ref m_BlockStates, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the state blocked by another enabed state?
|
||||
/// </summary>
|
||||
/// <returns>True if the state is blocked.</returns>
|
||||
public bool IsBlocked()
|
||||
{
|
||||
if (m_BlockStates != null) {
|
||||
for (int i = 0; i < m_BlockStates.Length; ++i) {
|
||||
if (m_BlockStates[i] != null && m_BlockStates[i].Active && !m_BlockStates[i].IsBlocked()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the values to the component specified within the preset object.
|
||||
/// </summary>
|
||||
public void ApplyValues()
|
||||
{
|
||||
if (m_Preset != null) {
|
||||
m_Preset.ApplyValues();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the values to the component specified within the preset object.
|
||||
/// </summary>
|
||||
public void ApplyValues(Preset.BaseDelegate[] delegates)
|
||||
{
|
||||
if (m_Preset != null) {
|
||||
m_Preset.ApplyValues(delegates);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8d40df4ef0129e44b885f12b0609b95
|
||||
timeCreated: 1482788438
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Acts as the parent component which can use the state system to change property values.
|
||||
/// </summary>
|
||||
public class StateBehavior : MonoBehaviour, IStateOwner
|
||||
{
|
||||
[Tooltip("A list of all states that the component can change to.")]
|
||||
[HideInInspector] [SerializeField] protected State[] m_States = new State[] { new State("Default", true) };
|
||||
|
||||
[Opsive.Shared.Utility.NonSerialized] public State[] States { get { return m_States; } set { m_States = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (Application.isPlaying) {
|
||||
StateManager.Initialize(gameObject, this, m_States);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates the specified state.
|
||||
/// </summary>
|
||||
/// <param name="stateName">The name of the state to change the activate status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
public void SetState(string stateName, bool active)
|
||||
{
|
||||
StateManager.SetState(this, m_States, stateName, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the StateManager will change the active state on the current object.
|
||||
/// </summary>
|
||||
public virtual void StateWillChange() { }
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the StateManager has changed the active state on the current object.
|
||||
/// </summary>
|
||||
public virtual void StateChange() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1e534f058bdcbf4cb5c680370f77a86
|
||||
timeCreated: 1482746434
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,357 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// The StateConfiguration class contains an array of profiles with prespecified states that can be added to an object.
|
||||
/// </summary>
|
||||
public class StateConfiguration : ScriptableObject
|
||||
{
|
||||
[Tooltip("An array of profiles which map a name to a list of states.")]
|
||||
[SerializeField] protected Profile[] m_Profiles;
|
||||
|
||||
public Profile[] Profiles { get { return m_Profiles; } set { m_Profiles = value; ResetInitialization(); } }
|
||||
|
||||
private Dictionary<string, Dictionary<Type, Profile.StateElement[]>> m_ProfileStateMap;
|
||||
|
||||
/// <summary>
|
||||
/// The Profile class contains an array of states that should be added.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class Profile
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies the type of object that represents the profile.
|
||||
/// </summary>
|
||||
public enum ProfileType { Character, Item, Camera }
|
||||
|
||||
/// <summary>
|
||||
/// A representation of the StateSystem.State object, used to restore states on an object.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StateElement
|
||||
{
|
||||
[Tooltip("The name of the state.")]
|
||||
[SerializeField] protected string m_Name;
|
||||
[Tooltip("The preset which the state belongs to.")]
|
||||
[SerializeField] protected PersistablePreset m_Preset;
|
||||
[Tooltip("Any other states that the current state can block.")]
|
||||
[SerializeField] protected string[] m_BlockList;
|
||||
[Tooltip("Is the state the default state? Only one state can be the default for each object type.")]
|
||||
[SerializeField] protected bool m_Default;
|
||||
|
||||
public string Name { get { return m_Name; } set { m_Name = value; } }
|
||||
public PersistablePreset Preset { get { return m_Preset; } set { m_Preset = value; } }
|
||||
public string[] BlockList { get { return m_BlockList; } set { m_BlockList = value; } }
|
||||
public bool Default { get { return m_Default; } set { m_Default = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
public StateElement() { }
|
||||
|
||||
/// <summary>
|
||||
/// Three parameter constructor.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the state.</param>
|
||||
/// <param name="preset">The preset used by the state.</param>
|
||||
/// <param name="blockList">The list of states that the current state should block.</param>
|
||||
/// <param name="defaultState">Is the state a default state?</param>
|
||||
public StateElement(string name, PersistablePreset preset, string[] blockList, bool defaultState)
|
||||
{
|
||||
m_Name = name;
|
||||
m_Preset = preset;
|
||||
m_BlockList = blockList;
|
||||
m_Default = defaultState;
|
||||
}
|
||||
}
|
||||
|
||||
[Tooltip("The name of the profile.")]
|
||||
[SerializeField] protected string m_Name;
|
||||
[Tooltip("The type of object the profile represents.")]
|
||||
[SerializeField] protected ProfileType m_Type;
|
||||
[Tooltip("The states which belong to the profile.")]
|
||||
[SerializeField] protected StateElement[] m_StateElements;
|
||||
|
||||
public string Name { get { return m_Name; } set { m_Name = value; } }
|
||||
public ProfileType Type { get { return m_Type; } set { m_Type = value; } }
|
||||
public StateElement[] StateElements { get { return m_StateElements; } set { m_StateElements = value; } }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mapping for all of the profiles.
|
||||
/// </summary>
|
||||
private void Initialize()
|
||||
{
|
||||
// The mapping may have already been initialized.
|
||||
if (m_ProfileStateMap != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_ProfileStateMap = new Dictionary<string, Dictionary<Type, Profile.StateElement[]>>();
|
||||
if (m_Profiles == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < m_Profiles.Length; ++i) {
|
||||
var profileStateElements = m_Profiles[i].StateElements;
|
||||
var typeStateMap = new Dictionary<Type, Profile.StateElement[]>();
|
||||
m_ProfileStateMap.Add(m_Profiles[i].Name, typeStateMap);
|
||||
for (int j = 0; j < profileStateElements.Length; ++j) {
|
||||
// The state must be valid.
|
||||
if (string.IsNullOrEmpty(profileStateElements[j].Name) || profileStateElements[j].Preset == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var objType = Utility.UnityEngineUtility.GetType(profileStateElements[j].Preset.Data.ObjectType);
|
||||
if (objType == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Profile.StateElement[] stateElements;
|
||||
if (!typeStateMap.TryGetValue(objType, out stateElements)) {
|
||||
stateElements = new Profile.StateElement[0];
|
||||
typeStateMap.Add(objType, stateElements);
|
||||
}
|
||||
|
||||
// Add the state to the array that is specific for the object type.
|
||||
Array.Resize(ref stateElements, stateElements.Length + 1);
|
||||
stateElements[stateElements.Length - 1] = profileStateElements[j];
|
||||
// Allocating a new array requires the dictionary element to be updated.
|
||||
typeStateMap[objType] = stateElements;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// After a change the state map must be cleared so it can be initialized again.
|
||||
/// </summary>
|
||||
public void ResetInitialization()
|
||||
{
|
||||
m_ProfileStateMap = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of profiles that have been added to the specified GameObject.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to retrieve the profiles for.</param>
|
||||
/// <param name="type">The type of profiles that should be shown.</param>
|
||||
/// <returns>A list of profiles that have been added to the specified GameObject.</returns>
|
||||
public List<string> GetProfilesForGameObject(GameObject gameObject, Profile.ProfileType type)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
var profileNames = new List<string>();
|
||||
if (gameObject == null) {
|
||||
// All of the profiles for the specfied type should be shown if the GameObject is null.
|
||||
if (m_Profiles != null) {
|
||||
for (int i = 0; i < m_Profiles.Length; ++i) {
|
||||
if (type != m_Profiles[i].Type) {
|
||||
continue;
|
||||
}
|
||||
profileNames.Add(m_Profiles[i].Name);
|
||||
}
|
||||
}
|
||||
return profileNames;
|
||||
}
|
||||
var stateBehaviors = gameObject.GetComponents<StateBehavior>();
|
||||
for (int i = 0; i < stateBehaviors.Length; ++i) {
|
||||
GetProfilesForType(stateBehaviors[i].GetType(), type, profileNames);
|
||||
|
||||
// The GameObject may contain the UltimateCharacterLocomotion component where the
|
||||
// movement types, abilities, item abilities, and effects also need to be searched.
|
||||
if (stateBehaviors[i] is Character.UltimateCharacterLocomotion) {
|
||||
var characterLocomotion = stateBehaviors[i] as Character.UltimateCharacterLocomotion;
|
||||
|
||||
characterLocomotion.DeserializeMovementTypes();
|
||||
for (int j = 0; j < characterLocomotion.MovementTypes.Length; ++j) {
|
||||
GetProfilesForType(characterLocomotion.MovementTypes[j].GetType(), type, profileNames);
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeAbilities();
|
||||
if (characterLocomotion.Abilities != null) {
|
||||
for (int j = 0; j < characterLocomotion.Abilities.Length; ++j) {
|
||||
GetProfilesForType(characterLocomotion.Abilities[j].GetType(), type, profileNames);
|
||||
}
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeItemAbilities();
|
||||
if (characterLocomotion.ItemAbilities != null) {
|
||||
for (int j = 0; j < characterLocomotion.ItemAbilities.Length; ++j) {
|
||||
GetProfilesForType(characterLocomotion.ItemAbilities[j].GetType(), type, profileNames);
|
||||
}
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeEffects();
|
||||
if (characterLocomotion.Effects != null) {
|
||||
for (int j = 0; j < characterLocomotion.Effects.Length; ++j) {
|
||||
GetProfilesForType(characterLocomotion.Effects[j].GetType(), type, profileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The GameObject may contain the CameraController component where the view types also need to be searched.
|
||||
if (stateBehaviors[i] is UltimateCharacterController.Camera.CameraController) {
|
||||
var cameraController = stateBehaviors[i] as UltimateCharacterController.Camera.CameraController;
|
||||
|
||||
cameraController.DeserializeViewTypes();
|
||||
for (int j = 0; j < cameraController.ViewTypes.Length; ++j) {
|
||||
GetProfilesForType(cameraController.ViewTypes[j].GetType(), type, profileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return profileNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds to a list of profiles that contain the specified type.
|
||||
/// </summary>
|
||||
/// <param name="objType">The type of object to retrieve the profiles for.</param>
|
||||
/// <param name="profileNames">A list of profiles that contain the specifeid type.</param>
|
||||
private void GetProfilesForType(Type objType, Profile.ProfileType profileType, List<string> profileNames)
|
||||
{
|
||||
for (int i = 0; i < m_Profiles.Length; ++i) {
|
||||
if (m_Profiles[i].Type != profileType) {
|
||||
continue;
|
||||
}
|
||||
Dictionary<Type, Profile.StateElement[]> typeStateMap;
|
||||
if (!m_ProfileStateMap.TryGetValue(m_Profiles[i].Name, out typeStateMap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the profile name if the type exists.
|
||||
if (typeStateMap.ContainsKey(objType) && !profileNames.Contains(m_Profiles[i].Name)) {
|
||||
profileNames.Add(m_Profiles[i].Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the states to the GameObject that have been added to the specified profile name.
|
||||
/// </summary>
|
||||
/// <param name="profileName">The name of the profile to retrieve the states from.</param>
|
||||
/// <param name="type">The type of profiles that should be shown.</param>
|
||||
/// <param name="gameObject">The GameObject to add the states to.</param>
|
||||
public void AddStatesToGameObject(string profileName, GameObject gameObject)
|
||||
{
|
||||
Initialize();
|
||||
|
||||
var stateBehaviors = gameObject.GetComponents<StateBehavior>();
|
||||
for (int i = 0; i < stateBehaviors.Length; ++i) {
|
||||
AddStatesToObject(profileName, stateBehaviors[i]);
|
||||
|
||||
// The GameObject may contain the UltimateCharacterLocomotion component where the
|
||||
// movement types, abilities, item abilities, and effects also need to be searched.
|
||||
if (stateBehaviors[i] is Character.UltimateCharacterLocomotion) {
|
||||
var characterLocomotion = stateBehaviors[i] as Character.UltimateCharacterLocomotion;
|
||||
|
||||
characterLocomotion.DeserializeMovementTypes();
|
||||
if (characterLocomotion.MovementTypes != null) {
|
||||
for (int j = 0; j < characterLocomotion.MovementTypes.Length; ++j) {
|
||||
AddStatesToObject(profileName, characterLocomotion.MovementTypes[j]);
|
||||
}
|
||||
var movementTypes = new List<Character.MovementTypes.MovementType>(characterLocomotion.MovementTypes);
|
||||
characterLocomotion.MovementTypeData = Shared.Utility.Serialization.Serialize<Character.MovementTypes.MovementType>(movementTypes);
|
||||
characterLocomotion.MovementTypes = movementTypes.ToArray();
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeAbilities();
|
||||
if (characterLocomotion.Abilities != null) {
|
||||
for (int j = 0; j < characterLocomotion.Abilities.Length; ++j) {
|
||||
AddStatesToObject(profileName, characterLocomotion.Abilities[j]);
|
||||
}
|
||||
Utility.Builders.AbilityBuilder.SerializeAbilities(characterLocomotion);
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeItemAbilities();
|
||||
if (characterLocomotion.ItemAbilities != null) {
|
||||
for (int j = 0; j < characterLocomotion.ItemAbilities.Length; ++j) {
|
||||
AddStatesToObject(profileName, characterLocomotion.ItemAbilities[j]);
|
||||
}
|
||||
Utility.Builders.AbilityBuilder.SerializeItemAbilities(characterLocomotion);
|
||||
}
|
||||
|
||||
characterLocomotion.DeserializeEffects();
|
||||
if (characterLocomotion.Effects != null) {
|
||||
for (int j = 0; j < characterLocomotion.Effects.Length; ++j) {
|
||||
AddStatesToObject(profileName, characterLocomotion.Effects[j]);
|
||||
}
|
||||
var effects = new List<Character.Effects.Effect>(characterLocomotion.Effects);
|
||||
characterLocomotion.EffectData = Shared.Utility.Serialization.Serialize<Character.Effects.Effect>(effects);
|
||||
characterLocomotion.Effects = effects.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
// The GameObject may contain the CameraController component where the view types also need to be searched.
|
||||
if (stateBehaviors[i] is UltimateCharacterController.Camera.CameraController) {
|
||||
var cameraController = stateBehaviors[i] as UltimateCharacterController.Camera.CameraController;
|
||||
|
||||
cameraController.DeserializeViewTypes();
|
||||
if (cameraController.ViewTypes != null) {
|
||||
for (int j = 0; j < cameraController.ViewTypes.Length; ++j) {
|
||||
AddStatesToObject(profileName, cameraController.ViewTypes[j]);
|
||||
}
|
||||
Utility.Builders.ViewTypeBuilder.SerializeViewTypes(cameraController);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the states to the object that have been added to the specified profile name.
|
||||
/// </summary>
|
||||
/// <param name="profileName">The name of the profile to retrieve the states from.</param>
|
||||
/// <param name="obj">The object to add the states to.</param>
|
||||
private void AddStatesToObject(string profileName, object obj)
|
||||
{
|
||||
Dictionary<Type, Profile.StateElement[]> typeStateMap;
|
||||
if (!m_ProfileStateMap.TryGetValue(profileName, out typeStateMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Profile.StateElement[] stateElements;
|
||||
if (!typeStateMap.TryGetValue(obj.GetType(), out stateElements)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var defaultIndex = -1;
|
||||
for (int i = 0; i < stateElements.Length; ++i) {
|
||||
if (stateElements[i].Default) {
|
||||
stateElements[i].Preset.Initialize(obj, MemberVisibility.Public);
|
||||
stateElements[i].Preset.ApplyValues();
|
||||
defaultIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The profile may contain states from more than one of the same object type. Only one set of states should be applied.
|
||||
if (defaultIndex != -1 && defaultIndex < stateElements.Length - 1) {
|
||||
Array.Resize(ref stateElements, defaultIndex + 1);
|
||||
}
|
||||
var states = new State[stateElements.Length + (defaultIndex != -1 ? 0 : 1)]; // One element is reserved for the default state.
|
||||
for (int i = 0; i < stateElements.Length; ++i) {
|
||||
if (stateElements[i].Default) {
|
||||
continue;
|
||||
}
|
||||
states[i] = new State(stateElements[i].Name, stateElements[i].Preset, stateElements[i].BlockList);
|
||||
}
|
||||
if (obj is StateBehavior) {
|
||||
var stateBehavior = obj as StateBehavior;
|
||||
states[states.Length - 1] = stateBehavior.States[stateBehavior.States.Length - 1];
|
||||
stateBehavior.States = states;
|
||||
} else { // StateObject.
|
||||
var stateObject = obj as StateObject;
|
||||
states[states.Length - 1] = stateObject.States[stateObject.States.Length - 1];
|
||||
stateObject.States = states;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3179c486391da9443aa57f9ce8c54954
|
||||
timeCreated: 1516916575
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Inspector helper class for the UltimateCharacterControllerInspector to be able to display states within the ReorderableList.
|
||||
/// </summary>
|
||||
public class StateInspectorHelper : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private int[] m_StateIndexData;
|
||||
public int[] StateIndexData { get { return m_StateIndexData; } set { m_StateIndexData = value; } }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfe2c7470df2c0946ac594d45fdee43b
|
||||
timeCreated: 1492140661
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,512 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.Shared.Game;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the activation and deactivation of states.
|
||||
/// </summary>
|
||||
public class StateManager : MonoBehaviour
|
||||
{
|
||||
[Tooltip("Should the OnStateChange event be sent when the state changes active status?")]
|
||||
[SerializeField] protected bool m_SendStateChangeEvent;
|
||||
|
||||
public bool SendStateChangeEvent { get { return m_SendStateChangeEvent; } set { m_SendStateChangeEvent = value; } }
|
||||
|
||||
private static StateManager s_Instance;
|
||||
private static StateManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!s_Initialized) {
|
||||
s_Instance = new GameObject("State Manager").AddComponent<StateManager>();
|
||||
s_Initialized = true;
|
||||
}
|
||||
return s_Instance;
|
||||
}
|
||||
}
|
||||
private static bool s_Initialized;
|
||||
|
||||
private Dictionary<object, Dictionary<string, State>> m_ObjectNameStateMap = new Dictionary<object, Dictionary<string, State>>();
|
||||
private Dictionary<GameObject, Dictionary<string, List<State>>> m_GameObjectNameStateList = new Dictionary<GameObject, Dictionary<string, List<State>>>();
|
||||
private Dictionary<GameObject, List<GameObject>> m_LinkedGameObjectList = new Dictionary<GameObject, List<GameObject>>();
|
||||
private Dictionary<State, State[]> m_StateArrayMap = new Dictionary<State, State[]>();
|
||||
private Dictionary<GameObject, HashSet<string>> m_ActiveCharacterStates = new Dictionary<GameObject, HashSet<string>>();
|
||||
private Dictionary<GameObject, Dictionary<string, ScheduledEventBase>> m_DisableStateTimerMap;
|
||||
|
||||
/// <summary>
|
||||
/// The object has been enabled.
|
||||
/// </summary>
|
||||
private void OnEnable()
|
||||
{
|
||||
// The object may have been enabled outside of the scene unloading.
|
||||
if (s_Instance == null) {
|
||||
s_Instance = this;
|
||||
s_Initialized = true;
|
||||
SceneManager.sceneUnloaded -= SceneUnloaded;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the states belonging to the owner on the GameObject.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to enable or disable all of the states on.</param>
|
||||
/// <param name="owner">The object that state belongs to.</param>
|
||||
/// <param name="states">A list of all of the states which the owner contains.</param>
|
||||
public static void Initialize(GameObject gameObject, IStateOwner owner, State[] states)
|
||||
{
|
||||
Instance.InitializeInternal(gameObject, owner, states);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which initializes the states belonging to the owner on the GameObject.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to enable or disable all of the states on.</param>
|
||||
/// <param name="owner">The object that state belongs to.</param>
|
||||
/// <param name="states">A list of all of the states which the owner contains.</param>
|
||||
private void InitializeInternal(GameObject gameObject, IStateOwner owner, State[] states)
|
||||
{
|
||||
// The last state will always be reserved for the default state.
|
||||
if (states[states.Length - 1] == null) {
|
||||
states[states.Length - 1] = new State("Default", true);
|
||||
}
|
||||
states[states.Length - 1].Preset = DefaultPreset.CreateDefaultPreset();
|
||||
|
||||
Dictionary<string, State> nameStateMap;
|
||||
if (!m_ObjectNameStateMap.TryGetValue(owner, out nameStateMap)) {
|
||||
nameStateMap = new Dictionary<string, State>();
|
||||
m_ObjectNameStateMap.Add(owner, nameStateMap);
|
||||
}
|
||||
|
||||
// Populate the maps for quick lookup based on owner and GameObject.
|
||||
GameObject characterGameObject = null;
|
||||
var characterLocomotion = gameObject.GetCachedParentComponent<Character.UltimateCharacterLocomotion>();
|
||||
if (characterLocomotion != null) {
|
||||
characterGameObject = characterLocomotion.gameObject;
|
||||
} else {
|
||||
var cameraController = gameObject.GetCachedParentComponent<UltimateCharacterController.Camera.CameraController>();
|
||||
if (cameraController != null) {
|
||||
characterGameObject = cameraController.Character;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < states.Length; ++i) {
|
||||
if (states[i].Preset == null) {
|
||||
Debug.LogError(string.Format("Error: The state {0} on {1} does not have a preset. Ensure each non-default state contains a preset.", states[i].Name, owner), owner as Object);
|
||||
}
|
||||
nameStateMap.Add(states[i].Name, states[i]);
|
||||
|
||||
Dictionary<string, List<State>> nameStateList;
|
||||
if (!m_GameObjectNameStateList.TryGetValue(gameObject, out nameStateList)) {
|
||||
nameStateList = new Dictionary<string, List<State>>();
|
||||
m_GameObjectNameStateList.Add(gameObject, nameStateList);
|
||||
}
|
||||
|
||||
// Child GameObjects should listen for states set on the parent. This for example allows an item to react to a state change even if that state change
|
||||
// is set on the character. The character GameObject does not need to be made aware of the Default state.
|
||||
if (i != states.Length - 1) {
|
||||
|
||||
if (characterGameObject != null && gameObject != characterGameObject) {
|
||||
Dictionary<string, List<State>> characterNameStateList;
|
||||
if (!m_GameObjectNameStateList.TryGetValue(characterGameObject, out characterNameStateList)) {
|
||||
characterNameStateList = new Dictionary<string, List<State>>();
|
||||
m_GameObjectNameStateList.Add(characterGameObject, characterNameStateList);
|
||||
}
|
||||
|
||||
List<State> characterStateList;
|
||||
if (!characterNameStateList.TryGetValue(states[i].Name, out characterStateList)) {
|
||||
characterStateList = new List<State>();
|
||||
characterNameStateList.Add(states[i].Name, characterStateList);
|
||||
}
|
||||
|
||||
characterStateList.Add(states[i]);
|
||||
}
|
||||
}
|
||||
|
||||
List<State> stateList;
|
||||
if (!nameStateList.TryGetValue(states[i].Name, out stateList)) {
|
||||
stateList = new List<State>();
|
||||
nameStateList.Add(states[i].Name, stateList);
|
||||
}
|
||||
|
||||
stateList.Add(states[i]);
|
||||
m_StateArrayMap.Add(states[i], states);
|
||||
}
|
||||
|
||||
// Initialize the state after the map has been created.
|
||||
for (int i = 0; i < states.Length; ++i) {
|
||||
states[i].Initialize(owner, nameStateMap);
|
||||
}
|
||||
|
||||
// The default state is always last.
|
||||
states[states.Length - 1].Active = true;
|
||||
|
||||
// Remember the active character states so if a GameObject is initialized after a state has already been activated that newly initialized GameObject
|
||||
// can start the correct states. As an example an item could be picked up after the character is already aiming. That item should go directly
|
||||
// into the aim state instead of requring the character to aim again.
|
||||
if (characterGameObject != null) {
|
||||
if (characterGameObject == gameObject) {
|
||||
// If the current GameObject is the character then the active states should be tracked.
|
||||
if (!m_ActiveCharacterStates.ContainsKey(gameObject)) {
|
||||
m_ActiveCharacterStates.Add(gameObject, new HashSet<string>());
|
||||
}
|
||||
} else {
|
||||
// If the current GameObject is not the character then the active character states should be applied to the child object.
|
||||
HashSet<string> activeStates;
|
||||
if (m_ActiveCharacterStates.TryGetValue(characterGameObject, out activeStates)) {
|
||||
if (activeStates.Count > 0) {
|
||||
foreach (var stateName in activeStates) {
|
||||
SetState(gameObject, stateName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Links the original GameObject to the linked GameObject. When GameObjects are linked the state will be updated for each GameObject even when only the
|
||||
/// original GameObject is set.
|
||||
/// </summary>
|
||||
/// <param name="original">The original GameObject to link.</param>
|
||||
/// <param name="linkedGameObject">The GameObject that should be linked to the original GameObject.</param>
|
||||
/// <param name="link">Should the GameObjects be linked. If fales the GameObjects will be unlinked.</param>
|
||||
public static void LinkGameObjects(GameObject original, GameObject linkedGameObject, bool link)
|
||||
{
|
||||
Instance.LinkGameObjectsInternal(original, linkedGameObject, link);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which links the original GameObject to the linked GameObject. When GameObjects are linked the state will be updated for each
|
||||
/// GameObject even when only the original GameObject is set.
|
||||
/// </summary>
|
||||
/// <param name="original">The original GameObject to link.</param>
|
||||
/// <param name="linkedGameObject">The GameObject that should be linked to the original GameObject.</param>
|
||||
/// <param name="link">Should the GameObjects be linked. If fales the GameObjects will be unlinked.</param>
|
||||
private void LinkGameObjectsInternal(GameObject original, GameObject linkedGameObject, bool link)
|
||||
{
|
||||
List<GameObject> linkedGameObjectList;
|
||||
if (!m_LinkedGameObjectList.TryGetValue(original, out linkedGameObjectList) && link) {
|
||||
linkedGameObjectList = new List<GameObject>();
|
||||
m_LinkedGameObjectList.Add(original, linkedGameObjectList);
|
||||
}
|
||||
|
||||
if (linkedGameObjectList != null) {
|
||||
if (link) {
|
||||
linkedGameObjectList.Add(linkedGameObject);
|
||||
|
||||
// If the current GameObject is not the character then the active character states should be applied to the child object.
|
||||
HashSet<string> activeStates;
|
||||
if (m_ActiveCharacterStates.TryGetValue(original, out activeStates)) {
|
||||
if (activeStates.Count > 0) {
|
||||
foreach (var stateName in activeStates) {
|
||||
SetState(linkedGameObject, stateName, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
linkedGameObjectList.Remove(linkedGameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates the specified state.
|
||||
/// </summary>
|
||||
/// <param name="owner">The object that state belongs to.</param>
|
||||
/// <param name="states">A list of all of the states which the owner contains.</param>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
public static void SetState(object owner, State[] states, string stateName, bool active)
|
||||
{
|
||||
Instance.SetStateInternal(owner, states, stateName, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which activates or deactivates the specified state.
|
||||
/// </summary>
|
||||
/// <param name="owner">The object that state belongs to.</param>
|
||||
/// <param name="states">A list of all of the states which the owner contains.</param>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
private void SetStateInternal(object owner, State[] states, string stateName, bool active)
|
||||
{
|
||||
// Lookup the state by owner.
|
||||
Dictionary<string, State> nameStateMap;
|
||||
if (!m_ObjectNameStateMap.TryGetValue(owner, out nameStateMap)) {
|
||||
Debug.LogWarning("Warning: Unable to find the name state map on object " + owner);
|
||||
return;
|
||||
}
|
||||
|
||||
// Lookup the state by name.
|
||||
State state;
|
||||
if (!nameStateMap.TryGetValue(stateName, out state)) {
|
||||
Debug.LogWarning("Warning: Unable to find the state with name " + stateName);
|
||||
return;
|
||||
}
|
||||
|
||||
// The state has been found, activate or deactivate the states.
|
||||
if (state.Active != active) {
|
||||
ActivateStateInternal(state, active, states);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates all of the states on the specified GameObject with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to enable or disable all of the states on.</param>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
public static void SetState(GameObject gameObject, string stateName, bool active)
|
||||
{
|
||||
Instance.SetStateInternal(gameObject, stateName, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which activates or deactivates all of the states on the specified GameObject with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to enable or disable all of the states on.</param>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
private void SetStateInternal(GameObject gameObject, string stateName, bool active)
|
||||
{
|
||||
// Remember the active character status.
|
||||
var characterLocomotion = gameObject.GetCachedComponent<Character.UltimateCharacterLocomotion>();
|
||||
if (characterLocomotion != null) {
|
||||
HashSet<string> activeStates;
|
||||
if (m_ActiveCharacterStates.TryGetValue(gameObject, out activeStates)) {
|
||||
// If the state name appears within the set then the state is active.
|
||||
if (active) {
|
||||
activeStates.Add(stateName);
|
||||
} else {
|
||||
activeStates.Remove(stateName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup the states by GameObject.
|
||||
Dictionary<string, List<State>> nameStateList;
|
||||
if (!m_GameObjectNameStateList.TryGetValue(gameObject, out nameStateList)) {
|
||||
SetLinkStateInternal(gameObject, stateName, active);
|
||||
return;
|
||||
}
|
||||
|
||||
// Lookup the states by name.
|
||||
List<State> stateList;
|
||||
if (!nameStateList.TryGetValue(stateName, out stateList)) {
|
||||
SetLinkStateInternal(gameObject, stateName, active);
|
||||
return;
|
||||
}
|
||||
|
||||
// An event can be sent when the active status changes. This is useful for multiplayer in that it allows the networking implementation
|
||||
// to send the state changes across the network.
|
||||
if (m_SendStateChangeEvent) {
|
||||
EventHandler.ExecuteEvent("OnStateChange", gameObject, stateName, active);
|
||||
}
|
||||
|
||||
// The states have been found, activate or deactivate the states.
|
||||
for (int i = 0; i < stateList.Count; ++i) {
|
||||
if (stateList[i].Active != active) {
|
||||
// The state array must exist to be able to apply the changes.
|
||||
State[] states;
|
||||
if (!m_StateArrayMap.TryGetValue(stateList[i], out states)) {
|
||||
Debug.LogWarning("Warning: Unable to find the state array with state name " + stateName);
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify the owner that the states will change.
|
||||
stateList[i].Owner.StateWillChange();
|
||||
|
||||
ActivateStateInternal(stateList[i], active, states);
|
||||
|
||||
// Notify the owner that the state has changed.
|
||||
stateList[i].Owner.StateChange();
|
||||
}
|
||||
}
|
||||
|
||||
SetLinkStateInternal(gameObject, stateName, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which activates or deactivates all of the states on the GameObjects linked from the GameObject with the specified name.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to enable or disable all of the states on.</param>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
private void SetLinkStateInternal(GameObject gameObject, string stateName, bool active)
|
||||
{
|
||||
List<GameObject> linkedGameObjects;
|
||||
if (m_LinkedGameObjectList.TryGetValue(gameObject, out linkedGameObjects)) {
|
||||
for (int i = 0; i < linkedGameObjects.Count; ++i) {
|
||||
SetStateInternal(linkedGameObjects[i], stateName, active);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates the specified state. In most cases SetState should be used instead of ActivateState.
|
||||
/// </summary>
|
||||
/// <param name="state">The state to activate or deactivate.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
/// <param name="states">The array of states that the state belongs to.</param>
|
||||
public static void ActivateState(State state, bool active, State[] states)
|
||||
{
|
||||
Instance.ActivateStateInternal(state, active, states);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which activates or deactivates the specified state. In most cases SetState should be used instead of ActivateState.
|
||||
/// </summary>
|
||||
/// <param name="state">The state to activate or deactivate.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
/// <param name="states">The array of states that the state belongs to.</param>
|
||||
private void ActivateStateInternal(State state, bool active, State[] states)
|
||||
{
|
||||
// Return early if there no work needs to be done.
|
||||
if (state.Active == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the active state.
|
||||
state.Active = active;
|
||||
|
||||
// Apply the changes.
|
||||
CombineStates(state, active, states);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loops through the states and applies the value. The states are looped in the order specified within the inspector from top to bottom.
|
||||
/// </summary>
|
||||
/// <param name="state">The state that was activated or deactivated.</param>
|
||||
/// <param name="active">Was the activated?</param>
|
||||
/// <param name="states">The array of states that the state belongs to.</param>
|
||||
private void CombineStates(State state, bool active, State[] states)
|
||||
{
|
||||
if (active) {
|
||||
// Apply the default value of the blocked states before looping through all of the states. This will ensure the default value
|
||||
// is set for that property if no other states set the property value.
|
||||
for (int i = states.Length - 2; i > -1; --i) {
|
||||
if (states[i].Active && states[i].IsBlocked()) {
|
||||
states[states.Length - 1].ApplyValues(states[i].Preset.Delegates);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Restore the default values if the state is no longer active.
|
||||
states[states.Length - 1].ApplyValues(state.Preset.Delegates);
|
||||
}
|
||||
|
||||
// Loop backwards so the higher priority states are applied first. Do not apply the default state because it was applied above.
|
||||
for (int i = states.Length - 2; i > -1; --i) {
|
||||
// Don't apply the state if the state isn't active.
|
||||
if (!states[i].Active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Do not apply the state if it is currently blocked by another state.
|
||||
if (states[i].IsBlocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
states[i].ApplyValues();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the state and then deactivates the state after the specified amount of time.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The Gameobject to set the state on.</param>
|
||||
/// <param name="stateName">The name of the state to activate and then deactivate.</param>
|
||||
/// <param name="time">The amount of time that should elapse before the state is disabled.</param>
|
||||
public static void DeactivateStateTimer(GameObject gameObject, string stateName, float time)
|
||||
{
|
||||
Instance.DeactivateStateTimerInternal(gameObject, stateName, time);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method which activates the state and then deactivates the state after the specified amount of time.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The Gameobject to set the state on.</param>
|
||||
/// <param name="stateName">The name of the state to activate and then deactivate.</param>
|
||||
/// <param name="time">The amount of time that should elapse before the state is disabled.</param>
|
||||
private void DeactivateStateTimerInternal(GameObject gameObject, string stateName, float time)
|
||||
{
|
||||
if (m_DisableStateTimerMap == null) {
|
||||
m_DisableStateTimerMap = new Dictionary<GameObject, Dictionary<string, ScheduledEventBase>>();
|
||||
}
|
||||
|
||||
Dictionary<string, ScheduledEventBase> stateNameEventMap;
|
||||
if (m_DisableStateTimerMap.TryGetValue(gameObject, out stateNameEventMap)) {
|
||||
ScheduledEventBase disableEvent;
|
||||
if (stateNameEventMap.TryGetValue(stateName, out disableEvent)) {
|
||||
// The state name exists. This means that the timer is currently active and should first been cancelled.
|
||||
Scheduler.Cancel(disableEvent);
|
||||
disableEvent = Scheduler.Schedule(time, DeactivateState, gameObject, stateName);
|
||||
} else {
|
||||
// The state name hasn't been added yet. Add it to the map.
|
||||
disableEvent = Scheduler.Schedule(time, DeactivateState, gameObject, stateName);
|
||||
stateNameEventMap.Add(stateName, disableEvent);
|
||||
}
|
||||
} else {
|
||||
// Neither the GameObject nor the state has been activated. Create the maps.
|
||||
stateNameEventMap = new Dictionary<string, ScheduledEventBase>();
|
||||
var disableEvent = Scheduler.Schedule(time, DeactivateState, gameObject, stateName);
|
||||
stateNameEventMap.Add(stateName, disableEvent);
|
||||
m_DisableStateTimerMap.Add(gameObject, stateNameEventMap);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactives the specified state and removes it form the timer map.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to set the state on.</param>
|
||||
/// <param name="stateName">The name of the state to set.</param>
|
||||
private void DeactivateState(GameObject gameObject, string stateName)
|
||||
{
|
||||
SetState(gameObject, stateName, false);
|
||||
|
||||
Dictionary<string, ScheduledEventBase> stateNameEventMap;
|
||||
if (m_DisableStateTimerMap.TryGetValue(gameObject, out stateNameEventMap)) {
|
||||
stateNameEventMap.Remove(stateName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset the initialized variable when the scene is no longer loaded.
|
||||
/// </summary>
|
||||
/// <param name="scene">The scene that was unloaded.</param>
|
||||
private void SceneUnloaded(Scene scene)
|
||||
{
|
||||
s_Initialized = false;
|
||||
s_Instance = null;
|
||||
SceneManager.sceneUnloaded -= SceneUnloaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The object has been disabled.
|
||||
/// </summary>
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneUnloaded += SceneUnloaded;
|
||||
}
|
||||
|
||||
#if UNITY_2019_3_OR_NEWER
|
||||
/// <summary>
|
||||
/// Reset the static variables for domain reloading.
|
||||
/// </summary>
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void DomainReset()
|
||||
{
|
||||
s_Initialized = false;
|
||||
s_Instance = null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a172b92538d3594daa1dca445dfeb43
|
||||
timeCreated: 1504636212
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -400
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Acts as the parent object which can use the state system to change property values.
|
||||
/// </summary>
|
||||
public class StateObject : IStateOwner
|
||||
{
|
||||
[Tooltip("A list of all states that the component can change to.")]
|
||||
[HideInInspector] [SerializeField] protected State[] m_States = new State[] { new State("Default", true) };
|
||||
|
||||
[Opsive.Shared.Utility.NonSerialized] public State[] States { get { return m_States; } set { m_States = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the default values.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject this object is attached to.</param>
|
||||
public virtual void Initialize(GameObject gameObject)
|
||||
{
|
||||
if (Application.isPlaying) {
|
||||
StateManager.Initialize(gameObject, this, m_States);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates the specified state.
|
||||
/// </summary>
|
||||
/// <param name="stateName">The name of the state to change the active status of.</param>
|
||||
/// <param name="active">Should the state be activated?</param>
|
||||
public void SetState(string stateName, bool active)
|
||||
{
|
||||
StateManager.SetState(this, m_States, stateName, active);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the StateManager will change the active state on the current object.
|
||||
/// </summary>
|
||||
public virtual void StateWillChange() { }
|
||||
|
||||
/// <summary>
|
||||
/// Callback when the StateManager has changed the active state on the current object.
|
||||
/// </summary>
|
||||
public virtual void StateChange() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attribute which allows the a state to automatically be added.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
|
||||
public class AddState : Attribute
|
||||
{
|
||||
private string m_Name;
|
||||
private string m_PresetGUID;
|
||||
public string Name { get { return m_Name; } }
|
||||
public string PresetGUID { get { return m_PresetGUID; } }
|
||||
public AddState(string name, string presetGUID)
|
||||
{
|
||||
m_Name = name;
|
||||
m_PresetGUID = presetGUID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76aa3b7ef3f16494eb72fd2a9c1836c8
|
||||
timeCreated: 1482746434
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,147 @@
|
||||
/// ---------------------------------------------
|
||||
/// Ultimate Character Controller
|
||||
/// Copyright (c) Opsive. All Rights Reserved.
|
||||
/// https://www.opsive.com
|
||||
/// ---------------------------------------------
|
||||
|
||||
namespace Opsive.UltimateCharacterController.StateSystem
|
||||
{
|
||||
using Opsive.Shared.Events;
|
||||
using Opsive.Shared.Game;
|
||||
using Opsive.UltimateCharacterController.Audio;
|
||||
using Opsive.UltimateCharacterController.Game;
|
||||
using Opsive.UltimateCharacterController.Utility;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// Activates the specified state when the object enters the state, and deactivates the sate when the object leaves.
|
||||
/// </summary>
|
||||
public class StateTrigger : MonoBehaviour
|
||||
{
|
||||
[Tooltip("The name of the state to activate/deactivate.")]
|
||||
[SerializeField] protected string m_StateName;
|
||||
[Tooltip("The delay before the state should be enabled.")]
|
||||
[SerializeField] protected float m_Delay;
|
||||
[Tooltip("The amount of time the state should be enabled for.")]
|
||||
[SerializeField] protected float m_Duration;
|
||||
[Tooltip("The LayerMask that the trigger can set the state of.")]
|
||||
[SerializeField] protected LayerMask m_LayerMask = 1 << LayerManager.Character;
|
||||
[Tooltip("Should the state change only be applied to the character?")]
|
||||
[SerializeField] protected bool m_RequireCharacter = true;
|
||||
[Tooltip("Does the state require the character changing transforms?")]
|
||||
[SerializeField] protected bool m_CharacterTransformChange;
|
||||
[Tooltip("A set of AudioClips that can be played when the state is activated.")]
|
||||
[SerializeField] protected AudioClipSet m_ActivateAudioClipSet = new AudioClipSet();
|
||||
|
||||
public AudioClipSet ActivateAudioClipSet { get { return m_ActivateAudioClipSet; } set { m_ActivateAudioClipSet = value; } }
|
||||
|
||||
private ScheduledEventBase m_ActivateStateEvent;
|
||||
private List<GameObject> m_DeathDeactivations;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the default values.
|
||||
/// </summary>
|
||||
private void Awake()
|
||||
{
|
||||
if (string.IsNullOrEmpty(m_StateName)) {
|
||||
enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The other collider has entered the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider which entered the trigger.</param>
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (!MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StateBehavior stateBehavior;
|
||||
if ((m_RequireCharacter && (stateBehavior = other.GetComponentInParent<Character.UltimateCharacterLocomotion>()) != null) ||
|
||||
(!m_RequireCharacter && (stateBehavior = other.GetComponentInParent<StateBehavior>()) != null)) {
|
||||
m_ActivateStateEvent = Scheduler.Schedule(m_Delay, ChangeState, stateBehavior.gameObject, true);
|
||||
|
||||
m_ActivateAudioClipSet.PlayAudioClip(null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates or deactivates the state on the specified GameObject.
|
||||
/// </summary>
|
||||
/// <param name="gameObject">The GameObject to activate the state on.</param>
|
||||
/// <param name="activate">Should the state be activated?</param>
|
||||
private void ChangeState(GameObject gameObject, bool activate)
|
||||
{
|
||||
StateManager.SetState(gameObject, m_StateName, activate);
|
||||
if (m_CharacterTransformChange) {
|
||||
EventHandler.ExecuteEvent(gameObject, "OnCharacterImmediateTransformChange", true);
|
||||
}
|
||||
m_ActivateStateEvent = null;
|
||||
int index;
|
||||
if (m_DeathDeactivations != null && (index = m_DeathDeactivations.IndexOf(gameObject)) > 0) {
|
||||
m_DeathDeactivations.RemoveAt(index);
|
||||
EventHandler.UnregisterEvent(gameObject, "OnRespawn", OnRespawn);
|
||||
}
|
||||
|
||||
// The state can be disabled automatically.
|
||||
if (activate && m_Duration > 0) {
|
||||
Scheduler.Schedule(m_Duration, ChangeState, gameObject, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The other collider has exited the trigger.
|
||||
/// </summary>
|
||||
/// <param name="other">The collider which exited the trigger.</param>
|
||||
private void OnTriggerExit(Collider other)
|
||||
{
|
||||
if (m_Duration > 0 || !MathUtility.InLayerMask(other.gameObject.layer, m_LayerMask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StateBehavior stateBehavior;
|
||||
if ((m_RequireCharacter && (stateBehavior = other.GetComponentInParent<Character.UltimateCharacterLocomotion>()) != null) ||
|
||||
(!m_RequireCharacter && (stateBehavior = other.GetComponentInParent<StateBehavior>()) != null)) {
|
||||
if (m_ActivateStateEvent != null && m_ActivateStateEvent.Active) {
|
||||
Scheduler.Cancel(m_ActivateStateEvent);
|
||||
m_ActivateStateEvent = null;
|
||||
} else {
|
||||
// The state shouldn't change when the object dies. It can be changed when the character respawns.
|
||||
var health = other.gameObject.GetCachedParentComponent<Traits.Health>();
|
||||
if (health != null && !health.IsAlive()) {
|
||||
// When the character respawns the trigger enter/exit event may not fire. Register that the state should be deactivated so when the
|
||||
// character respawns the state can then be disabled.
|
||||
if (m_DeathDeactivations == null) {
|
||||
m_DeathDeactivations = new List<GameObject>();
|
||||
}
|
||||
if (!m_DeathDeactivations.Contains(stateBehavior.gameObject)) {
|
||||
m_DeathDeactivations.Add(stateBehavior.gameObject);
|
||||
EventHandler.RegisterEvent(stateBehavior.gameObject, "OnRespawn", OnRespawn);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
StateManager.SetState(stateBehavior.gameObject, m_StateName, false);
|
||||
if (m_CharacterTransformChange) {
|
||||
EventHandler.ExecuteEvent(stateBehavior.gameObject, "OnCharacterImmediateTransformChange", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The character has respawned.
|
||||
/// </summary>
|
||||
private void OnRespawn()
|
||||
{
|
||||
for (int i = m_DeathDeactivations.Count - 1; i > -1; --i) {
|
||||
StateManager.SetState(m_DeathDeactivations[i].gameObject, m_StateName, false);
|
||||
EventHandler.UnregisterEvent(m_DeathDeactivations[i].gameObject, "OnRespawn", OnRespawn);
|
||||
}
|
||||
m_DeathDeactivations.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 64f2fa1f4fdfea445b980a7530be3231
|
||||
timeCreated: 1512934167
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user