init 1.1.2
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5763c36eef64a04e8397263868ef52e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[System.Serializable]
|
||||
public class AnimationClass
|
||||
{
|
||||
public AnimationClass(float NewAnimationSpeed, AnimationClip NewAnimationClip, bool NewMirror)
|
||||
{
|
||||
AnimationSpeed = NewAnimationSpeed;
|
||||
AnimationClip = NewAnimationClip;
|
||||
Mirror = NewMirror;
|
||||
}
|
||||
|
||||
public float AnimationSpeed = 1;
|
||||
public AnimationClip AnimationClip;
|
||||
public bool Mirror = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63a47e5720f75cf4a9d3a28c0d699b90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,121 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the Animation Preview Editor with the preset Animation Event data.
|
||||
/// </summary>
|
||||
public static class AnimationEventInitializer
|
||||
{
|
||||
public static List<EmeraldAnimationEventsClass> GetEmeraldAnimationEvents ()
|
||||
{
|
||||
List<EmeraldAnimationEventsClass> EmeraldAnimationEvents = new List<EmeraldAnimationEventsClass>();
|
||||
|
||||
//Custom
|
||||
AnimationEvent Custom = new AnimationEvent();
|
||||
Custom.functionName = "---YOUR FUNCTION NAME HERE---";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Custom", Custom, "A custom/default event with no added parameters"));
|
||||
|
||||
//Emerald Attack Event
|
||||
AnimationEvent EmeraldAttack = new AnimationEvent();
|
||||
EmeraldAttack.functionName = "CreateAbility";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Create Ability", EmeraldAttack, "An event used for creating an AI's current ability (previously called EmeraldAttackEvent). This is required for Ability Objects to be triggered and should be done for all attack animations.\n\nNote: If your AI uses Attack Transform, " +
|
||||
"you should include the name of the Attack Transform in the String Paramter of this event. This will allow an ability to spawn from the Attack Transform location."));
|
||||
|
||||
//Charge Ability
|
||||
AnimationEvent ChargeEffect = new AnimationEvent();
|
||||
ChargeEffect.functionName = "ChargeEffect";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Charge Effect", ChargeEffect, "An event used for triggering an AI's current abilty's Charge Effect. You will need to add the Attack Transform you would like the charge effect to spawn at. " +
|
||||
"This is done through the String Parameter and is based off of the AI's Attack Transform list within its Combat Component. An Ability Object must have a Charge Module and have it enabled or this event will be skipped." +
|
||||
"\n\nNote: This will not create an ability. The CreateAbility event still needs to be assigned, which should be after a Charge Effect event. This Animation Event is completely optional."));
|
||||
|
||||
//Fade Out IK
|
||||
AnimationEvent FadeOutIK = new AnimationEvent();
|
||||
FadeOutIK.functionName = "FadeOutIK";
|
||||
FadeOutIK.floatParameter = 5f;
|
||||
FadeOutIK.stringParameter = "---YOUR RIG NAME TO FADE HERE---";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Fade Out IK", FadeOutIK, "Fade out an AI's IK overtime. This is helpful if an AI's IK is interfering with certain animations " +
|
||||
"(such as hit, equipping, certain attacks, and death animations).\n\nFloatParamer = Fade Out Time (In Seconds)\n\nStringParameter = The name of your rig you'd like to fade out"));
|
||||
|
||||
//Fade In IK
|
||||
AnimationEvent FadeInIK = new AnimationEvent();
|
||||
FadeInIK.functionName = "FadeInIK";
|
||||
FadeInIK.floatParameter = 5f;
|
||||
FadeInIK.stringParameter = "---YOUR RIG NAME TO FADE HERE---";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Fade In IK", FadeInIK, "Fade in an AI's IK overtime. This should be used after Fade Out IK has been used.\n\nFloatParamer = Fade In Time (In Seconds)\n\nStringParameter = The name of your rig you'd like to fade in"));
|
||||
|
||||
//Enable Weapon Collider
|
||||
AnimationEvent EnableWeaponCollider = new AnimationEvent();
|
||||
EnableWeaponCollider.functionName = "EnableWeaponCollider";
|
||||
EnableWeaponCollider.stringParameter = "---THE NAME OF YOUR AI'S WEAPON HERE---";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Enable Weapon Collider", EnableWeaponCollider, "Enables an AI's weapon's collider (The weapon object must also have a WeaponCollider component and be set up through an AI's EmeraldItems component)." +
|
||||
"\n\nNote: You must also assign the gameobject name of your AI's weapon to the String parameter of this Animation Event. This is used to search through an AI's Items Component to find which weapon to enable. For a detailed tutorial on this, see the Emerald AI Wiki."));
|
||||
|
||||
//Disable Weapon Collider
|
||||
AnimationEvent DisableWeaponCollider = new AnimationEvent();
|
||||
DisableWeaponCollider.functionName = "DisableWeaponCollider";
|
||||
DisableWeaponCollider.stringParameter = "---THE NAME OF YOUR AI'S WEAPON HERE---";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Disable Weapon Collider", DisableWeaponCollider, "Disables an AI's weapon's collider (The weapon object must also have a WeaponCollider component and be set up through an AI's EmeraldItems component)." +
|
||||
"\n\nNote: You must also assign the gameobject name of your AI's weapon to the String parameter of this Animation Event. This is used to search through an AI's Items Component to find which weapon to disable. For a detailed tutorial on this, see the Emerald AI Wiki."));
|
||||
|
||||
//Equip Weapon 1
|
||||
AnimationEvent EquipWeapon1 = new AnimationEvent();
|
||||
EquipWeapon1.functionName = "EquipWeapon";
|
||||
EquipWeapon1.stringParameter = "Weapon Type 1";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Equip Weapon Type 1", EquipWeapon1, "Equip an AI's Type 1 Weapon (The weapon object must be setup through Emerald AI)"));
|
||||
|
||||
//Equip Weapon 2
|
||||
AnimationEvent EquipWeapon2 = new AnimationEvent();
|
||||
EquipWeapon2.functionName = "EquipWeapon";
|
||||
EquipWeapon2.stringParameter = "Weapon Type 2";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Equip Weapon Type 2", EquipWeapon2, "Equip an AI's Type 2 Weapon (The weapon object must be setup through Emerald AI)"));
|
||||
|
||||
//Unequip Weapon 1
|
||||
AnimationEvent UnequipWeapon1 = new AnimationEvent();
|
||||
UnequipWeapon1.functionName = "UnequipWeapon";
|
||||
UnequipWeapon1.stringParameter = "Weapon Type 1";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Unequip Weapon Type 1", UnequipWeapon1, "Unquip an AI's Type 1 Weapon (The weapon object must be setup through Emerald AI)"));
|
||||
|
||||
//Unequip Weapon 2
|
||||
AnimationEvent UnequipWeapon2 = new AnimationEvent();
|
||||
UnequipWeapon2.functionName = "UnequipWeapon";
|
||||
UnequipWeapon2.stringParameter = "Weapon Type 2";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Unequip Weapon Type 2", UnequipWeapon2, "Unequip an AI's Type 2 Weapon (The weapon object must be setup through Emerald AI)"));
|
||||
|
||||
//Enable Item
|
||||
AnimationEvent EnableItem = new AnimationEvent();
|
||||
EnableItem.functionName = "EnableItem";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Enable Item", EnableItem, "Enable an Item by passing the ItemID. This is based off of an AI's Item List and an AI must have an EmeraldAIItem component.\n\nIntParameter = ItemID"));
|
||||
|
||||
//Disable Item
|
||||
AnimationEvent DisableItem = new AnimationEvent();
|
||||
DisableItem.functionName = "DisableItem";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Disable Item", DisableItem, "Disable an Item by passing the ItemID. This is based off of an AI's Item List and an AI must have an EmeraldAIItem component.\n\nIntParameter = ItemID"));
|
||||
|
||||
//Footstep Sound
|
||||
AnimationEvent Footstep = new AnimationEvent();
|
||||
Footstep.functionName = "Footstep";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Footstep", Footstep, "If using a Footstep Component:\nCreates a footstep effect and sound based on the detected surface of the footstep (requires a Footstep Component that has been set up).\n\n" +
|
||||
"If NOT using a Footstep Component:\nPlay a random footstep sound based off of your AI's Walk Sound List."));
|
||||
|
||||
//Play Attack Sound
|
||||
AnimationEvent PlayAttackSound = new AnimationEvent();
|
||||
PlayAttackSound.functionName = "PlayAttackSound";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Play Attack Sound", PlayAttackSound, "Play a random attack sound based off of your AI's Attack Sound List."));
|
||||
|
||||
//Play Sound Effect
|
||||
AnimationEvent PlaySoundEffect = new AnimationEvent();
|
||||
PlaySoundEffect.functionName = "PlaySoundEffect";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Play Sound Effect", PlaySoundEffect, "Play a specified sound from an AI's Sounds List by passing the SoundEffectID.\n\nIntParameter = SoundEffectID"));
|
||||
|
||||
//Play Warning Sound
|
||||
AnimationEvent PlayWarningSound = new AnimationEvent();
|
||||
PlayWarningSound.functionName = "PlayWarningSound";
|
||||
EmeraldAnimationEvents.Add(new EmeraldAnimationEventsClass("Play Warning Sound", PlayWarningSound, "Play a random warning sound based off of your AI's Warning Sound List."));
|
||||
|
||||
return EmeraldAnimationEvents;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8bc209408af88e418c3f14ce2e4b260
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// Since most animations are repeated, a parent class is used for each animation category
|
||||
/// (NonCombat, Type 1, and Type 2). Animations that are not used are simply not displayed.
|
||||
/// This also makes for adding new animations with future updates easier.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class AnimationParentClass
|
||||
{
|
||||
/// <summary>
|
||||
/// List of Animations (NonCombat Only)
|
||||
/// </summary>
|
||||
public List<AnimationClass> IdleList = new List<AnimationClass>();
|
||||
|
||||
/// <summary>
|
||||
/// Stationary Idle Animation
|
||||
/// </summary>
|
||||
public AnimationClass IdleStationary;
|
||||
|
||||
/// <summary>
|
||||
/// Warning Animation (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass IdleWarning;
|
||||
|
||||
/// <summary>
|
||||
/// Walk Animations
|
||||
/// </summary>
|
||||
public AnimationClass WalkLeft, WalkForward, WalkRight, WalkBack;
|
||||
|
||||
/// <summary>
|
||||
/// Run Animations
|
||||
/// </summary>
|
||||
public AnimationClass RunLeft, RunForward, RunRight;
|
||||
|
||||
/// <summary>
|
||||
/// Turn Animations
|
||||
/// </summary>
|
||||
public AnimationClass TurnLeft, TurnRight;
|
||||
|
||||
/// <summary>
|
||||
/// List of Hit Animations
|
||||
/// </summary>
|
||||
public List<AnimationClass> HitList = new List<AnimationClass>();
|
||||
|
||||
/// <summary>
|
||||
/// List of Death Animations
|
||||
/// </summary>
|
||||
public List<AnimationClass> DeathList = new List<AnimationClass>();
|
||||
|
||||
/// <summary>
|
||||
/// Strafe Animations (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass StrafeLeft, StrafeRight;
|
||||
|
||||
/// <summary>
|
||||
/// Block Animations (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass BlockIdle, BlockHit;
|
||||
|
||||
/// <summary>
|
||||
/// Dodge Animations (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass DodgeLeft, DodgeBack, DodgeRight;
|
||||
|
||||
/// <summary>
|
||||
/// Recoil Animation (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass Recoil;
|
||||
|
||||
/// <summary>
|
||||
/// Stunned Animation (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass Stunned;
|
||||
|
||||
/// <summary>
|
||||
/// Equip and Unequip Animations (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public AnimationClass PutAwayWeapon, PullOutWeapon;
|
||||
|
||||
/// <summary>
|
||||
/// List of Attack Animations (Type 1 and Type 2 Only)
|
||||
/// </summary>
|
||||
public List<AnimationClass> AttackList = new List<AnimationClass>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d616af0e007bdc4a94109ff7e1b8127
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds all of an AI's attack attack information.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class AttackClass
|
||||
{
|
||||
public int AttackListIndex = 0;
|
||||
public AttackPickTypes AttackPickType = AttackPickTypes.Order;
|
||||
[SerializeField]
|
||||
public List<AttackData> AttackDataList = new List<AttackData>();
|
||||
|
||||
[System.Serializable]
|
||||
public class AttackData
|
||||
{
|
||||
public EmeraldAbilityObject AbilityObject;
|
||||
public int AttackAnimation;
|
||||
public int AttackOdds = 25;
|
||||
public float AttackDistance = 3f;
|
||||
public float TooCloseDistance = 1f;
|
||||
public bool CooldownIgnored;
|
||||
public float CooldownTimeStamp;
|
||||
|
||||
public bool Contains(List<AttackData> m_AttackDataList, AttackData m_AttackDataClass)
|
||||
{
|
||||
foreach (AttackData AttackInfo in m_AttackDataList)
|
||||
{
|
||||
return (AttackInfo == m_AttackDataClass);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec03113c4b005254885582b621087135
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public class EmeraldAnimationEventsClass
|
||||
{
|
||||
public string eventDisplayName;
|
||||
public string eventDescription;
|
||||
public AnimationEvent animationEvent;
|
||||
|
||||
public EmeraldAnimationEventsClass(string m_eventDisplayName, AnimationEvent m_animationEvent, string m_eventDescription)
|
||||
{
|
||||
eventDisplayName = m_eventDisplayName;
|
||||
animationEvent = m_animationEvent;
|
||||
eventDescription = m_eventDescription;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6bd069176478b34bae65fc7826d2215
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[System.Serializable]
|
||||
public class EmoteAnimationClass
|
||||
{
|
||||
public EmoteAnimationClass(int NewAnimationID, AnimationClip NewEmoteAnimationClip)
|
||||
{
|
||||
AnimationID = NewAnimationID;
|
||||
EmoteAnimationClip = NewEmoteAnimationClip;
|
||||
}
|
||||
|
||||
public int AnimationID = 1;
|
||||
public AnimationClip EmoteAnimationClip;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c9170614f478a8e44b8fef898167670f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[System.Serializable]
|
||||
public class FactionClass
|
||||
{
|
||||
public int FactionIndex;
|
||||
public RelationTypes RelationType;
|
||||
|
||||
public FactionClass(int m_FactionIndex, int m_RelationType)
|
||||
{
|
||||
FactionIndex = m_FactionIndex;
|
||||
RelationType = (RelationTypes)m_RelationType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fb3ed8e04ef6024aa8d3102e80a421d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// Used through projectiles to cache effects so they can be enabled and disabled when needed.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class ProjectileEffectsClass
|
||||
{
|
||||
public ParticleSystemRenderer EffectParticle;
|
||||
public GameObject EffectObject;
|
||||
|
||||
public ProjectileEffectsClass(ParticleSystemRenderer m_EffectParticle, GameObject m_EffectObject)
|
||||
{
|
||||
EffectParticle = m_EffectParticle;
|
||||
EffectObject = m_EffectObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc221726d07b4ec43be8323a834fcdca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 164660049c8f6a4429f124269c7b1230
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,532 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
using System.Linq;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class EmeraldAnimatorGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates an Animator Controller using the passed EmeraldAnimation values. This is done by searching each state by name and applying the proper animation, animation speed, and mirroring values.
|
||||
/// </summary>
|
||||
public static void GenerateAnimatorController(AnimationProfile EmeraldAnimationComponent)
|
||||
{
|
||||
AnimatorController m_AnimatorController = EmeraldAnimationComponent.AIAnimator as AnimatorController;
|
||||
|
||||
ApplyNonCombatAnimations(EmeraldAnimationComponent, m_AnimatorController);
|
||||
ApplyType1Animations(EmeraldAnimationComponent, m_AnimatorController);
|
||||
ApplyType2Animations(EmeraldAnimationComponent, m_AnimatorController);
|
||||
|
||||
EmeraldAnimationComponent.AnimatorControllerGenerated = true;
|
||||
EmeraldAnimationComponent.AnimationsUpdated = false;
|
||||
EmeraldAnimationComponent.AnimationListsChanged = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set each sub-state's states with an animation from the passed AnimationClass list.
|
||||
/// </summary>
|
||||
static void SetState(ChildAnimatorStateMachine childAnimatorStateMachine, string stateName, ChildAnimatorState[] childAnimatorState, List<AnimationClass> animationList)
|
||||
{
|
||||
if (childAnimatorStateMachine.stateMachine.name == stateName)
|
||||
{
|
||||
for (int f = 0; f < animationList.Count; f++)
|
||||
{
|
||||
childAnimatorState[f].state.motion = animationList[f].AnimationClip;
|
||||
childAnimatorState[f].state.speed = animationList[f].AnimationSpeed;
|
||||
}
|
||||
|
||||
//Set each state that's greater than the passed list count to null so it is no longer preset on the state.
|
||||
for (int f = animationList.Count; f < childAnimatorState.Length; f++)
|
||||
{
|
||||
childAnimatorState[f].state.motion = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns all non-combat animations to the Animator Controller.
|
||||
/// </summary>
|
||||
static void ApplyNonCombatAnimations(AnimationProfile EmeraldAnimationComponent, AnimatorController m_AnimatorController)
|
||||
{
|
||||
//Go through each sub-state by name and assign the animation to each state within the sub-state using an index
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.stateMachines.Length; i++)
|
||||
{
|
||||
ChildAnimatorStateMachine childAnimatorStateMachine = m_AnimatorController.layers[0].stateMachine.stateMachines[i];
|
||||
ChildAnimatorState[] childAnimatorState = m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.states;
|
||||
|
||||
SetState(childAnimatorStateMachine, "Idle States", childAnimatorState, EmeraldAnimationComponent.NonCombatAnimations.IdleList);
|
||||
SetState(childAnimatorStateMachine, "Hit States", childAnimatorState, EmeraldAnimationComponent.NonCombatAnimations.HitList);
|
||||
SetState(childAnimatorStateMachine, "Death States", childAnimatorState, EmeraldAnimationComponent.NonCombatAnimations.DeathList);
|
||||
|
||||
if (m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.name == "Emote States")
|
||||
{
|
||||
for (int f = 0; f < EmeraldAnimationComponent.EmoteAnimationList.Count; f++)
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.states[f].state.motion = EmeraldAnimationComponent.EmoteAnimationList[f].EmoteAnimationClip;
|
||||
//m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.states[f].state.speed = EmeraldAnimationComponent.EmoteAnimationList[f].AnimationSpeed; //TODO: Need speed parameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Go through each state by name and assign the animation to the proper state
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.states.Length; i++)
|
||||
{
|
||||
if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Turn Left")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.NonCombatAnimations.TurnLeft.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.NonCombatAnimations.TurnLeft.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.NonCombatAnimations.TurnLeft.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Turn Right")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.NonCombatAnimations.TurnRight.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.NonCombatAnimations.TurnRight.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.NonCombatAnimations.TurnRight.AnimationSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
//Get and assign Movement Blend Tree animations
|
||||
AnimatorState m_StateMachine = m_AnimatorController.layers[0].stateMachine.states[0].state;
|
||||
BlendTree MovementBlendTree = m_StateMachine.motion as BlendTree;
|
||||
|
||||
var SerializedIdleBlendTreeRef = new SerializedObject(MovementBlendTree);
|
||||
var MovementBlendTreeChildren = SerializedIdleBlendTreeRef.FindProperty("m_Childs");
|
||||
|
||||
//Assign the Idle animation and settings to the Idle Blend Tree
|
||||
var MovementMotionSlot1 = MovementBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var MovementMotion1 = MovementMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
BlendTree IdleBlendTree = MovementMotion1.objectReferenceValue as BlendTree;
|
||||
var SerializedIdleBlendTree = new SerializedObject(IdleBlendTree);
|
||||
var IdleBlendTreeChildren = SerializedIdleBlendTree.FindProperty("m_Childs");
|
||||
var IdleMotionSlot = IdleBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var IdleAnimation = IdleMotionSlot.FindPropertyRelative("m_Motion");
|
||||
var IdleAnimationSpeed = IdleMotionSlot.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.IdleStationary.AnimationSpeed != 0) IdleAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.IdleStationary.AnimationSpeed;
|
||||
IdleAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.IdleStationary.AnimationClip;
|
||||
SerializedIdleBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Walk animations and settings to the Walk Blend Tree; one for walk left, walk straight, and walk right.
|
||||
var MovementMotionSlot2 = MovementBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var MovementMotion2 = MovementMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
BlendTree WalkBlendTree = MovementMotion2.objectReferenceValue as BlendTree;
|
||||
var SerializedWalkBlendTree = new SerializedObject(WalkBlendTree);
|
||||
var WalkBlendTreeChildren = SerializedWalkBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Adjust the non-combat movement thresholds depending on which Animator Type is being used.
|
||||
var WalkMovementMotionThreshold = MovementBlendTreeChildren.GetArrayElementAtIndex(1).FindPropertyRelative("m_Threshold");
|
||||
var RunMovementMotionThreshold = MovementBlendTreeChildren.GetArrayElementAtIndex(2).FindPropertyRelative("m_Threshold");
|
||||
|
||||
SerializedIdleBlendTreeRef.ApplyModifiedProperties();
|
||||
|
||||
//Walk Left
|
||||
var WalkMotionSlot1 = WalkBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var WalkLeftAnimation = WalkMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var WalkLeftAnimationSpeed = WalkMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var WalkLeftMirror = WalkMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.WalkLeft.AnimationSpeed != 0) WalkLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.WalkLeft.AnimationSpeed;
|
||||
WalkLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.WalkLeft.AnimationClip;
|
||||
WalkLeftMirror.boolValue = EmeraldAnimationComponent.NonCombatAnimations.WalkLeft.Mirror;
|
||||
|
||||
//Walk Straight
|
||||
var WalkMotionSlot2 = WalkBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var WalkStraightAnimation = WalkMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var WalkStraightAnimationSpeed = WalkMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.WalkForward.AnimationSpeed != 0) WalkStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.WalkForward.AnimationSpeed;
|
||||
WalkStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.WalkForward.AnimationClip;
|
||||
|
||||
//Walk Right
|
||||
var WalkMotionSlot3 = WalkBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var WalkRightAnimation = WalkMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var WalkRightAnimationSpeed = WalkMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var WalkRightMirror = WalkMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.WalkRight.AnimationSpeed != 0) WalkRightAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.WalkRight.AnimationSpeed;
|
||||
WalkRightAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.WalkRight.AnimationClip;
|
||||
WalkRightMirror.boolValue = EmeraldAnimationComponent.NonCombatAnimations.WalkRight.Mirror;
|
||||
|
||||
SerializedWalkBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Run animations and settings to the Run Blend Tree; one for run left, run straight, and run right.
|
||||
var MovementMotionSlot3 = MovementBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var MovementMotion3 = MovementMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
BlendTree RunBlendTree = MovementMotion3.objectReferenceValue as BlendTree;
|
||||
var SerializedRunBlendTree = new SerializedObject(RunBlendTree);
|
||||
var RunBlendTreeChildren = SerializedRunBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Run Left
|
||||
var RunMotionSlot1 = RunBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var RunLeftAnimation = RunMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var RunLeftAnimationSpeed = RunMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var RunLeftMirror = RunMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.RunLeft.AnimationSpeed != 0) RunLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.RunLeft.AnimationSpeed;
|
||||
RunLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.RunLeft.AnimationClip;
|
||||
RunLeftMirror.boolValue = EmeraldAnimationComponent.NonCombatAnimations.RunLeft.Mirror;
|
||||
|
||||
//Run Straight
|
||||
var RunMotionSlot2 = RunBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var RunStraightAnimation = RunMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var RunStraightAnimationSpeed = RunMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.RunForward.AnimationSpeed != 0) RunStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.RunForward.AnimationSpeed;
|
||||
RunStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.RunForward.AnimationClip;
|
||||
|
||||
//Run Right
|
||||
var RunMotionSlot3 = RunBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var RunRightAnimation = RunMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var RunRightAnimationSpeed = RunMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var RunRightMirror = RunMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.NonCombatAnimations.RunRight.AnimationSpeed != 0) RunRightAnimationSpeed.floatValue = EmeraldAnimationComponent.NonCombatAnimations.RunRight.AnimationSpeed;
|
||||
RunRightAnimation.objectReferenceValue = EmeraldAnimationComponent.NonCombatAnimations.RunRight.AnimationClip;
|
||||
RunRightMirror.boolValue = EmeraldAnimationComponent.NonCombatAnimations.RunRight.Mirror;
|
||||
|
||||
SerializedRunBlendTree.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns all type 1 weapon type animations to the Animator Controller.
|
||||
/// </summary>
|
||||
static void ApplyType1Animations(AnimationProfile EmeraldAnimationComponent, AnimatorController m_AnimatorController)
|
||||
{
|
||||
//Go through each sub-state by name and assign the animation to each state within the sub-state using an index
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.stateMachines.Length; i++)
|
||||
{
|
||||
ChildAnimatorStateMachine childAnimatorStateMachine = m_AnimatorController.layers[0].stateMachine.stateMachines[i];
|
||||
ChildAnimatorState[] childAnimatorState = m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.states;
|
||||
|
||||
SetState(childAnimatorStateMachine, "Combat Hit States (Type 1)", childAnimatorState, EmeraldAnimationComponent.Type1Animations.HitList);
|
||||
SetState(childAnimatorStateMachine, "Attack States (Type 1)", childAnimatorState, EmeraldAnimationComponent.Type1Animations.AttackList);
|
||||
SetState(childAnimatorStateMachine, "Death States (Type 1)", childAnimatorState, EmeraldAnimationComponent.Type1Animations.DeathList);
|
||||
|
||||
AnimationClass[] Type1StrafeList = new AnimationClass[2] { EmeraldAnimationComponent.Type1Animations.StrafeLeft, EmeraldAnimationComponent.Type1Animations.StrafeRight };
|
||||
SetState(childAnimatorStateMachine, "Strafe States (Type 1)", childAnimatorState, Type1StrafeList.ToList());
|
||||
AnimationClass[] Type1DodgeList = new AnimationClass[3] { EmeraldAnimationComponent.Type1Animations.DodgeLeft, EmeraldAnimationComponent.Type1Animations.DodgeRight, EmeraldAnimationComponent.Type1Animations.DodgeBack };
|
||||
SetState(childAnimatorStateMachine, "Dodge States (Type 1)", childAnimatorState, Type1DodgeList.ToList());
|
||||
}
|
||||
|
||||
//Go through each state by name and assign the animation to the proper state
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.states.Length; i++)
|
||||
{
|
||||
if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Pull Out Weapon (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.PullOutWeapon.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.PullOutWeapon.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Put Away Weapon (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.PutAwayWeapon.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.PutAwayWeapon.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Combat Turn Left (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.TurnLeft.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type1Animations.TurnLeft.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.TurnLeft.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Combat Turn Right (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.TurnRight.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type1Animations.TurnRight.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.TurnRight.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Walk Backwards (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.WalkBack.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type1Animations.WalkBack.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.WalkBack.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Block (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.BlockIdle.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.BlockIdle.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Block Hit (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.BlockHit.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.BlockHit.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Warning (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.IdleWarning.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.IdleWarning.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Recoil (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.Recoil.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.Recoil.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Stunned (Type 1)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type1Animations.Stunned.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type1Animations.Stunned.AnimationSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
//Get and assign Combat Movement Blend Tree animations
|
||||
AnimatorState m_StateMachine_Combat = m_AnimatorController.layers[0].stateMachine.states.ToList().Find(x => x.state.name == "Combat Movement (Type 1)").state;
|
||||
BlendTree CombatMovementBlendTree = m_StateMachine_Combat.motion as BlendTree;
|
||||
|
||||
var SerializedCombatIdleBlendTreeRef = new SerializedObject(CombatMovementBlendTree);
|
||||
var CombatMovementBlendTreeChildren = SerializedCombatIdleBlendTreeRef.FindProperty("m_Childs");
|
||||
|
||||
//Assign the Idle animation and settings to the Idle Blend Tree
|
||||
var CombatMovementMotionSlot1 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatMovementMotion1 = CombatMovementMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatIdleBlendTree = CombatMovementMotion1.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatIdleBlendTree = new SerializedObject(CombatIdleBlendTree);
|
||||
var CombatIdleBlendTreeChildren = SerializedCombatIdleBlendTree.FindProperty("m_Childs");
|
||||
var CombatIdleMotionSlot = CombatIdleBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatIdleAnimation = CombatIdleMotionSlot.FindPropertyRelative("m_Motion");
|
||||
var CombatIdleAnimationSpeed = CombatIdleMotionSlot.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type1Animations.IdleStationary.AnimationSpeed != 0) CombatIdleAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.IdleStationary.AnimationSpeed;
|
||||
CombatIdleAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.IdleStationary.AnimationClip;
|
||||
SerializedCombatIdleBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Walk animations and settings to the Walk Blend Tree; one for walk left, walk straight, and walk right.
|
||||
var CombatMovementMotionSlot2 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatMovementMotion2 = CombatMovementMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatWalkBlendTree = CombatMovementMotion2.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatWalkBlendTree = new SerializedObject(CombatWalkBlendTree);
|
||||
var CombatWalkBlendTreeChildren = SerializedCombatWalkBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Adjust the combat movement thresholds depending on which Animator Type is being used.
|
||||
var CombatWalkMovementMotionThreshold = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(1).FindPropertyRelative("m_Threshold");
|
||||
var CombatRunMovementMotionThreshold = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(2).FindPropertyRelative("m_Threshold");
|
||||
|
||||
SerializedCombatIdleBlendTreeRef.ApplyModifiedProperties();
|
||||
|
||||
//Walk Left
|
||||
var CombatWalkMotionSlot1 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatWalkLeftAnimation = CombatWalkMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkLeftAnimationSpeed = CombatWalkMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var CombatWalkLeftMirror = CombatWalkMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type1Animations.WalkLeft.AnimationSpeed != 0) CombatWalkLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.WalkLeft.AnimationSpeed;
|
||||
CombatWalkLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.WalkLeft.AnimationClip;
|
||||
CombatWalkLeftMirror.boolValue = EmeraldAnimationComponent.Type1Animations.WalkLeft.Mirror;
|
||||
|
||||
//Walk Straight
|
||||
var CombatWalkMotionSlot2 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatWalkStraightAnimation = CombatWalkMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkStraightAnimationSpeed = CombatWalkMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type1Animations.WalkForward.AnimationSpeed != 0) CombatWalkStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.WalkForward.AnimationSpeed;
|
||||
CombatWalkStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.WalkForward.AnimationClip;
|
||||
|
||||
//Walk Right
|
||||
var CombatWalkMotionSlot3 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatWalkRightAnimation = CombatWalkMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkRightAnimationSpeed = CombatWalkMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var CombatWalkRightMirror = CombatWalkMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type1Animations.WalkRight.AnimationSpeed != 0) CombatWalkRightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.WalkRight.AnimationSpeed;
|
||||
CombatWalkRightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.WalkRight.AnimationClip;
|
||||
CombatWalkRightMirror.boolValue = EmeraldAnimationComponent.Type1Animations.WalkRight.Mirror;
|
||||
|
||||
SerializedCombatWalkBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Run animations and settings to the Run Blend Tree; one for run left, run straight, and run right.
|
||||
var CombatMovementMotionSlot3 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatMovementMotion3 = CombatMovementMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatRunBlendTree = CombatMovementMotion3.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatRunBlendTree = new SerializedObject(CombatRunBlendTree);
|
||||
var CombatRunBlendTreeChildren = SerializedCombatRunBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Run Left
|
||||
var CombatRunMotionSlot1 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatRunLeftAnimation = CombatRunMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var CombatRunLeftAnimationSpeed = CombatRunMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var CombatRunLeftMirror = CombatRunMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type1Animations.RunLeft.AnimationSpeed != 0) CombatRunLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.RunLeft.AnimationSpeed;
|
||||
CombatRunLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.RunLeft.AnimationClip;
|
||||
CombatRunLeftMirror.boolValue = EmeraldAnimationComponent.Type1Animations.RunLeft.Mirror;
|
||||
|
||||
//Run Straight
|
||||
var CombatRunMotionSlot2 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatRunStraightAnimation = CombatRunMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var CombatRunStraightAnimationSpeed = CombatRunMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type1Animations.RunForward.AnimationSpeed != 0) CombatRunStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.RunForward.AnimationSpeed;
|
||||
CombatRunStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.RunForward.AnimationClip;
|
||||
|
||||
//Run Right
|
||||
var CombatRunMotionSlot3 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatRunRightAnimation = CombatRunMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var CombatRunRightAnimationSpeed = CombatRunMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var CombatRunRightMirror = CombatRunMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type1Animations.RunRight.AnimationSpeed != 0) CombatRunRightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type1Animations.RunRight.AnimationSpeed;
|
||||
CombatRunRightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type1Animations.RunRight.AnimationClip;
|
||||
CombatRunRightMirror.boolValue = EmeraldAnimationComponent.Type1Animations.RunRight.Mirror;
|
||||
|
||||
SerializedCombatRunBlendTree.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns all type 2 weapon type animations to the Animator Controller.
|
||||
/// </summary>
|
||||
static void ApplyType2Animations(AnimationProfile EmeraldAnimationComponent, AnimatorController m_AnimatorController)
|
||||
{
|
||||
//Go through each sub-state by name and assign the animation to each state within the sub-state using an index
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.stateMachines.Length; i++)
|
||||
{
|
||||
ChildAnimatorStateMachine childAnimatorStateMachine = m_AnimatorController.layers[0].stateMachine.stateMachines[i];
|
||||
ChildAnimatorState[] childAnimatorState = m_AnimatorController.layers[0].stateMachine.stateMachines[i].stateMachine.states;
|
||||
|
||||
SetState(childAnimatorStateMachine, "Combat Hit States (Type 2)", childAnimatorState, EmeraldAnimationComponent.Type2Animations.HitList);
|
||||
SetState(childAnimatorStateMachine, "Attack States (Type 2)", childAnimatorState, EmeraldAnimationComponent.Type2Animations.AttackList);
|
||||
SetState(childAnimatorStateMachine, "Death States (Type 2)", childAnimatorState, EmeraldAnimationComponent.Type2Animations.DeathList);
|
||||
|
||||
AnimationClass[] Type2StrafeList = new AnimationClass[2] { EmeraldAnimationComponent.Type2Animations.StrafeLeft, EmeraldAnimationComponent.Type2Animations.StrafeRight };
|
||||
SetState(childAnimatorStateMachine, "Strafe States (Type 2)", childAnimatorState, Type2StrafeList.ToList());
|
||||
AnimationClass[] Type2DodgeList = new AnimationClass[3] { EmeraldAnimationComponent.Type2Animations.DodgeLeft, EmeraldAnimationComponent.Type2Animations.DodgeRight, EmeraldAnimationComponent.Type2Animations.DodgeBack };
|
||||
SetState(childAnimatorStateMachine, "Dodge States (Type 2)", childAnimatorState, Type2DodgeList.ToList());
|
||||
}
|
||||
|
||||
//Go through each state by name and assign the animation to the proper state
|
||||
for (int i = 0; i < m_AnimatorController.layers[0].stateMachine.states.Length; i++)
|
||||
{
|
||||
if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Pull Out Weapon (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.PullOutWeapon.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.PullOutWeapon.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Put Away Weapon (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.PutAwayWeapon.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.PutAwayWeapon.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Combat Turn Left (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.TurnLeft.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type2Animations.TurnLeft.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.TurnLeft.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Combat Turn Right (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.TurnRight.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type2Animations.TurnRight.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.TurnRight.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Walk Backwards (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.WalkBack.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.mirror = EmeraldAnimationComponent.Type2Animations.WalkBack.Mirror;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.WalkBack.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Block (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.BlockIdle.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.BlockIdle.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Block Hit (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.BlockHit.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.BlockHit.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Warning (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.IdleWarning.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.IdleWarning.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Recoil (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.Recoil.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.Recoil.AnimationSpeed;
|
||||
}
|
||||
else if (m_AnimatorController.layers[0].stateMachine.states[i].state.name == "Stunned (Type 2)")
|
||||
{
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.motion = EmeraldAnimationComponent.Type2Animations.Stunned.AnimationClip;
|
||||
m_AnimatorController.layers[0].stateMachine.states[i].state.speed = EmeraldAnimationComponent.Type2Animations.Stunned.AnimationSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
//Get and assign Combat Movement Blend Tree animations
|
||||
AnimatorState m_StateMachine_Combat = m_AnimatorController.layers[0].stateMachine.states.ToList().Find(x => x.state.name == "Combat Movement (Type 2)").state;
|
||||
BlendTree CombatMovementBlendTree = m_StateMachine_Combat.motion as BlendTree;
|
||||
|
||||
var SerializedCombatIdleBlendTreeRef = new SerializedObject(CombatMovementBlendTree);
|
||||
var CombatMovementBlendTreeChildren = SerializedCombatIdleBlendTreeRef.FindProperty("m_Childs");
|
||||
|
||||
//Assign the Idle animation and settings to the Idle Blend Tree
|
||||
var CombatMovementMotionSlot1 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatMovementMotion1 = CombatMovementMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatIdleBlendTree = CombatMovementMotion1.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatIdleBlendTree = new SerializedObject(CombatIdleBlendTree);
|
||||
var CombatIdleBlendTreeChildren = SerializedCombatIdleBlendTree.FindProperty("m_Childs");
|
||||
var CombatIdleMotionSlot = CombatIdleBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatIdleAnimation = CombatIdleMotionSlot.FindPropertyRelative("m_Motion");
|
||||
var CombatIdleAnimationSpeed = CombatIdleMotionSlot.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type2Animations.IdleStationary.AnimationSpeed != 0) CombatIdleAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.IdleStationary.AnimationSpeed;
|
||||
CombatIdleAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.IdleStationary.AnimationClip;
|
||||
SerializedCombatIdleBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Walk animations and settings to the Walk Blend Tree; one for walk left, walk straight, and walk right.
|
||||
var CombatMovementMotionSlot2 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatMovementMotion2 = CombatMovementMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatWalkBlendTree = CombatMovementMotion2.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatWalkBlendTree = new SerializedObject(CombatWalkBlendTree);
|
||||
var CombatWalkBlendTreeChildren = SerializedCombatWalkBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Adjust the combat movement thresholds depending on which Animator Type is being used.
|
||||
var CombatWalkMovementMotionThreshold = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(1).FindPropertyRelative("m_Threshold");
|
||||
var CombatRunMovementMotionThreshold = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(2).FindPropertyRelative("m_Threshold");
|
||||
|
||||
SerializedCombatIdleBlendTreeRef.ApplyModifiedProperties();
|
||||
|
||||
//Walk Left
|
||||
var CombatWalkMotionSlot1 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatWalkLeftAnimation = CombatWalkMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkLeftAnimationSpeed = CombatWalkMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var CombatWalkLeftMirror = CombatWalkMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type2Animations.WalkLeft.AnimationSpeed != 0) CombatWalkLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.WalkLeft.AnimationSpeed;
|
||||
CombatWalkLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.WalkLeft.AnimationClip;
|
||||
CombatWalkLeftMirror.boolValue = EmeraldAnimationComponent.Type2Animations.WalkLeft.Mirror;
|
||||
|
||||
//Walk Straight
|
||||
var CombatWalkMotionSlot2 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatWalkStraightAnimation = CombatWalkMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkStraightAnimationSpeed = CombatWalkMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type2Animations.WalkForward.AnimationSpeed != 0) CombatWalkStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.WalkForward.AnimationSpeed;
|
||||
CombatWalkStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.WalkForward.AnimationClip;
|
||||
|
||||
//Walk Right
|
||||
var CombatWalkMotionSlot3 = CombatWalkBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatWalkRightAnimation = CombatWalkMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var CombatWalkRightAnimationSpeed = CombatWalkMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var CombatWalkRightMirror = CombatWalkMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type2Animations.WalkRight.AnimationSpeed != 0) CombatWalkRightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.WalkRight.AnimationSpeed;
|
||||
CombatWalkRightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.WalkRight.AnimationClip;
|
||||
CombatWalkRightMirror.boolValue = EmeraldAnimationComponent.Type2Animations.WalkRight.Mirror;
|
||||
|
||||
SerializedCombatWalkBlendTree.ApplyModifiedProperties();
|
||||
|
||||
//Assign the Run animations and settings to the Run Blend Tree; one for run left, run straight, and run right.
|
||||
var CombatMovementMotionSlot3 = CombatMovementBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatMovementMotion3 = CombatMovementMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
BlendTree CombatRunBlendTree = CombatMovementMotion3.objectReferenceValue as BlendTree;
|
||||
var SerializedCombatRunBlendTree = new SerializedObject(CombatRunBlendTree);
|
||||
var CombatRunBlendTreeChildren = SerializedCombatRunBlendTree.FindProperty("m_Childs");
|
||||
|
||||
//Run Left
|
||||
var CombatRunMotionSlot1 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(0);
|
||||
var CombatRunLeftAnimation = CombatRunMotionSlot1.FindPropertyRelative("m_Motion");
|
||||
var CombatRunLeftAnimationSpeed = CombatRunMotionSlot1.FindPropertyRelative("m_TimeScale");
|
||||
var CombatRunLeftMirror = CombatRunMotionSlot1.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type2Animations.RunLeft.AnimationSpeed != 0) CombatRunLeftAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.RunLeft.AnimationSpeed;
|
||||
CombatRunLeftAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.RunLeft.AnimationClip;
|
||||
CombatRunLeftMirror.boolValue = EmeraldAnimationComponent.Type2Animations.RunLeft.Mirror;
|
||||
|
||||
//Run Straight
|
||||
var CombatRunMotionSlot2 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(1);
|
||||
var CombatRunStraightAnimation = CombatRunMotionSlot2.FindPropertyRelative("m_Motion");
|
||||
var CombatRunStraightAnimationSpeed = CombatRunMotionSlot2.FindPropertyRelative("m_TimeScale");
|
||||
if (EmeraldAnimationComponent.Type2Animations.RunForward.AnimationSpeed != 0) CombatRunStraightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.RunForward.AnimationSpeed;
|
||||
CombatRunStraightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.RunForward.AnimationClip;
|
||||
|
||||
//Run Right
|
||||
var CombatRunMotionSlot3 = CombatRunBlendTreeChildren.GetArrayElementAtIndex(2);
|
||||
var CombatRunRightAnimation = CombatRunMotionSlot3.FindPropertyRelative("m_Motion");
|
||||
var CombatRunRightAnimationSpeed = CombatRunMotionSlot3.FindPropertyRelative("m_TimeScale");
|
||||
var CombatRunRightMirror = CombatRunMotionSlot3.FindPropertyRelative("m_Mirror");
|
||||
if (EmeraldAnimationComponent.Type2Animations.RunRight.AnimationSpeed != 0) CombatRunRightAnimationSpeed.floatValue = EmeraldAnimationComponent.Type2Animations.RunRight.AnimationSpeed;
|
||||
CombatRunRightAnimation.objectReferenceValue = EmeraldAnimationComponent.Type2Animations.RunRight.AnimationClip;
|
||||
CombatRunRightMirror.boolValue = EmeraldAnimationComponent.Type2Animations.RunRight.Mirror;
|
||||
|
||||
SerializedCombatRunBlendTree.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a05e831007417874e865416638622131
|
||||
timeCreated: 1539964285
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,39 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class EmeraldDefine
|
||||
{
|
||||
const string EmeraldAIDefinesString = "EMERALD_AI_2024_PRESENT";
|
||||
|
||||
static EmeraldDefine()
|
||||
{
|
||||
InitializeEmeraldAIDefines();
|
||||
}
|
||||
|
||||
static void InitializeEmeraldAIDefines()
|
||||
{
|
||||
var BTG = EditorUserBuildSettings.selectedBuildTargetGroup;
|
||||
string EmeraldAIDef = PlayerSettings.GetScriptingDefineSymbolsForGroup(BTG);
|
||||
|
||||
if (!EmeraldAIDef.Contains(EmeraldAIDefinesString))
|
||||
{
|
||||
if (string.IsNullOrEmpty(EmeraldAIDef))
|
||||
{
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BTG, EmeraldAIDefinesString);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (EmeraldAIDef[EmeraldAIDef.Length - 1] != ';')
|
||||
{
|
||||
EmeraldAIDef += ';';
|
||||
}
|
||||
|
||||
EmeraldAIDef += EmeraldAIDefinesString;
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(BTG, EmeraldAIDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cf756773aa684b4fb3bf2964f5b28c8
|
||||
timeCreated: 1519800001
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,991 @@
|
||||
using EmeraldAI.Utility;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// An easy and convenient way to access all practical API for Emerald AI through a static script. There's a class for each category of API. The EmeraldSystem of the AI is required for each function.
|
||||
/// </summary>
|
||||
public static class EmeraldAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains all usable Detection related API.
|
||||
/// </summary>
|
||||
public class Detection
|
||||
{
|
||||
/// <summary>
|
||||
/// Assigns a new follow target for an AI to follow. This will turn the AI into a Pet or Companion AI depending on its Behavior Type.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
/// <param name="CopyFactionData">Copies the Target to Follow's Faction Data so it will react the same way the follower does to detected targets. This requires the Target to Follow to be another AI (if this condition is not met, this parameter will be ignored).</param>
|
||||
public static void SetTargetToFollow(EmeraldSystem EmeraldComponent, Transform Target, bool CopyFactionData = true)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.SetTargetToFollow(Target, CopyFactionData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the AI's Target to Follow transform so it will be no longer following it. This will also stop the AI from being a Companion or Pet AI.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ClearTargetToFollow(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.ClearTargetToFollow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the player is currently within the AI's detection radius by returning true or false (this can be true even if the player is an enemy).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static bool CheckForPlayerDetection(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
return EmeraldComponent.CombatTarget != null && EmeraldComponent.CombatTarget.CompareTag(EmeraldComponent.DetectionComponent.PlayerTag) || EmeraldComponent.LookAtTarget != null && EmeraldComponent.LookAtTarget.CompareTag(EmeraldComponent.DetectionComponent.PlayerTag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all ignored targets from the static EmeraldDetection IgnoredTargetsList.
|
||||
/// </summary>
|
||||
public static void ClearAllIgnoredTargets()
|
||||
{
|
||||
EmeraldDetection.IgnoredTargetsList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the specified ignored target to the static EmeraldDetection IgnoredTargetsList.
|
||||
/// </summary>
|
||||
public static void SetIgnoredTarget(Transform TargetTransform)
|
||||
{
|
||||
if (!EmeraldDetection.IgnoredTargetsList.Contains(TargetTransform))
|
||||
{
|
||||
EmeraldDetection.IgnoredTargetsList.Add(TargetTransform);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the specified ignored target from the static EmeraldDetection IgnoredTargetsList.
|
||||
/// </summary>
|
||||
public static void ClearIgnoredTarget(Transform TargetTransform)
|
||||
{
|
||||
if (!EmeraldDetection.IgnoredTargetsList.Contains(TargetTransform))
|
||||
{
|
||||
Debug.Log("The TargetTransform did not exist in the EmeraldAISystem IgnoreTargetsList list.");
|
||||
return;
|
||||
}
|
||||
|
||||
EmeraldDetection.IgnoredTargetsList.Remove(TargetTransform);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Behaviors related API.
|
||||
/// </summary>
|
||||
public class Behaviors
|
||||
{
|
||||
/// <summary>
|
||||
/// Changes the AI's current behavior to the one specified. By default, the internal BehaviorState is set back to its default "Non Combat" which will then allow the AI to update its current state based on its new behavior.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ChangeBehavior (EmeraldSystem EmeraldComponent, EmeraldBehaviors.BehaviorTypes BehaviorType)
|
||||
{
|
||||
EmeraldComponent.BehaviorsComponent.CurrentBehaviorType = BehaviorType;
|
||||
EmeraldComponent.BehaviorsComponent.BehaviorState = "Non Combat";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Combat related API.
|
||||
/// </summary>
|
||||
public class Combat
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantly kills this AI.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void KillAI(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (!EmeraldComponent.AnimationComponent.IsDead)
|
||||
{
|
||||
EmeraldComponent.HealthComponent.Damage(9999999);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the AI so it can be reused (typically called after an AI has been killed). This is automatically called when an AI is killed and then re-enabled.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ResetAI(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.HealthComponent.InstantlyRefillAIHealth();
|
||||
EmeraldCombatManager.EnableComponents(EmeraldComponent);
|
||||
EmeraldComponent.AnimationComponent.IsDead = false;
|
||||
EmeraldCombatManager.DisableRagdoll(EmeraldComponent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current distance between the AI and their combat target (Returns -1 if the Combat Target is null).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static float GetDistanceFromTarget(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (EmeraldComponent.CombatTarget != null)
|
||||
{
|
||||
return EmeraldComponent.CombatComponent.DistanceFromTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("This AI's Combat Target is null");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the AI's combat target.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static Transform GetCombatTarget(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
return EmeraldComponent.CombatTarget;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a specified combat target for your AI to attack within the AI's Detection Radius. Note: Targets outside of an AI's Detection Radius will be ignored. If you want no distance limitations, use OverrideCombatTarget(Transform Target).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SetCombatTarget(EmeraldSystem EmeraldComponent, Transform Target)
|
||||
{
|
||||
if (EmeraldComponent.BehaviorsComponent.CurrentBehaviorType != EmeraldBehaviors.BehaviorTypes.Aggressive) return;
|
||||
|
||||
if (Target != null)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.SetDetectedTarget(Target);
|
||||
EmeraldComponent.m_NavMeshAgent.ResetPath();
|
||||
EmeraldComponent.m_NavMeshAgent.stoppingDistance = EmeraldComponent.CombatComponent.AttackDistance;
|
||||
EmeraldComponent.m_NavMeshAgent.destination = Target.position;
|
||||
}
|
||||
else if (Target == null)
|
||||
{
|
||||
Debug.Log("The SetCombatTarget paramter is null. Ensure that the target exists before calling this function.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assigns a specified combat target for your AI to attack ignoring any distance limitations. If the target is not within attacking range, the AI will move to the target's position and attack based on its attack distance, even if it is outside of its detection radius.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void OverrideCombatTarget(EmeraldSystem EmeraldComponent, Transform Target)
|
||||
{
|
||||
if (EmeraldComponent.BehaviorsComponent.CurrentBehaviorType != EmeraldBehaviors.BehaviorTypes.Aggressive) return;
|
||||
|
||||
if (Target != null)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.SetDetectedTarget(Target);
|
||||
EmeraldComponent.m_NavMeshAgent.ResetPath();
|
||||
EmeraldComponent.m_NavMeshAgent.stoppingDistance = EmeraldComponent.CombatComponent.AttackDistance;
|
||||
EmeraldComponent.m_NavMeshAgent.destination = Target.position;
|
||||
EmeraldComponent.BehaviorsComponent.InfititeChase = true;
|
||||
}
|
||||
else if (Target == null)
|
||||
{
|
||||
Debug.Log("The OverrideCombatTarget paramter is null. Ensure that the target exists before calling this function.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes an AI flee from the specified target by switching their behavior to Coward. The AI will remain with the Coward until it is reset manually.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void FleeFromTarget(EmeraldSystem EmeraldComponent, Transform FleeTarget)
|
||||
{
|
||||
if (FleeTarget != null)
|
||||
{
|
||||
EmeraldComponent.BehaviorsComponent.CurrentBehaviorType = EmeraldBehaviors.BehaviorTypes.Coward;
|
||||
EmeraldComponent.DetectionComponent.SetDetectedTarget(FleeTarget);
|
||||
}
|
||||
else if (FleeTarget == null)
|
||||
{
|
||||
Debug.Log("The FleeTarget paramter is null. Ensure that the target exists before calling this function.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a new target within the AI's Detection Radius closest to the AI.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SearchForClosestTarget(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.SearchForTarget(PickTargetTypes.Closest);
|
||||
EmeraldComponent.DetectionComponent.SetDetectedTarget(EmeraldComponent.CombatTarget);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Searches for a new random target within the AI's Detection Radius.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SearchForRandomTarget(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.SearchForTarget(PickTargetTypes.Random);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the transform that last attacked the AI.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static Transform GetLastAttacker(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
return EmeraldComponent.CombatComponent.LastAttacker;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Health related API.
|
||||
/// </summary>
|
||||
public class Health
|
||||
{
|
||||
/// <summary>
|
||||
/// Instantly heals this AI back to full health.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void InstantlyRefillAIHealth(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (!EmeraldComponent.AnimationComponent.IsDead)
|
||||
{
|
||||
EmeraldComponent.HealthComponent.InstantlyRefillAIHealth();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's Current and Max Health.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateHealth(EmeraldSystem EmeraldComponent, int MaxHealth, int CurrentHealth)
|
||||
{
|
||||
if (!EmeraldComponent.AnimationComponent.IsDead)
|
||||
{
|
||||
EmeraldComponent.HealthComponent.UpdateHealth(MaxHealth, CurrentHealth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Faction related API.
|
||||
/// </summary>
|
||||
public class Faction
|
||||
{
|
||||
/// <summary>
|
||||
/// Changes the relation of the given faction. Note: The faction must be available in the AI's faction list.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
/// <param name="Faction"> The name of the faction to change.</param>
|
||||
/// <param name="FactionLevel">The level to set the faction to typed as a string. The options are Enemy, Neutral, or Friendly</param>
|
||||
public static void SetFactionLevel(EmeraldSystem EmeraldComponent, string Faction, RelationTypes RelationType)
|
||||
{
|
||||
EmeraldFactionData FactionData = Resources.Load("Faction Data") as EmeraldFactionData;
|
||||
|
||||
for (int i = 0; i < EmeraldComponent.DetectionComponent.FactionRelationsList.Count; i++)
|
||||
{
|
||||
if (EmeraldComponent.DetectionComponent.FactionRelationsList[i].FactionIndex == FactionData.FactionNameList.IndexOf(Faction))
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.FactionRelationsList[i].RelationType = RelationType;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("The faction '" + Faction + "' does not exist in the AI's Faction Relations list. Please add it using the Faction Settings Foldout through the Emerald Detection editor of this AI.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the Faction and Faction Relation to the AI's Faction Relations List. Note: The faction must exist within the Emerald Faction Manager's Faction List.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
/// <param name="Faction"> The name of the faction to change.</param>
|
||||
/// <param name="FactionLevel">The level to set the faction to typed as a string. The options are Enemy, Neutral, or Friendly</param>
|
||||
public static void AddFactionRelation(EmeraldSystem EmeraldComponent, string Faction, RelationTypes RelationType)
|
||||
{
|
||||
EmeraldFactionData FactionData = Resources.Load("Faction Data") as EmeraldFactionData;
|
||||
|
||||
if (!EmeraldDetection.FactionData.FactionNameList.Contains(Faction))
|
||||
{
|
||||
Debug.Log("The faction '" + Faction + "' does not exist in the Faction Manager. Please add it using the Emerald Faction Manager.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < EmeraldComponent.DetectionComponent.FactionRelationsList.Count; i++)
|
||||
{
|
||||
if (EmeraldComponent.DetectionComponent.FactionRelationsList[i].FactionIndex == FactionData.FactionNameList.IndexOf(Faction))
|
||||
{
|
||||
Debug.Log("This AI already contains the faction '" + Faction + "'. If you would like to modify an AI's existing faction, please use SetFactionLevel(string Faction, RelationTypes RelationType) instead.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EmeraldComponent.DetectionComponent.FactionRelationsList.Add(new FactionClass(FactionData.FactionNameList.IndexOf(Faction), (int)RelationType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the relation of the passed target and this AI in the form of a string (Enemy, Neutral, or Friendly). If a faction cannot be found, or if it is not a valid target, you will receive a value of Invalid Target.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static string GetTargetFactionRelation(EmeraldSystem EmeraldComponent, Transform Target)
|
||||
{
|
||||
IFaction m_IFaction = Target.GetComponent<IFaction>();
|
||||
|
||||
if (m_IFaction != null)
|
||||
{
|
||||
int ReceivedFaction = m_IFaction.GetFaction();
|
||||
if (EmeraldComponent.DetectionComponent.AIFactionsList.Contains(ReceivedFaction))
|
||||
{
|
||||
var Faction = (RelationTypes)EmeraldComponent.DetectionComponent.FactionRelations[EmeraldComponent.DetectionComponent.AIFactionsList.IndexOf(ReceivedFaction)];
|
||||
return Faction.ToString();
|
||||
}
|
||||
else return "Invalid Target";
|
||||
}
|
||||
else return "Invalid Target";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the faction name of the passed AI target. The AI's own transform can also be passed to get its own faction name.
|
||||
/// </summary>
|
||||
public static string GetTargetFactionName(Transform Target)
|
||||
{
|
||||
IFaction m_IFaction = Target.GetComponent<IFaction>();
|
||||
|
||||
if (m_IFaction != null)
|
||||
{
|
||||
int ReceivedFaction = m_IFaction.GetFaction();
|
||||
return EmeraldDetection.FactionData.FactionNameList[ReceivedFaction];
|
||||
}
|
||||
else return "Invalid Target";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the AI's faction (Note: The FactionName must exists within the Faction Manager's Current Faction list).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ChangeFaction(EmeraldSystem EmeraldComponent, string FactionName)
|
||||
{
|
||||
EmeraldFactionData FactionData = Resources.Load("Faction Data") as EmeraldFactionData;
|
||||
|
||||
if (FactionData.FactionNameList.Contains(FactionName))
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.CurrentFaction = FactionData.FactionNameList.IndexOf(FactionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Faction not Found");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies all faction data from the FactionDataToCopy and applies it to the EmeraldComponent. This is the AI Faction Relations List (within the Faction Settings foldout of the Detection Component).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call and receive the FactionDataToCopy AI's faction data.</param>
|
||||
public static void CopyFactionData(EmeraldSystem EmeraldComponent, EmeraldSystem FactionDataToCopy)
|
||||
{
|
||||
EmeraldComponent.DetectionComponent.CurrentFaction = FactionDataToCopy.DetectionComponent.CurrentFaction;
|
||||
EmeraldComponent.DetectionComponent.AIFactionsList = FactionDataToCopy.DetectionComponent.AIFactionsList;
|
||||
EmeraldComponent.DetectionComponent.FactionRelations = FactionDataToCopy.DetectionComponent.FactionRelations;
|
||||
EmeraldComponent.DetectionComponent.FactionRelationsList = FactionDataToCopy.DetectionComponent.FactionRelationsList;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Movement related API.
|
||||
/// </summary>
|
||||
public class Movement
|
||||
{
|
||||
/// <summary>
|
||||
/// Changes the AI's Wander Type. If the Dynamic Wander Type is used, the AI's current position will be updated as the AI's new starting position, which is used by the Dynamic Wander position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ChangeWanderType(EmeraldSystem EmeraldComponent, EmeraldMovement.WanderTypes NewWanderType)
|
||||
{
|
||||
if (NewWanderType == EmeraldMovement.WanderTypes.Dynamic) UpdateDynamicWanderPosition(EmeraldComponent);
|
||||
EmeraldComponent.MovementComponent.ChangeWanderType(NewWanderType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's dynamic wandering position to the AI's current position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateDynamicWanderPosition(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.StartingDestination = EmeraldComponent.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the AI's dynamic wandering position to the position of the Destination transform.
|
||||
/// This is useful for functionality such as custom AI schedules. Note: This will automatically change
|
||||
/// your AI's Wander Type to Dynamic.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SetDynamicWanderPosition(EmeraldSystem EmeraldComponent, Vector3 DestinationPosition)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.ChangeWanderType(EmeraldMovement.WanderTypes.Dynamic);
|
||||
EmeraldComponent.MovementComponent.StartingDestination = DestinationPosition;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's starting position to the AI's current position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateStartingPosition(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.StartingDestination = EmeraldComponent.transform.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the AI's Wander Type to Custom and sets the AI's destination to the Vector3 position. This is useful functionality like point and click movement, schedules, and more.
|
||||
/// Because this modifies the AI's Wander Type, the ChangeWanderType function will need to be called again to set the desired Wander Type, if something other than Custom is wanted.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SetCustomDestination(EmeraldSystem EmeraldComponent, Vector3 DestinationPosition)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.ResetWanderSettings();
|
||||
if (EmeraldComponent.MovementComponent.WanderType != EmeraldMovement.WanderTypes.Custom) ChangeWanderType(EmeraldComponent, EmeraldMovement.WanderTypes.Custom);
|
||||
EmeraldComponent.m_NavMeshAgent.SetDestination(DestinationPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the AI's destination to the Vector3 position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void SetDestination(EmeraldSystem EmeraldComponent, Vector3 DestinationPosition)
|
||||
{
|
||||
EmeraldComponent.m_NavMeshAgent.SetDestination(DestinationPosition);
|
||||
EmeraldComponent.MovementComponent.ResetWanderSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new position to move to within the specified radius based on the AI's current position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void GenerateRandomDestination(EmeraldSystem EmeraldComponent, int Radius)
|
||||
{
|
||||
Vector3 NewDestination = EmeraldComponent.transform.position + new Vector3(Random.insideUnitSphere.y, 0, Random.insideUnitSphere.z) * Radius;
|
||||
RaycastHit HitDown;
|
||||
if (Physics.Raycast(new Vector3(NewDestination.x, NewDestination.y + 5, NewDestination.z), -EmeraldComponent.transform.up, out HitDown, 10, EmeraldComponent.MovementComponent.DynamicWanderLayerMask, QueryTriggerInteraction.Ignore))
|
||||
{
|
||||
UnityEngine.AI.NavMeshHit hit;
|
||||
if (UnityEngine.AI.NavMesh.SamplePosition(NewDestination, out hit, 4, EmeraldComponent.m_NavMeshAgent.areaMask))
|
||||
{
|
||||
EmeraldComponent.m_NavMeshAgent.SetDestination(NewDestination);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a waypoint to an AI's Waypoint List.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void AddWaypoint(EmeraldSystem EmeraldComponent, Transform Waypoint)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.WaypointsList.Add(Waypoint.position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a waypoint from the AI's Waypoint List according to the specified index.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void RemoveWaypoint(EmeraldSystem EmeraldComponent, int WaypointIndex)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.WaypointsList.RemoveAt(WaypointIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all of an AI's current waypoints. Note: When an AI's waypoints are cleared, it will be set to the Stationary wander type to avoid an error.
|
||||
/// If you want the AI to follow newly created waypoints, you will need to set its Wander Type back to Waypoint with the ChangeWanderType function (located at EmeraldAPI.Movement.ChangeWanderType).
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ClearAllWaypoints(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.WanderType = EmeraldMovement.WanderTypes.Stationary;
|
||||
EmeraldComponent.MovementComponent.WaypointsList.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops an AI from moving when out of combat. This is useful for functionality like dialogue.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void StopMovement(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.m_NavMeshAgent.ResetPath();
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = true;
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes an AI's movement after using the StopMovement function.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ResumeMovement(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.DefaultMovement();
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = false;
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops an AI with a follow target from following. This will only work if an AI has a Current Follow Target.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void StopFollowing(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (EmeraldComponent.TargetToFollow == null)
|
||||
{
|
||||
Debug.LogError("The '" + EmeraldComponent.gameObject.name + "' does not have a Current Follow Target. Please have one before calling this function.");
|
||||
return;
|
||||
}
|
||||
|
||||
EmeraldComponent.m_NavMeshAgent.ResetPath();
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = true;
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows an AI with a follow target to resume following its follower. This will only work if an AI has a Current Follow Target.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ResumeFollowing(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (EmeraldComponent.TargetToFollow == null)
|
||||
{
|
||||
Debug.LogError("The '" + EmeraldComponent.gameObject.name + "' does not have a Current Follow Target. Please have one before calling this function.");
|
||||
return;
|
||||
}
|
||||
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = false;
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a Companion AI (an AI with Follow Target) to guard the assigned position.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void StartCompanionGuardPosition(EmeraldSystem EmeraldComponent, Vector3 PositionToGuard)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = true;
|
||||
EmeraldComponent.m_NavMeshAgent.SetDestination(PositionToGuard);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops a Companion AI (an AI with Follow Target) from guarding and returns it to their current follower.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void StopCompanionGuardPosition(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rotates the AI towards the specified target position using the AI's turning animations. The angle in which the AI will stop rotating is based off of an AI's Turning Angle set within the Emerald Movement Component editor.
|
||||
/// The AI will be unable to move during the duration of the turning process. If an AI is wandering, it is recommended that StopMovement is called first to stop an AI from wandering as an AI can still wander after the rotating has finished.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
/// <param name="TargetPosition">The position the AI will rotate towards. This can be an object, a player, another AI, a custom position, etc.</param>
|
||||
public static void RotateTowardsPosition(EmeraldSystem EmeraldComponent, Vector3 TargetPosition)
|
||||
{
|
||||
EmeraldComponent.GetComponent<MonoBehaviour>().StartCoroutine(RotateTowardsPositionInternal(EmeraldComponent, TargetPosition));
|
||||
}
|
||||
|
||||
static IEnumerator RotateTowardsPositionInternal(EmeraldSystem EmeraldComponent, Vector3 TargetPosition)
|
||||
{
|
||||
if (EmeraldComponent.MovementComponent.RotateTowardsTarget) yield break; //Don't allow the AI to rotate towards the TargetPosition if it's already doing so
|
||||
|
||||
EmeraldComponent.MovementComponent.RotateTowardsTarget = true; //Stops certain functionality while in this state
|
||||
EmeraldComponent.MovementComponent.LockTurning = false; //This is used for preventing an AI from getting stuck between two turn animations
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = true; //Stop the AI's NavMesh
|
||||
yield return new WaitForSeconds(0.1f); //Add a delay so the changes above aren't missed
|
||||
|
||||
while (!EmeraldComponent.MovementComponent.LockTurning)
|
||||
{
|
||||
Vector3 Direction = new Vector3(TargetPosition.x, 0, TargetPosition.z) - new Vector3(EmeraldComponent.transform.position.x, 0, EmeraldComponent.transform.position.z);
|
||||
EmeraldComponent.MovementComponent.UpdateRotations(Direction);
|
||||
EmeraldComponent.AnimationComponent.CalculateTurnAnimations(true);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
EmeraldComponent.MovementComponent.RotateTowardsTarget = false;
|
||||
EmeraldComponent.m_NavMeshAgent.isStopped = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Animation related API.
|
||||
/// </summary>
|
||||
public class Animation
|
||||
{
|
||||
/// <summary>
|
||||
/// Plays an emote animation according to the EmoteAnimationID parameter (from the AI's Emote Animation List). Note: This function will only work if
|
||||
/// an AI is not in active combat mode.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayEmoteAnimation(EmeraldSystem EmeraldComponent, int EmoteAnimationID)
|
||||
{
|
||||
EmeraldComponent.AnimationComponent.PlayEmoteAnimation(EmoteAnimationID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loops an emote animation according to the EmoteAnimationID parameter (from the AI's Emote Animation List).
|
||||
/// StopLoopEmoteAnimation must be called for the animation to stop playing. Note: This function will only work if an AI is not in active combat mode.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void LoopEmoteAnimation(EmeraldSystem EmeraldComponent, int EmoteAnimationID)
|
||||
{
|
||||
EmeraldComponent.AnimationComponent.LoopEmoteAnimation(EmoteAnimationID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops an emote animation from looping using the EmoteAnimationID parameter (from the AI's Emote Animation List). Note: This function will only work if an AI is not in active combat mode.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void StopLoopEmoteAnimation(EmeraldSystem EmeraldComponent, int EmoteAnimationID)
|
||||
{
|
||||
EmeraldComponent.AnimationComponent.StopLoopEmoteAnimation(EmoteAnimationID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually sets the AI's next Idle animation instead of being generated randomly. This is useful for functionality such as playing a particular idle animation
|
||||
/// at a certain location such as for an AI's schedule. Note: The animation numbers are from 1 to 6 and must exist in your AI's Idle Animation list. You must call
|
||||
/// DisableOverrideIdleAnimation() to have idle animations randomly generate again and to disable this feature.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void OverrideIdleAnimation(EmeraldSystem EmeraldComponent, int IdleIndex)
|
||||
{
|
||||
EmeraldComponent.AnimationComponent.m_IdleAnimaionIndexOverride = true;
|
||||
EmeraldComponent.AIAnimator.SetInteger("Idle Index", IdleIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables the OverrideIdleAnimation feature.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void DisableOverrideIdleAnimation(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.AnimationComponent.m_IdleAnimaionIndexOverride = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Sound related API.
|
||||
/// </summary>
|
||||
public class Sound
|
||||
{
|
||||
/// <summary>
|
||||
/// Plays a sound clip according to the Clip parameter.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlaySoundClip(EmeraldSystem EmeraldComponent, AudioClip Clip)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlaySoundClip(Clip);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random attack sound based on your AI's Attack Sounds list. Can also be called through Animation Events.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayIdleSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayIdleSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random attack sound based on your AI's Attack Sounds list. Can also be called through Animation Events.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayAttackSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayAttackSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random attack sound based on your AI's Attack Sounds list. Can also be called through Animation Events.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayWarningSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayWarningSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random block sound based on your AI's Block Sounds list.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayBlockSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayBlockSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random injured sound based on your AI's Injured Sounds list.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayInjuredSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayInjuredSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random death sound based on your AI's Death Sounds list. Can also be called through Animation Events.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayDeathSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayDeathSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a footstep sound from the AI's Footstep Sounds list to use when the AI is walking. This should be setup through an Animation Event.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void WalkFootstepSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.WalkFootstepSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a footstep sound from the AI's Footstep Sounds list to use when the AI is running. This should be setup through an Animation Event.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void RunFootstepSound(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.RunFootstepSound();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a random sound effect from the AI's General Sounds list.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlayRandomSoundEffect(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlayRandomSoundEffect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays a sound effect from the AI's General Sounds list using the Sound Effect ID as the parameter.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void PlaySoundEffect(EmeraldSystem EmeraldComponent, int SoundEffectID)
|
||||
{
|
||||
EmeraldComponent.SoundComponent.PlaySoundEffect(SoundEffectID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable UI related API (Requires EmeraldUI component).
|
||||
/// </summary>
|
||||
public class UI
|
||||
{
|
||||
/// <summary>
|
||||
/// Updates the AI's Health Bar color.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateUIHealthBarColor(EmeraldSystem EmeraldComponent, Color NewColor)
|
||||
{
|
||||
CheckForUIComponent(EmeraldComponent); //Checks that the EmeraldUI component exists
|
||||
|
||||
if (EmeraldComponent.UIComponent.AutoCreateHealthBars == YesOrNo.Yes)
|
||||
{
|
||||
GameObject HealthBarChild = EmeraldComponent.UIComponent.HealthBar.transform.Find("AI Health Bar Background").gameObject;
|
||||
UnityEngine.UI.Image HealthBarRef = HealthBarChild.transform.Find("AI Health Bar").GetComponent<UnityEngine.UI.Image>();
|
||||
HealthBarRef.color = NewColor;
|
||||
UnityEngine.UI.Image HealthBarBackgroundImageRef = HealthBarChild.GetComponent<UnityEngine.UI.Image>();
|
||||
HealthBarBackgroundImageRef.color = EmeraldComponent.UIComponent.HealthBarBackgroundColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's Health Bar Background color.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateUIHealthBarBackgroundColor(EmeraldSystem EmeraldComponent, Color NewColor)
|
||||
{
|
||||
CheckForUIComponent(EmeraldComponent); //Checks that the EmeraldUI component exists
|
||||
|
||||
if (EmeraldComponent.UIComponent.AutoCreateHealthBars == YesOrNo.Yes)
|
||||
{
|
||||
GameObject HealthBarChild = EmeraldComponent.UIComponent.HealthBar.transform.Find("AI Health Bar Background").gameObject;
|
||||
UnityEngine.UI.Image HealthBarBackgroundImageRef = HealthBarChild.GetComponent<UnityEngine.UI.Image>();
|
||||
HealthBarBackgroundImageRef.color = NewColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's Name color
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateUINameColor(EmeraldSystem EmeraldComponent, Color NewColor)
|
||||
{
|
||||
CheckForUIComponent(EmeraldComponent); //Checks that the EmeraldUI component exists
|
||||
|
||||
if (EmeraldComponent.UIComponent.AutoCreateHealthBars == YesOrNo.Yes && EmeraldComponent.UIComponent.DisplayAIName == YesOrNo.Yes)
|
||||
{
|
||||
EmeraldComponent.UIComponent.AINameUI.color = NewColor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's Name text
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void UpdateUINameText(EmeraldSystem EmeraldComponent, string NewName)
|
||||
{
|
||||
CheckForUIComponent(EmeraldComponent); //Checks that the EmeraldUI component exists
|
||||
|
||||
if (EmeraldComponent.UIComponent.AutoCreateHealthBars == YesOrNo.Yes && EmeraldComponent.UIComponent.DisplayAIName == YesOrNo.Yes)
|
||||
{
|
||||
EmeraldComponent.UIComponent.AINameUI.text = NewName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that the EmeraldUI component exists.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
static void CheckForUIComponent (EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (EmeraldComponent.UIComponent == null)
|
||||
{
|
||||
Debug.LogError("The '" + EmeraldComponent.name + "' AI does not have a EmeraldUI component. Please attach one to said AI before calling this function.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains all usable Items related API (Requires EmeraldItems component).
|
||||
/// </summary>
|
||||
public class Items
|
||||
{
|
||||
/// <summary>
|
||||
/// Enables an item from your AI's Item list using the Item ID.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void EnableItem(EmeraldSystem EmeraldComponent, int ItemID)
|
||||
{
|
||||
CheckForItemsComponent(EmeraldComponent); //Checks that the EmeraldItems component exists
|
||||
EmeraldComponent.ItemsComponent.EnableItem(ItemID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables an item from your AI's Item list using the Item ID.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void DisableItem(EmeraldSystem EmeraldComponent, int ItemID)
|
||||
{
|
||||
CheckForItemsComponent(EmeraldComponent); //Checks that the EmeraldItems component exists
|
||||
EmeraldComponent.ItemsComponent.DisableItem(ItemID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables all items from your AI's Item list.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void DisableAllItems(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
CheckForItemsComponent(EmeraldComponent); //Checks that the EmeraldItems component exists
|
||||
EmeraldComponent.ItemsComponent.DisableAllItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset any equipped items to their defaults.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
public static void ResetSettings(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
CheckForItemsComponent(EmeraldComponent); //Checks that the EmeraldItems component exists
|
||||
EmeraldComponent.ItemsComponent.ResetSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks that the EmeraldItems component exists.
|
||||
/// </summary>
|
||||
/// <param name="EmeraldComponent"> The AI's EmeraldSystem who will use this API call.</param>
|
||||
static void CheckForItemsComponent(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
if (EmeraldComponent.ItemsComponent == null)
|
||||
{
|
||||
Debug.LogError("The '" + EmeraldComponent.name + "' AI does not have a EmeraldItems component. Please attach one to said AI before calling this function.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains internal API that is used for specific internal mechanics. It is not recommended to be used directly.
|
||||
/// </summary>
|
||||
public class Internal
|
||||
{
|
||||
public static void GenerateRandomPositionWithinRadius(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
//Return if the CombatTarget is null (which can happen if the CombatTarget gets cleared rght before this function gets called).
|
||||
if (EmeraldComponent.CombatTarget == null) return;
|
||||
|
||||
EmeraldComponent.CombatComponent.CancelAllCombatActions();
|
||||
EmeraldComponent.MovementComponent.StopBackingUp();
|
||||
EmeraldComponent.m_NavMeshAgent.stoppingDistance = 0.5f;
|
||||
int Radius = Random.Range(2, 5);
|
||||
|
||||
Vector3 Dir = (EmeraldComponent.CombatTarget.position - EmeraldComponent.transform.position).normalized;
|
||||
int OffsetAmount = Random.Range(1, 3);
|
||||
var DirectionOffset = Quaternion.Euler(0, OffsetAmount == 1 ? -50 : 50, 0) * Dir;
|
||||
Vector3 GeneratedDestination = EmeraldComponent.CombatTarget.position + (DirectionOffset * Radius);
|
||||
|
||||
RaycastHit HitDown;
|
||||
if (Physics.Raycast(GeneratedDestination + Vector3.up * 2, -Vector3.up, out HitDown, 5f))
|
||||
{
|
||||
GeneratedDestination.y = HitDown.point.y;
|
||||
}
|
||||
|
||||
EmeraldComponent.m_NavMeshAgent.destination = GeneratedDestination;
|
||||
EmeraldComponent.GetComponent<MonoBehaviour>().StartCoroutine(Moving(EmeraldComponent));
|
||||
}
|
||||
|
||||
static IEnumerator Moving(EmeraldSystem EmeraldComponent)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = true;
|
||||
yield return new WaitForSeconds(0.25f);
|
||||
float CanSeeTargetTimer = 0;
|
||||
|
||||
while (EmeraldComponent.m_NavMeshAgent.enabled && !EmeraldComponent.AnimationComponent.IsDead && EmeraldComponent.m_NavMeshAgent.remainingDistance >= 0.75f && CanSeeTargetTimer < 1)
|
||||
{
|
||||
if (EmeraldComponent.DetectionComponent.ObstructionType == EmeraldDetection.ObstructedTypes.None)
|
||||
{
|
||||
CanSeeTargetTimer += Time.deltaTime;
|
||||
}
|
||||
|
||||
EmeraldComponent.m_NavMeshAgent.stoppingDistance = 0.5f;
|
||||
Vector3 Direction = new Vector3(EmeraldComponent.m_NavMeshAgent.steeringTarget.x, 0, EmeraldComponent.m_NavMeshAgent.steeringTarget.z) - new Vector3(EmeraldComponent.transform.position.x, 0, EmeraldComponent.transform.position.z);
|
||||
EmeraldComponent.MovementComponent.UpdateRotations(Direction);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (!EmeraldComponent.m_NavMeshAgent.enabled || EmeraldComponent.AnimationComponent.IsDead)
|
||||
{
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = false;
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
float t = 0;
|
||||
|
||||
while (t < 1f && EmeraldComponent.CombatTarget != null)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
|
||||
Vector3 Direction = new Vector3(EmeraldComponent.CombatTarget.position.x, 0, EmeraldComponent.CombatTarget.position.z) - new Vector3(EmeraldComponent.transform.position.x, 0, EmeraldComponent.transform.position.z);
|
||||
EmeraldComponent.MovementComponent.UpdateRotations(Direction);
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
EmeraldComponent.MovementComponent.DefaultMovementPaused = false;
|
||||
EmeraldComponent.m_NavMeshAgent.stoppingDistance = EmeraldComponent.CombatComponent.AttackDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c475d05c5e69d6148af8aa299ecc27f9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class EmeraldDamageOverTime : MonoBehaviour
|
||||
{
|
||||
float DamageTimer;
|
||||
float ActiveLengthTimer;
|
||||
EmeraldAbilityObject m_AbilityObject;
|
||||
AudioSource m_AudioSource;
|
||||
Transform m_TargetTransform;
|
||||
Transform m_AttackerTransform;
|
||||
|
||||
float TickRate;
|
||||
int DamagePerTick;
|
||||
float DamageOverTimeLength;
|
||||
GameObject DamageOverTimeEffect;
|
||||
float OverTimeEffectTimeOutSeconds;
|
||||
AudioClip DamageOverTimeSound;
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_AudioSource = gameObject.AddComponent<AudioSource>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiaizes the damage over time component.
|
||||
/// </summary>
|
||||
public void Initialize(EmeraldAbilityObject AbilityObject, AbilityData.DamageData DamageData, Transform TargetTransform, Transform AttackerTransform)
|
||||
{
|
||||
DamageTimer = 0;
|
||||
ActiveLengthTimer = 0;
|
||||
m_TargetTransform = TargetTransform;
|
||||
m_AttackerTransform = AttackerTransform;
|
||||
m_AbilityObject = AbilityObject;
|
||||
|
||||
TickRate = DamageData.DamageOverTimeSettings.TickRate;
|
||||
DamagePerTick = DamageData.DamageOverTimeSettings.DamagePerTick;
|
||||
DamageOverTimeEffect = DamageData.DamageOverTimeSettings.DamageOverTimeEffect;
|
||||
DamageOverTimeLength = DamageData.DamageOverTimeSettings.DamageOverTimeLength;
|
||||
OverTimeEffectTimeOutSeconds = DamageData.DamageOverTimeSettings.OverTimeEffectTimeOutSeconds;
|
||||
if (DamageData.DamageOverTimeSettings.OverTimeSounds.Count > 0) DamageOverTimeSound = DamageData.DamageOverTimeSettings.OverTimeSounds[Random.Range(0, DamageData.DamageOverTimeSettings.OverTimeSounds.Count)];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the EmeraldAIDamageOverTime timers.
|
||||
/// </summary>
|
||||
void Update()
|
||||
{
|
||||
DamageTimer += Time.deltaTime;
|
||||
ActiveLengthTimer += Time.deltaTime;
|
||||
|
||||
if (ActiveLengthTimer >= DamageOverTimeLength + 0.05f)
|
||||
{
|
||||
IDamageableHelper.RemoveAbilityActiveEffect(m_TargetTransform.gameObject, m_AbilityObject); //Removes the current projectile from the target's active effects list.
|
||||
|
||||
if (!m_AudioSource.isPlaying)
|
||||
{
|
||||
EmeraldObjectPool.Despawn(gameObject); //Despawn the EmeraldAIDamageOverTime component.
|
||||
}
|
||||
}
|
||||
|
||||
if (DamageTimer >= TickRate && ActiveLengthTimer <= DamageOverTimeLength + 0.05f)
|
||||
{
|
||||
DamageTarget(); //Damage the target once the DamageTimer is equal to the AbilityDamageIncrement.
|
||||
DamageTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Damage the target through its IDamageable using the current Ability Object data.
|
||||
/// </summary>
|
||||
void DamageTarget ()
|
||||
{
|
||||
var m_IDamageable = m_TargetTransform.GetComponent<IDamageable>();
|
||||
var m_ICombat = m_TargetTransform.GetComponent<ICombat>();
|
||||
|
||||
if (m_IDamageable != null && m_ICombat != null)
|
||||
{
|
||||
//Damage the m_TargetTransform through its IDamageable component.
|
||||
m_IDamageable.Damage(DamagePerTick, m_AttackerTransform, 50, false);
|
||||
|
||||
//Spawn the DamageOverTimeEffect based on the m_IDamageable position.
|
||||
if (DamageOverTimeEffect != null)
|
||||
{
|
||||
EmeraldObjectPool.SpawnEffect(DamageOverTimeEffect, m_ICombat.DamagePosition(), Quaternion.identity, OverTimeEffectTimeOutSeconds);
|
||||
}
|
||||
|
||||
//Play the DamageOverTimeSound.
|
||||
if (DamageOverTimeSound != null)
|
||||
{
|
||||
m_AudioSource.PlayOneShot(DamageOverTimeSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a5c9e0937288c5439ecaba194c20f1e
|
||||
timeCreated: 1563245805
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[System.Serializable]
|
||||
public class EmeraldFactionData : ScriptableObject
|
||||
{
|
||||
[SerializeField]
|
||||
public List<string> FactionNameList = new List<string>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2c73612b71f812045a5fe04ece2df09b
|
||||
timeCreated: 1579729800
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,199 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class EmeraldHealthBar : MonoBehaviour
|
||||
{
|
||||
#region Health Bar Variables
|
||||
Camera m_Camera;
|
||||
Canvas canvas;
|
||||
Image HealthBar;
|
||||
Image HealthBarDamage;
|
||||
CanvasGroup CG;
|
||||
Text AINameUI;
|
||||
Text AILevelUI;
|
||||
Coroutine C;
|
||||
EmeraldSystem EmeraldComponent;
|
||||
EmeraldUI EmeraldUI;
|
||||
EmeraldHealth EmeraldHeath;
|
||||
Coroutine CoroutineTransitionDamage;
|
||||
#endregion
|
||||
|
||||
void Start()
|
||||
{
|
||||
InitializeHealthBar();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the health bar.
|
||||
/// </summary>
|
||||
void InitializeHealthBar ()
|
||||
{
|
||||
//Since the transform order of the health bar is always the same, get the parent's parent to get all need Emerald AI Components.
|
||||
canvas = GetComponent<Canvas>();
|
||||
EmeraldUI = transform.parent.parent.GetComponent<EmeraldUI>();
|
||||
EmeraldHeath = transform.parent.parent.GetComponent<EmeraldHealth>();
|
||||
EmeraldComponent = transform.parent.parent.GetComponent<EmeraldSystem>();
|
||||
if (m_Camera == null) m_Camera = GameObject.FindGameObjectWithTag(EmeraldUI.CameraTag).GetComponent<Camera>(); //Get a reference to the camera via the EmeraldUI.CameraTag.
|
||||
|
||||
CG = GetComponent<CanvasGroup>();
|
||||
HealthBar = transform.Find("AI Health Bar Background/AI Health Bar").GetComponent<Image>();
|
||||
HealthBarDamage = transform.Find("AI Health Bar Background/AI Health Bar (Damage)").GetComponent<Image>();
|
||||
AINameUI = transform.Find("AI Name Text").GetComponent<Text>();
|
||||
AILevelUI = transform.Find("AI Level Text").GetComponent<Text>();
|
||||
|
||||
EmeraldHeath.OnDeath += FadeOutUI; //Subscribe FadeOutUI to the OnDeath delegate.
|
||||
EmeraldHeath.OnTakeDamage += TransitionDamage; //Subscribe TransitionDamage to the OnTakeDamage delegate.
|
||||
EmeraldHeath.OnTakeCritDamage += TransitionDamage; //Subscribe TransitionDamage to the OnTakeCritDamage delegate.
|
||||
EmeraldHeath.OnHealRateTick += TransitionHealing; //Subscribe TransitionHealing to the OnHealRateTick delegate.
|
||||
EmeraldHeath.OnHealthChange += UpdateHealthUI; //Subscribe UpdateHealthUI to the OnHealthChange delegate.
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
CalculateUI();
|
||||
}
|
||||
|
||||
public void CalculateUI()
|
||||
{
|
||||
if (m_Camera != null)
|
||||
{
|
||||
if (HealthBar != null)
|
||||
{
|
||||
canvas.transform.parent.LookAt(canvas.transform.parent.position + m_Camera.transform.rotation * Vector3.forward,
|
||||
m_Camera.transform.rotation * Vector3.up);
|
||||
|
||||
float dist = Vector3.Distance(m_Camera.transform.position, transform.position);
|
||||
if (dist < EmeraldUI.MaxUIScaleSize)
|
||||
{
|
||||
canvas.transform.localScale = new Vector3(dist * 0.085f, dist * 0.085f, dist * 0.085f);
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas.transform.localScale = new Vector3(EmeraldUI.MaxUIScaleSize * 0.085f, EmeraldUI.MaxUIScaleSize * 0.085f, EmeraldUI.MaxUIScaleSize * 0.085f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fades out the UI when called. (This is handled automatically through the EmeraldHeath.OnDeath delegate).
|
||||
/// </summary>
|
||||
void FadeOutUI()
|
||||
{
|
||||
if (gameObject.activeSelf)
|
||||
{
|
||||
if (C != null) { StopCoroutine(C); }
|
||||
C = StartCoroutine(FadeOutUIInternal(0.0f, 1.5f));
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if (EmeraldComponent != null && !EmeraldComponent.CombatComponent.CombatState) ResetValues(); //Resets the UI values back to their defaults.
|
||||
}
|
||||
|
||||
IEnumerator FadeOutUIInternal(float DesiredValue, float TransitionTime)
|
||||
{
|
||||
HealthBar.fillAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
float alpha = CG.alpha;
|
||||
float t = 0;
|
||||
|
||||
while ((t / TransitionTime) < 1)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
Color newColor1 = new Color(1, 1, 1, Mathf.Lerp(alpha, DesiredValue, t));
|
||||
CG.alpha = newColor1.a;
|
||||
AINameUI.color = new Color(AINameUI.color.r, AINameUI.color.g, AINameUI.color.b, newColor1.a);
|
||||
AILevelUI.color = new Color(AILevelUI.color.r, AILevelUI.color.g, AILevelUI.color.b, newColor1.a);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
void TransitionDamage ()
|
||||
{
|
||||
if (gameObject.activeSelf)
|
||||
{
|
||||
if (CoroutineTransitionDamage != null) StopCoroutine(CoroutineTransitionDamage);
|
||||
CoroutineTransitionDamage = StartCoroutine(TransitionDamageInternal());
|
||||
}
|
||||
else
|
||||
{
|
||||
HealthBar.fillAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
HealthBarDamage.fillAmount = HealthBar.fillAmount;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator TransitionDamageInternal ()
|
||||
{
|
||||
HealthBar.fillAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
float Start = HealthBarDamage.fillAmount;
|
||||
float t = 0;
|
||||
yield return new WaitForSeconds(0.75f);
|
||||
|
||||
while ((t / 1f) < 1)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
HealthBarDamage.fillAmount = Mathf.Lerp(Start, HealthBar.fillAmount, t);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionHealing ()
|
||||
{
|
||||
if (gameObject.activeSelf)
|
||||
{
|
||||
StartCoroutine(TransitionHealingInternal());
|
||||
}
|
||||
else
|
||||
{
|
||||
HealthBar.fillAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
HealthBarDamage.fillAmount = HealthBar.fillAmount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the AI's health bar based on its current health.
|
||||
/// </summary>
|
||||
void UpdateHealthUI ()
|
||||
{
|
||||
HealthBar.fillAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
HealthBarDamage.fillAmount = HealthBar.fillAmount;
|
||||
}
|
||||
|
||||
IEnumerator TransitionHealingInternal()
|
||||
{
|
||||
float HealAmount = ((float)EmeraldHeath.Health / (float)EmeraldHeath.StartHealth);
|
||||
float Start = HealthBar.fillAmount;
|
||||
float t = 0;
|
||||
|
||||
while ((t / 1f) < 1)
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
HealthBar.fillAmount = Mathf.Lerp(Start, HealAmount, t);
|
||||
HealthBarDamage.fillAmount = Mathf.Lerp(Start, HealAmount, t);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the UI values back to their defaults.
|
||||
/// </summary>
|
||||
void ResetValues ()
|
||||
{
|
||||
if (CG != null)
|
||||
{
|
||||
Color newColor1 = new Color(1, 1, 1, 1);
|
||||
CG.alpha = newColor1.a;
|
||||
AINameUI.color = new Color(AINameUI.color.r, AINameUI.color.g, AINameUI.color.b, newColor1.a);
|
||||
AILevelUI.color = new Color(AILevelUI.color.r, AILevelUI.color.g, AILevelUI.color.b, newColor1.a);
|
||||
HealthBar.fillAmount = 1;
|
||||
HealthBarDamage.fillAmount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 98a33a04e19e3ac4790d52a2324589e0
|
||||
timeCreated: 1502574141
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,275 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public static class EmeraldObjectPool
|
||||
{
|
||||
// You can avoid resizing of the Stack's internal data by
|
||||
// setting this to a number equal to or greater to what you
|
||||
// expect most of your pool sizes to be.
|
||||
// Note, you can also use Preload() to set the initial size
|
||||
// of a pool -- this can be handy if only some of your pools
|
||||
// are going to be exceptionally large (for example, your bullets.)
|
||||
const int DEFAULT_POOL_SIZE = 3;
|
||||
|
||||
/// <summary>
|
||||
/// The Pool class represents the pool for a particular prefab.
|
||||
/// </summary>
|
||||
class Pool
|
||||
{
|
||||
private GameObject PoolParent;
|
||||
|
||||
// We append an id to the name of anything we instantiate.
|
||||
// This is purely cosmetic.
|
||||
int nextId = 1;
|
||||
|
||||
// The structure containing our inactive objects.
|
||||
// Why a Stack and not a List? Because we'll never need to
|
||||
// pluck an object from the start or middle of the array.
|
||||
// We'll always just grab the last one, which eliminates
|
||||
// any need to shuffle the objects around in memory.
|
||||
Stack<GameObject> inactive;
|
||||
|
||||
// The prefab that we are pooling
|
||||
GameObject prefab;
|
||||
|
||||
// Constructor
|
||||
public Pool(GameObject prefab, int initialQty)
|
||||
{
|
||||
this.prefab = prefab;
|
||||
//PoolParent = new GameObject(prefab.name + " (Pool)");
|
||||
|
||||
// If Stack uses a linked list internally, then this
|
||||
// whole initialQty thing is a placebo that we could
|
||||
// strip out for more minimal code. But it can't *hurt*.
|
||||
inactive = new Stack<GameObject>(initialQty);
|
||||
}
|
||||
|
||||
// Spawn an object from our pool
|
||||
public GameObject Spawn(Vector3 pos, Quaternion rot)
|
||||
{
|
||||
GameObject obj;
|
||||
if (inactive.Count == 0)
|
||||
{
|
||||
// We don't have an object in our pool, so we
|
||||
// instantiate a whole new object.
|
||||
obj = (GameObject)GameObject.Instantiate(prefab, pos, rot);
|
||||
obj.name = prefab.name + " (" + (nextId++) + ")";
|
||||
|
||||
// Add a PoolMember component so we know what pool
|
||||
// we belong to.
|
||||
obj.AddComponent<PoolMember>().myPool = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the last object in the inactive array
|
||||
obj = inactive.Pop();
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
// The inactive object we expected to find no longer exists.
|
||||
// The most likely causes are:
|
||||
// - Someone calling Destroy() on our object
|
||||
// - A scene change (which will destroy all our objects).
|
||||
// NOTE: This could be prevented with a DontDestroyOnLoad
|
||||
// if you really don't want this.
|
||||
// No worries -- we'll just try the next one in our sequence.
|
||||
|
||||
return Spawn(pos, rot);
|
||||
}
|
||||
}
|
||||
|
||||
obj.transform.position = pos;
|
||||
obj.transform.rotation = rot;
|
||||
|
||||
if (PoolParent == null) PoolParent = new GameObject(prefab.name + " (Pool)");
|
||||
PoolParent.transform.parent = EmeraldSystem.ObjectPool.transform;
|
||||
obj.transform.SetParent(PoolParent.transform);
|
||||
|
||||
obj.SetActive(true);
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
// Spawn an object from our pool
|
||||
public GameObject SpawnEffect(Vector3 pos, Quaternion rot, float SecondsToDespawn)
|
||||
{
|
||||
GameObject obj;
|
||||
|
||||
if (inactive.Count == 0)
|
||||
{
|
||||
// We don't have an object in our pool, so we
|
||||
// instantiate a whole new object.
|
||||
obj = (GameObject)GameObject.Instantiate(prefab, pos, rot);
|
||||
obj.name = prefab.name + " (" + (nextId++) + ")";
|
||||
|
||||
// Add a PoolMember component so we know what pool
|
||||
// we belong to.
|
||||
obj.AddComponent<PoolMember>().myPool = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Grab the last object in the inactive array
|
||||
obj = inactive.Pop();
|
||||
|
||||
if (obj == null)
|
||||
{
|
||||
// The inactive object we expected to find no longer exists.
|
||||
// The most likely causes are:
|
||||
// - Someone calling Destroy() on our object
|
||||
// - A scene change (which will destroy all our objects).
|
||||
// NOTE: This could be prevented with a DontDestroyOnLoad
|
||||
// if you really don't want this.
|
||||
// No worries -- we'll just try the next one in our sequence.
|
||||
|
||||
return SpawnEffect(pos, rot, SecondsToDespawn);
|
||||
}
|
||||
}
|
||||
|
||||
AssignTimedDespawn(obj, SecondsToDespawn);
|
||||
|
||||
obj.transform.position = pos;
|
||||
obj.transform.rotation = rot;
|
||||
|
||||
if (PoolParent == null) PoolParent = new GameObject(prefab.name + " (Pool)");
|
||||
PoolParent.transform.parent = EmeraldSystem.ObjectPool.transform;
|
||||
obj.transform.SetParent(PoolParent.transform);
|
||||
|
||||
obj.SetActive(true);
|
||||
return obj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void AssignTimedDespawn (GameObject obj, float SecondsToDespawn)
|
||||
{
|
||||
EmeraldTimedDespawn TimedDespawn = obj.GetComponent<EmeraldTimedDespawn>();
|
||||
if (TimedDespawn == null) TimedDespawn = obj.AddComponent<EmeraldTimedDespawn>();
|
||||
TimedDespawn.SecondsToDespawn = SecondsToDespawn;
|
||||
}
|
||||
|
||||
// Return an object to the inactive pool.
|
||||
public void Despawn(GameObject obj)
|
||||
{
|
||||
obj.SetActive(false);
|
||||
|
||||
// Since Stack doesn't have a Capacity member, we can't control
|
||||
// the growth factor if it does have to expand an internal array.
|
||||
// On the other hand, it might simply be using a linked list
|
||||
// internally. But then, why does it allow us to specify a size
|
||||
// in the constructor? Maybe it's a placebo? Stack is weird.
|
||||
inactive.Push(obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Added to freshly instantiated objects, so we can link back
|
||||
/// to the correct pool on despawn.
|
||||
/// </summary>
|
||||
class PoolMember : MonoBehaviour
|
||||
{
|
||||
public Pool myPool;
|
||||
}
|
||||
|
||||
// All of our pools
|
||||
static Dictionary<GameObject, Pool> pools;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize our dictionary.
|
||||
/// </summary>
|
||||
static void Init(GameObject prefab = null, int qty = DEFAULT_POOL_SIZE)
|
||||
{
|
||||
if (pools == null)
|
||||
{
|
||||
pools = new Dictionary<GameObject, Pool>();
|
||||
}
|
||||
if (prefab != null && pools.ContainsKey(prefab) == false)
|
||||
{
|
||||
pools[prefab] = new Pool(prefab, qty);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If you want to preload a few copies of an object at the start
|
||||
/// of a scene, you can use this. Really not needed unless you're
|
||||
/// going to go from zero instances to 100+ very quickly.
|
||||
/// Could technically be optimized more, but in practice the
|
||||
/// Spawn/Despawn sequence is going to be pretty darn quick and
|
||||
/// this avoids code duplication.
|
||||
/// </summary>
|
||||
static public void Preload(GameObject prefab, int qty = 1)
|
||||
{
|
||||
Init(prefab, qty);
|
||||
|
||||
// Make an array to grab the objects we're about to pre-spawn.
|
||||
GameObject[] obs = new GameObject[qty];
|
||||
for (int i = 0; i < qty; i++)
|
||||
{
|
||||
obs[i] = Spawn(prefab, Vector3.zero, Quaternion.identity);
|
||||
}
|
||||
|
||||
// Now despawn them all.
|
||||
for (int i = 0; i < qty; i++)
|
||||
{
|
||||
Despawn(obs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear the pool. This is called once during initialization and
|
||||
/// only if the pool has been populated (typically after a scene change).
|
||||
/// </summary>
|
||||
static public void Clear()
|
||||
{
|
||||
if (pools != null && pools.Count != 0) pools.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a copy of the specified prefab (instantiating one if required).
|
||||
/// NOTE: Remember that Awake() or Start() will only run on the very first
|
||||
/// spawn and that member variables won't get reset. OnEnable will run
|
||||
/// after spawning -- but remember that toggling IsActive will also
|
||||
/// call that function.
|
||||
/// </summary>
|
||||
static public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot)
|
||||
{
|
||||
Init(prefab);
|
||||
|
||||
return pools[prefab].Spawn(pos, rot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Spawns a copy of the specified prefab (instantiating one if required).
|
||||
/// NOTE: Remember that Awake() or Start() will only run on the very first
|
||||
/// spawn and that member variables won't get reset. OnEnable will run
|
||||
/// after spawning -- but remember that toggling IsActive will also
|
||||
/// call that function.
|
||||
/// </summary>
|
||||
static public GameObject SpawnEffect(GameObject prefab, Vector3 pos, Quaternion rot, float SecondsToDespawn)
|
||||
{
|
||||
Init(prefab);
|
||||
|
||||
return pools[prefab].SpawnEffect(pos, rot, SecondsToDespawn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Despawn the specified gameobject back into its pool.
|
||||
/// </summary>
|
||||
static public void Despawn(GameObject obj)
|
||||
{
|
||||
PoolMember pm = obj.GetComponent<PoolMember>();
|
||||
if (pm == null)
|
||||
{
|
||||
Debug.Log("Object '" + obj.name + "' wasn't spawned from a pool. Destroying it instead.");
|
||||
GameObject.Destroy(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm.myPool.Despawn(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e071264767dcb2449b6f28129fba481b
|
||||
timeCreated: 1509114988
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class EmeraldTimedDespawn : MonoBehaviour
|
||||
{
|
||||
public float SecondsToDespawn = 3;
|
||||
float Timer;
|
||||
|
||||
void Update()
|
||||
{
|
||||
Timer += Time.deltaTime;
|
||||
if (Timer >= SecondsToDespawn)
|
||||
{
|
||||
EmeraldObjectPool.Despawn(gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
Timer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e035c00e1f0e024285e7ee9cd795ca1
|
||||
timeCreated: 1510963085
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0253966a04d8e744483331c08c5732d4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[System.Flags]
|
||||
public enum AnimationStateTypes
|
||||
{
|
||||
None = 0,
|
||||
Idling = 1 << 1,
|
||||
Moving = 1 << 2,
|
||||
BackingUp = 1 << 3,
|
||||
TurningLeft = 1 << 4,
|
||||
TurningRight = 1 << 5,
|
||||
Attacking = 1 << 6,
|
||||
Strafing = 1 << 7,
|
||||
Blocking = 1 << 8,
|
||||
Dodging = 1 << 9,
|
||||
Recoiling = 1 << 10,
|
||||
Stunned = 1 << 11,
|
||||
GettingHit = 1 << 12,
|
||||
Equipping = 1 << 13,
|
||||
SwitchingWeapons = 1 << 14,
|
||||
Dead = 1 << 15,
|
||||
Emoting = 1 << 16,
|
||||
Everything = ~0,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa1b0ca94785d6a41909e8b139df704c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public enum AttackPickTypes { Odds, Order, Random};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e247633349e4fd24d8a2e9613fbdb238
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public enum PickTargetTypes
|
||||
{
|
||||
Closest = 0,
|
||||
FirstDetected = 1,
|
||||
Random = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50a550417f3dc2a4697cdd47dd506905
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public enum RelationTypes
|
||||
{
|
||||
Enemy = 0,
|
||||
Neutral = 1,
|
||||
Friendly = 2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea8ab8c7d527ddb40bd8675733017ea7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public enum YesOrNo
|
||||
{
|
||||
No = 0,
|
||||
Yes = 1
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1a06ba65d4194145a75dd4ef1cc840b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb6130ab02241ed4eaeaea9b618ea4c8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to allow AI to detect which objects/abilities they should avoid.
|
||||
/// The AbilityTarget is used to determine which target the ability is intended for.
|
||||
/// </summary>
|
||||
public interface IAvoidable
|
||||
{
|
||||
Transform AbilityTarget { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12b93e20d734af046bd4c989dfaf3e8a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// An interafce script used for monitoring and tracking a target's combat actions (as well as its damage position). This allows other AI to see any target's information through functions.
|
||||
/// Note: This interface is required (on 3rd party or custom character controllers) to use the blocking and dodging features for player targets.
|
||||
/// </summary>
|
||||
public interface ICombat
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for getting the transform of the target.
|
||||
/// </summary>
|
||||
Transform TargetTransform();
|
||||
|
||||
/// <summary>
|
||||
/// Used for getting the damage position of the target.
|
||||
/// </summary>
|
||||
Vector3 DamagePosition();
|
||||
|
||||
/// <summary>
|
||||
/// Used for detecting when a target is attacking.
|
||||
/// </summary>
|
||||
bool IsAttacking();
|
||||
|
||||
/// <summary>
|
||||
/// Used for detecting when a target is blocking.
|
||||
/// </summary>
|
||||
bool IsBlocking();
|
||||
|
||||
/// <summary>
|
||||
/// Used for detecting when a target is dodging.
|
||||
/// </summary>
|
||||
bool IsDodging();
|
||||
|
||||
/// <summary>
|
||||
/// Used through Emerald AI to trigger stunned mechanics, however, can also be extended to trigger stunned mechanics through custom character controllers, given they have them.
|
||||
/// </summary>
|
||||
void TriggerStun(float StunLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aef9b7ce85ce4d847aa3aff4791502a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,72 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// An interafce script used for monitoring and tracking a target. This allows other AI to see any target's information by using customizable functions.
|
||||
/// </summary>
|
||||
public interface IDamageable
|
||||
{
|
||||
/// <summary>
|
||||
/// Used for passing damage to any script that has an IDamageable component.
|
||||
/// </summary>
|
||||
void Damage(int DamageAmount, Transform AttackerTransform = null, int RagdollForce = 100, bool CriticalHit = false);
|
||||
|
||||
int Health { get; set; }
|
||||
|
||||
int StartHealth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Used for tracking active damage over time effects on targets.
|
||||
/// </summary>
|
||||
List<string> ActiveEffects { get; set; }
|
||||
}
|
||||
|
||||
public static class IDamageableHelper
|
||||
{
|
||||
public static bool IsDead (this GameObject receiver)
|
||||
{
|
||||
var m_IDamageable = receiver.GetComponent<IDamageable>();
|
||||
if (m_IDamageable != null) return m_IDamageable.Health <= 0;
|
||||
else return false;
|
||||
}
|
||||
|
||||
public static bool CheckAbilityActiveEffects (this GameObject receiver, EmeraldAbilityObject AbilityData)
|
||||
{
|
||||
var m_IDamageable = receiver.GetComponent<IDamageable>();
|
||||
if (m_IDamageable != null)
|
||||
{
|
||||
return !m_IDamageable.ActiveEffects.Contains(AbilityData.AbilityName) && AbilityData.AbilityName != string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddAbilityActiveEffect(this GameObject receiver, EmeraldAbilityObject AbilityData)
|
||||
{
|
||||
var m_IDamageable = receiver.GetComponent<IDamageable>();
|
||||
if (m_IDamageable != null)
|
||||
{
|
||||
if (!m_IDamageable.ActiveEffects.Contains(AbilityData.AbilityName) && AbilityData.AbilityName != string.Empty)
|
||||
{
|
||||
m_IDamageable.ActiveEffects.Add(AbilityData.AbilityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void RemoveAbilityActiveEffect(this GameObject receiver, EmeraldAbilityObject AbilityData)
|
||||
{
|
||||
var m_IDamageable = receiver.GetComponent<IDamageable>();
|
||||
if (m_IDamageable != null)
|
||||
{
|
||||
if (m_IDamageable.ActiveEffects.Contains(AbilityData.AbilityName) && AbilityData.AbilityName != string.Empty)
|
||||
{
|
||||
m_IDamageable.ActiveEffects.Remove(AbilityData.AbilityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b70d1ee666095e4d8c4cb388d716643
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public interface IFaction
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the object's faction index (based on the Faction Data's Faction Name List).
|
||||
/// </summary>
|
||||
int GetFaction();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ccf922b652ff97459885a7bffdf355b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
public class LocationBasedDamageArea : MonoBehaviour
|
||||
{
|
||||
[HideInInspector] public float DamageMultiplier = 1;
|
||||
[HideInInspector] public EmeraldSystem EmeraldComponent;
|
||||
|
||||
/// <summary>
|
||||
/// Damages an AI's location based damage component and applies a multiplier to the damage receieved. The parameters of this are the same as the EmeraldAISystem Damage function.
|
||||
/// Call this function instead if you want to utilize the Location Based Damage feature. Ensure that the AI you are damaging has a Location Based Damage script applied to where
|
||||
/// the EmeraldAISystem script is and that you have pressed the Get Colliders button on the Location Based Damage component.
|
||||
/// </summary>
|
||||
public void DamageArea(int DamageAmount, Transform AttackerTransform = null, int RagdollForce = 0, bool CriticalHit = false)
|
||||
{
|
||||
int DamageDealt = DamageAmount;
|
||||
if (DamageMultiplier > 1) DamageDealt = Mathf.RoundToInt(DamageAmount * DamageMultiplier);
|
||||
IDamageable m_IDamageable = EmeraldComponent.GetComponent<IDamageable>();
|
||||
m_IDamageable.Damage(DamageDealt, AttackerTransform, RagdollForce, CriticalHit);
|
||||
if (!EmeraldComponent.AnimationComponent.IsBlocking) CreateImpactEffect(transform.position, true);
|
||||
if (m_IDamageable.Health <= 0)
|
||||
EmeraldComponent.CombatComponent.RagdollTransform = transform;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an impact effect at the ImpactPosition. The Impact Effect is based off of your AI's Hit Effects List (Located under AI's Settings>Combat>Hit Effect).
|
||||
/// </summary>
|
||||
public void CreateImpactEffect(Vector3 ImpactPosition, bool SetAIAsEffectParent = true)
|
||||
{
|
||||
if (EmeraldComponent.HealthComponent.UseHitEffect == YesOrNo.Yes && EmeraldComponent.HealthComponent.HitEffectsList.Count > 0)
|
||||
{
|
||||
GameObject RandomBloodEffect = EmeraldComponent.HealthComponent.HitEffectsList[Random.Range(0, EmeraldComponent.HealthComponent.HitEffectsList.Count)];
|
||||
if (RandomBloodEffect != null)
|
||||
{
|
||||
GameObject SpawnedBlood = EmeraldAI.Utility.EmeraldObjectPool.SpawnEffect(RandomBloodEffect, ImpactPosition, Quaternion.LookRotation(transform.forward, Vector3.up), EmeraldComponent.HealthComponent.HitEffectTimeoutSeconds) as GameObject;
|
||||
|
||||
if (SetAIAsEffectParent)
|
||||
SpawnedBlood.transform.SetParent(transform);
|
||||
else
|
||||
SpawnedBlood.transform.SetParent(EmeraldSystem.ObjectPool.transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ded479506d679a4f836c4476e6dfefd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a3f3a42f43c1df47a3d1bf31c7333c3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the field/property ONLY if the compared property compared by the comparison type with the value of comparedValue returns true.
|
||||
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
|
||||
public class CompareEnumWithRangeAttribute : PropertyAttribute
|
||||
{
|
||||
#region Fields
|
||||
public string comparedPropertyName { get; private set; }
|
||||
public object comparedValue1 { get; private set; }
|
||||
public object comparedValue2 { get; private set; }
|
||||
public object comparedValue3 { get; private set; }
|
||||
|
||||
public StyleType styleType { get; private set; }
|
||||
public float min;
|
||||
public float max;
|
||||
|
||||
/// <summary>
|
||||
/// Types of styles variables can use.
|
||||
/// </summary>
|
||||
public enum StyleType
|
||||
{
|
||||
FloatSlider = 1,
|
||||
IntSlider = 2
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Only draws the field only if a condition is met.
|
||||
/// </summary>
|
||||
/// <param name="comparedPropertyName">The name of the property that is being compared (case sensitive).</param>
|
||||
/// <param name="comparedValue">The value the property is being compared to.</param>
|
||||
public CompareEnumWithRangeAttribute(string comparedPropertyName, float min, float max, StyleType styleType, object comparedValue1, object comparedValue2 = null, object comparedValue3 = null)
|
||||
{
|
||||
this.comparedPropertyName = comparedPropertyName;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.styleType = styleType;
|
||||
this.comparedValue1 = comparedValue1;
|
||||
this.comparedValue2 = comparedValue2;
|
||||
this.comparedValue3 = comparedValue3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94bbf07212b478443add5b5ef96d02cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,40 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the field/property ONLY if the compared property compared by the comparison type with the value of comparedValue returns true.
|
||||
/// </summary>
|
||||
//Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
|
||||
public class DrawIfAttribute : PropertyAttribute
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public string comparedPropertyName { get; private set; }
|
||||
public object comparedValue { get; private set; }
|
||||
public DisablingType disablingType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Types of comperisons.
|
||||
/// </summary>
|
||||
public enum DisablingType
|
||||
{
|
||||
ReadOnly = 2,
|
||||
DontDraw = 3
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Only draws the field only if a condition is met. Supports enum and bools.
|
||||
/// </summary>
|
||||
/// <param name="comparedPropertyName">The name of the property that is being compared (case sensitive).</param>
|
||||
/// <param name="comparedValue">The value the property is being compared to.</param>
|
||||
/// <param name="disablingType">The type of disabling that should happen if the condition is NOT met. Defaulted to DisablingType.DontDraw.</param>
|
||||
public DrawIfAttribute(string comparedPropertyName, object comparedValue, DisablingType disablingType = DisablingType.DontDraw)
|
||||
{
|
||||
this.comparedPropertyName = comparedPropertyName;
|
||||
this.comparedValue = comparedValue;
|
||||
this.disablingType = disablingType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52f60d70871714644bf9e7a75d7c611f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Draws the field/property ONLY if the compared property compared by the comparison type with the value of comparedValue returns true.
|
||||
/// <summary>
|
||||
//Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
|
||||
public class DrawIfRangeAttribute : PropertyAttribute
|
||||
{
|
||||
#region Fields
|
||||
|
||||
public string comparedPropertyName { get; private set; }
|
||||
public object comparedValue { get; private set; }
|
||||
public ComparisonType comparisonType { get; private set; }
|
||||
public StyleType styleType { get; private set; }
|
||||
|
||||
public float min;
|
||||
public float max;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Types of styles variables can use.
|
||||
/// </summary>
|
||||
public enum StyleType
|
||||
{
|
||||
Default = 1,
|
||||
FloatSlider = 2,
|
||||
IntSlider = 3
|
||||
}
|
||||
|
||||
public enum ComparisonType
|
||||
{
|
||||
Equals = 1,
|
||||
NotEqual = 2,
|
||||
GreaterThan = 3,
|
||||
SmallerThan = 4,
|
||||
SmallerOrEqual = 5,
|
||||
GreaterOrEqual = 6
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Only draws the field only if a condition is met. Supports enum and bools.
|
||||
/// </summary>
|
||||
/// <param name="comparedPropertyName">The name of the property that is being compared (case sensitive).</param>
|
||||
/// <param name="comparedValue">The value the property is being compared to.</param>
|
||||
public DrawIfRangeAttribute(string comparedPropertyName, object comparedValue, ComparisonType comparisonType, float min, float max, StyleType styleType)
|
||||
{
|
||||
this.comparedPropertyName = comparedPropertyName;
|
||||
this.comparedValue = comparedValue;
|
||||
this.comparisonType = comparisonType;
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.styleType = styleType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f12b29c782320814f9c57f548efa4b99
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f89d90d7de68624c84be8b1bce507cc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
/// </summary>
|
||||
[CustomPropertyDrawer(typeof(CompareEnumWithRangeAttribute))]
|
||||
public class CompareEnumWithRangePropertyDrawer : PropertyDrawer
|
||||
{
|
||||
#region Fields
|
||||
|
||||
// Reference to the attribute on the property.
|
||||
CompareEnumWithRangeAttribute CompareEnumWithRangeAttribute;
|
||||
|
||||
// Field that is being compared.
|
||||
SerializedProperty comparedField;
|
||||
|
||||
#endregion
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (!ShowMe(property))
|
||||
return 0f;
|
||||
|
||||
// The height of the property should be defaulted to the default height.
|
||||
return base.GetPropertyHeight(property, label);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Errors default to showing the property.
|
||||
/// </summary>
|
||||
private bool ShowMe(SerializedProperty property)
|
||||
{
|
||||
CompareEnumWithRangeAttribute = attribute as CompareEnumWithRangeAttribute;
|
||||
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, CompareEnumWithRangeAttribute.comparedPropertyName) : CompareEnumWithRangeAttribute.comparedPropertyName;
|
||||
|
||||
comparedField = property.serializedObject.FindProperty(path);
|
||||
|
||||
if (comparedField == null)
|
||||
{
|
||||
Debug.LogError("Cannot find property with name: " + path);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (comparedField.type)
|
||||
{
|
||||
case "Enum":
|
||||
return comparedField.enumValueIndex.Equals((int)CompareEnumWithRangeAttribute.comparedValue1) ||
|
||||
CompareEnumWithRangeAttribute.comparedValue2 != null && comparedField.enumValueIndex.Equals((int)CompareEnumWithRangeAttribute.comparedValue2) ||
|
||||
CompareEnumWithRangeAttribute.comparedValue3 != null && comparedField.enumValueIndex.Equals((int)CompareEnumWithRangeAttribute.comparedValue3);
|
||||
default:
|
||||
Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
// If the condition is met, simply draw the field.
|
||||
if (ShowMe(property))
|
||||
{
|
||||
Rect offsetPosition = position;
|
||||
//offsetPosition.x = offsetPosition.x + 30;
|
||||
//offsetPosition.width = offsetPosition.width - 30;
|
||||
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (CompareEnumWithRangeAttribute.styleType == CompareEnumWithRangeAttribute.StyleType.FloatSlider)
|
||||
{
|
||||
var newValue = EditorGUI.Slider(offsetPosition, label, property.floatValue, CompareEnumWithRangeAttribute.min, CompareEnumWithRangeAttribute.max);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.floatValue = newValue;
|
||||
}
|
||||
}
|
||||
else if (CompareEnumWithRangeAttribute.styleType == CompareEnumWithRangeAttribute.StyleType.IntSlider)
|
||||
{
|
||||
var newValue = EditorGUI.IntSlider(offsetPosition, label, property.intValue, (int)CompareEnumWithRangeAttribute.min, (int)CompareEnumWithRangeAttribute.max);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.intValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
//EditorGUI.PropertyField(position, property, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd7f70077f9ee234c902879bf9e87cea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,849 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class CustomEditorProperties
|
||||
{
|
||||
public static void DisplaySetupWarning (string WarningMessage)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(-12);
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.HelpBox(WarningMessage, MessageType.Warning);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
public static void DisplayWarningMessage(string WarningMessage)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUIUtility.SetIconSize(new Vector2(32, 32));
|
||||
EditorGUILayout.HelpBox(WarningMessage, MessageType.Warning);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
public static void DisplayImportantHeaderMessage(string WarningMessage)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(-12);
|
||||
GUI.backgroundColor = new Color(10f, 10f, 0.0f, 0.5f);
|
||||
EditorGUILayout.HelpBox(WarningMessage, MessageType.Info);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
public static void DisplayImportantMessage(string WarningMessage)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUI.backgroundColor = new Color(10f, 10f, 0.0f, 0.5f);
|
||||
EditorGUIUtility.SetIconSize(new Vector2(32, 32));
|
||||
EditorGUILayout.HelpBox(WarningMessage, MessageType.Info);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to automatically find the AI's head transform.
|
||||
/// </summary>
|
||||
public static void AutoFindHeadTransform (Rect position, GUIContent label, SerializedProperty property, Transform AIRef)
|
||||
{
|
||||
CustomHelpLabelField("Attempts to automatically find the AI's head transform. If a transform is found, it is recommended that it is checked to ensure it's correct. " +
|
||||
"If a suitable transform isn't found, no object will be applied and you will need to apply one manually.", false);
|
||||
if (GUILayout.Button("Auto Find Head Transform"))
|
||||
{
|
||||
//Search all the transforms within an AI and look for the word root
|
||||
foreach (Transform root in AIRef.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (i < root.childCount && root.GetChild(i).name == "root" || i < root.childCount && root.GetChild(i).name == "Root" || i < root.childCount && root.GetChild(i).name == "ROOT") //Only look in the root transform - 3 child index in
|
||||
{
|
||||
foreach (Transform t in root.GetChild(i).GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (t.name.Contains("head") || t.name.Contains("Head") || t.name.Contains("HEAD")) //Look for the word head within all transforms within the root transform
|
||||
{
|
||||
property.objectReferenceValue = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//If no head transform was found, the model may not have a root named bone, try again with less conditions.
|
||||
if (property.objectReferenceValue == null)
|
||||
{
|
||||
foreach (Transform t in AIRef.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
//Ignore transforms with a MultiAimConstraint as these can be for the Animation Rigging system/constraint.
|
||||
if (t.GetComponent<UnityEngine.Animations.Rigging.MultiAimConstraint>() == null)
|
||||
{
|
||||
if (t.name.Contains("head") || t.name.Contains("Head") || t.name.Contains("HEAD")) //Look for the word head within all transforms within the root transform
|
||||
{
|
||||
property.objectReferenceValue = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CustomListFloatSlider(Rect position, GUIContent label, SerializedProperty property, float MinValue, float MaxValue)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUI.Slider(position, label, property.floatValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.floatValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomListIntSlider(Rect position, GUIContent label, SerializedProperty property, int MinValue, int MaxValue)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUI.IntSlider(position, label, property.intValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomListPopup(Rect position, GUIContent label, SerializedProperty property, string nameOfLabel, string[] names)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string[] enumNamesList = names;
|
||||
var newValue = EditorGUI.Popup(position, property.intValue, enumNamesList);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomHelpLabelField(string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.19f);
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static string CustomDescriptionField (UnityEngine.Object self, string DescriptionName, string Description)
|
||||
{
|
||||
GUIStyle style = new GUIStyle(EditorStyles.textArea);
|
||||
style.wordWrap = true;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.LabelField(DescriptionName);
|
||||
string Value = EditorGUILayout.TextArea(Description, style);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RecordObject(self, "Changed Action Description");
|
||||
Description = Value;
|
||||
}
|
||||
EditorGUILayout.Space();
|
||||
|
||||
return Description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property field with a description and an optional space.
|
||||
/// </summary>
|
||||
public static void CustomPropertyField(SerializedProperty Property, string Name, string TextInfo, bool UseSpace)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property, new GUIContent(Name));
|
||||
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.19f);
|
||||
if (TextInfo != "") EditorGUILayout.LabelField(TextInfo, EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace) EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property field with a description and an optional space.
|
||||
/// </summary>
|
||||
public static void CustomListPropertyField(SerializedProperty Property, string Name, string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUILayout.Space(5);
|
||||
GUILayout.Box(new GUIContent("What's This?", TextInfo + "\n\nNote: The list below can be opened up by clicking on the foldout."), EditorStyles.toolbarButton, GUILayout.ExpandWidth(false));
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(15);
|
||||
EditorGUILayout.PropertyField(Property, new GUIContent(Name));
|
||||
GUILayout.Space(2);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (UseSpace) EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a custom float slider with a description and an optional space.
|
||||
/// </summary>
|
||||
public static void CustomStringPropertyField(SerializedProperty property, string Name, string Description, bool UseSpace)
|
||||
{
|
||||
GUIContent label = EditorGUI.BeginProperty(new Rect(), GUIContent.none, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.TextField(Name, property.stringValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.stringValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
if (Description != string.Empty)
|
||||
{
|
||||
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.19f);
|
||||
EditorGUILayout.LabelField(Description, EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
if (UseSpace) EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a custom float slider with a description and an optional space.
|
||||
/// </summary>
|
||||
public static void CustomFloatSliderPropertyField(SerializedProperty property, string Name, string Description, float MinValue, float MaxValue, bool UseSpace)
|
||||
{
|
||||
GUIContent label = EditorGUI.BeginProperty(new Rect(), GUIContent.none, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.Slider(Name, property.floatValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.floatValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.19f);
|
||||
EditorGUILayout.LabelField(Description, EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace) EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a custom float slider with a description and an optional space.
|
||||
/// </summary>
|
||||
public static void CustomIntSliderPropertyField(SerializedProperty property, string Name, string Description, int MinValue, int MaxValue, bool UseSpace)
|
||||
{
|
||||
GUIContent label = EditorGUI.BeginProperty(new Rect(), GUIContent.none, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.IntSlider(Name, property.intValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 0.19f);
|
||||
EditorGUILayout.LabelField(Description, EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace) EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
public static void CustomHelpLabelFieldWithType(string TextInfo, bool UseSpace, Color color, MessageType messageType)
|
||||
{
|
||||
EditorGUIUtility.SetIconSize(new Vector2(32, 32));
|
||||
GUI.backgroundColor = color;
|
||||
EditorGUILayout.HelpBox(TextInfo, messageType);
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
}
|
||||
|
||||
public static void TextTitle (string TitleText)
|
||||
{
|
||||
GUI.backgroundColor = new Color(1f, 155f, 1f, 0.25f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel);
|
||||
GUI.backgroundColor = Color.white;
|
||||
EditorGUILayout.EndVertical();
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
public static void BoldTextTitle(string TitleText)
|
||||
{
|
||||
GUIStyle TextStyle = EditorStyles.boldLabel;
|
||||
TextStyle.fontStyle = FontStyle.Bold;
|
||||
TextStyle.fontSize = 12;
|
||||
TextStyle.normal.textColor = Color.white;
|
||||
EditorGUILayout.LabelField(TitleText, TextStyle);
|
||||
}
|
||||
|
||||
public static void TextTitleWithDescription(string TitleText, string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUI.backgroundColor = new Color(1f, 155f, 1f, 0.25f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static GUIStyle UpdateEditorStyles()
|
||||
{
|
||||
GUIStyle FoldoutStyle = EditorStyles.foldout;
|
||||
FoldoutStyle.fontStyle = FontStyle.Bold;
|
||||
FoldoutStyle.fontSize = 12;
|
||||
if (EditorGUIUtility.isProSkin)
|
||||
{
|
||||
FoldoutStyle.active.textColor = Color.white;
|
||||
FoldoutStyle.focused.textColor = Color.white;
|
||||
FoldoutStyle.onHover.textColor = Color.white;
|
||||
FoldoutStyle.normal.textColor = Color.white;
|
||||
FoldoutStyle.onNormal.textColor = Color.white;
|
||||
FoldoutStyle.onActive.textColor = Color.white;
|
||||
FoldoutStyle.onFocused.textColor = Color.white;
|
||||
}
|
||||
else
|
||||
{
|
||||
FoldoutStyle.active.textColor = Color.black;
|
||||
FoldoutStyle.focused.textColor = Color.black;
|
||||
FoldoutStyle.onHover.textColor = Color.black;
|
||||
FoldoutStyle.normal.textColor = Color.black;
|
||||
FoldoutStyle.onNormal.textColor = Color.black;
|
||||
FoldoutStyle.onActive.textColor = Color.black;
|
||||
FoldoutStyle.onFocused.textColor = Color.black;
|
||||
}
|
||||
Color myStyleColor = Color.white;
|
||||
return FoldoutStyle;
|
||||
}
|
||||
|
||||
public static GUIStyle UpdateTitleStyle()
|
||||
{
|
||||
GUIStyle TitleStyle = EditorStyles.wordWrappedLabel;
|
||||
TitleStyle.fontStyle = FontStyle.Bold;
|
||||
TitleStyle.fontSize = 16;
|
||||
TitleStyle.alignment = TextAnchor.MiddleLeft;
|
||||
TitleStyle.padding.left = 10;
|
||||
TitleStyle.padding.top = -16;
|
||||
TitleStyle.normal.textColor = Color.white;
|
||||
return TitleStyle;
|
||||
}
|
||||
|
||||
public static GUIStyle UpdateHelpButtonStyle ()
|
||||
{
|
||||
GUIStyle HelpButtonStyle = new GUIStyle(GUI.skin.button);
|
||||
HelpButtonStyle.normal.textColor = Color.white;
|
||||
HelpButtonStyle.fontStyle = FontStyle.Bold;
|
||||
return HelpButtonStyle;
|
||||
}
|
||||
|
||||
public static void BeginScriptHeader(string TitleText, Texture Icon)
|
||||
{
|
||||
GUILayout.Space(8); //Added to give extra space at the top before drawing everything.
|
||||
|
||||
GUIStyle Style = EditorStyles.wordWrappedLabel;
|
||||
Style.fontStyle = FontStyle.Bold;
|
||||
Style.fontSize = 16;
|
||||
Style.alignment = TextAnchor.MiddleLeft;
|
||||
Style.padding.left = 10;
|
||||
Style.padding.top = -15;
|
||||
Style.normal.textColor = Color.white;
|
||||
|
||||
BeginIndent(-7); //Offset the header boxes
|
||||
|
||||
//Header
|
||||
GUI.backgroundColor = new Color(0.62f, 0.62f, 0.62f, 1f);
|
||||
|
||||
EditorGUILayout.BeginVertical("Window");
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUIUtility.SetIconSize(new Vector2(32, 32));
|
||||
EditorGUILayout.LabelField(new GUIContent(" " + TitleText, Icon), Style, GUILayout.ExpandHeight(true));
|
||||
GUI.backgroundColor = Color.white;
|
||||
EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
//Encompassing Box
|
||||
GUI.backgroundColor = new Color(0.85f, 0.85f, 0.85f, 1f);
|
||||
EditorGUILayout.BeginVertical("Window");
|
||||
GUILayout.Space(-22);
|
||||
GUI.backgroundColor = Color.white;
|
||||
BeginIndent(15); //Offset the elements
|
||||
}
|
||||
|
||||
public static bool BeginScriptHeaderNew(string TitleText, Texture Icon, GUIContent label, SerializedProperty property, bool DisplayHideButton = true)
|
||||
{
|
||||
GUILayout.Space(8); //Added to give extra space at the top before drawing everything.
|
||||
|
||||
string ButtonText = " Hide ";
|
||||
GUIStyle Style = EditorStyles.wordWrappedLabel;
|
||||
Style.fontStyle = FontStyle.Bold;
|
||||
Style.fontSize = 16;
|
||||
Style.alignment = TextAnchor.MiddleLeft;
|
||||
Style.padding.left = 10;
|
||||
Style.padding.top = -20;
|
||||
Style.normal.textColor = Color.white;
|
||||
|
||||
BeginIndent(-7); //Offset the header boxes
|
||||
|
||||
//Header
|
||||
GUI.backgroundColor = new Color(0.62f, 0.62f, 0.62f, 1f);
|
||||
|
||||
EditorGUILayout.BeginVertical("Window");
|
||||
|
||||
EditorGUILayout.BeginHorizontal(); //Added
|
||||
//EditorGUIUtility.SetIconSize(new Vector2(32, 32));
|
||||
EditorGUILayout.LabelField(new GUIContent(" " + TitleText, Icon), Style, GUILayout.ExpandHeight(true));
|
||||
GUI.backgroundColor = Color.white;
|
||||
//EditorGUIUtility.SetIconSize(new Vector2(16, 16));
|
||||
|
||||
//Button Style
|
||||
var ButtonStyle = new GUIStyle(GUI.skin.button);
|
||||
ButtonStyle.normal.textColor = Color.white;
|
||||
ButtonStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
GUILayout.FlexibleSpace();
|
||||
EditorGUILayout.BeginVertical();
|
||||
GUILayout.Space(-13f);
|
||||
if (property.boolValue)
|
||||
{
|
||||
ButtonText = " Show ";
|
||||
}
|
||||
|
||||
if (property.boolValue)
|
||||
GUI.backgroundColor = new Color(0.7f, 1.25f, 0.7f, 0.75f);
|
||||
else
|
||||
GUI.backgroundColor = Color.white;
|
||||
|
||||
if (DisplayHideButton)
|
||||
{
|
||||
if (GUILayout.Button(ButtonText, ButtonStyle, GUILayout.Height(25), GUILayout.ExpandWidth(false)))
|
||||
{
|
||||
property.boolValue = !property.boolValue;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
|
||||
//Encompassing Box
|
||||
if (property.boolValue)
|
||||
GUI.backgroundColor = new Color(1f, 0.85f, 0.85f, 1f);
|
||||
else
|
||||
GUI.backgroundColor = new Color(0.85f, 0.85f, 0.85f, 1f);
|
||||
EditorGUILayout.BeginVertical("Window");
|
||||
GUILayout.Space(-22);
|
||||
|
||||
//Display a description that the current script window is minimized.
|
||||
if (property.boolValue)
|
||||
{
|
||||
GUILayout.Space(3);
|
||||
EditorGUILayout.LabelField(" Settings Hidden ");
|
||||
}
|
||||
|
||||
BeginIndent(15); //Offset the elements
|
||||
return property.boolValue;
|
||||
}
|
||||
|
||||
public static void EndScriptHeader()
|
||||
{
|
||||
EndIndent();
|
||||
EndIndent();
|
||||
GUILayout.Space(7); //Added (Adds space to the right side)
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUILayout.Space(6); //Added to give extra space at the bottom after drawing everything.
|
||||
}
|
||||
|
||||
public static void BeginFoldoutWindowBox ()
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
GUI.backgroundColor = new Color(0.85f, 0.85f, 0.85f, 1f);
|
||||
EditorGUILayout.BeginVertical("Window");
|
||||
GUILayout.Space(-19);
|
||||
}
|
||||
|
||||
public static void EndFoldoutWindowBox()
|
||||
{
|
||||
EditorGUILayout.EndVertical();
|
||||
GUILayout.Space(8);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
public static void TextTitleWithDescriptionAndColor(string TitleText, string TextInfo, bool UseSpace, Color color)
|
||||
{
|
||||
GUI.backgroundColor = color;
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static void NoticeTextTitleWithDescription(string TitleText, string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUI.backgroundColor = new Color(155f, 125f, 1f, 0.45f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static void NoticeTextDescription(string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUI.backgroundColor = new Color(155f, 125f, 1f, 0.45f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static void WarningTextTitleWithDescription(string TitleText, string TextInfo, bool UseSpace)
|
||||
{
|
||||
GUI.backgroundColor = new Color(155f, 1f, 1f, 0.35f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(TitleText, EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.LabelField(TextInfo, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
|
||||
GUI.backgroundColor = Color.white;
|
||||
if (UseSpace)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
}
|
||||
|
||||
public static void BeginIndent (int Distance = 10)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(Distance);
|
||||
EditorGUILayout.BeginVertical();
|
||||
}
|
||||
|
||||
public static void EndIndent()
|
||||
{
|
||||
EditorGUILayout.EndHorizontal();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public static void TutorialButton (string Description, string LinkText)
|
||||
{
|
||||
var HelpButtonStyle = new GUIStyle(GUI.skin.button);
|
||||
HelpButtonStyle.normal.textColor = Color.white;
|
||||
HelpButtonStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
GUI.backgroundColor = new Color(1f, 155f, 1f, 0.25f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(Description, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
GUI.backgroundColor = new Color(0, 0.65f, 0, 0.8f);
|
||||
if (GUILayout.Button("See Tutorial", HelpButtonStyle, GUILayout.Height(20)))
|
||||
{
|
||||
Application.OpenURL(LinkText);
|
||||
}
|
||||
GUI.backgroundColor = Color.white;
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
public static void ImportantTutorialButton(string Description, string LinkText)
|
||||
{
|
||||
var HelpButtonStyle = new GUIStyle(GUI.skin.button);
|
||||
HelpButtonStyle.normal.textColor = Color.white;
|
||||
HelpButtonStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
GUI.backgroundColor = new Color(155f, 125f, 1f, 0.45f);
|
||||
EditorGUILayout.BeginVertical("Box");
|
||||
EditorGUILayout.LabelField(Description, EditorStyles.wordWrappedMiniLabel);
|
||||
EditorGUILayout.EndVertical();
|
||||
GUI.backgroundColor = new Color(0, 0.65f, 0, 0.8f);
|
||||
if (GUILayout.Button("See Tutorial", HelpButtonStyle, GUILayout.Height(20)))
|
||||
{
|
||||
Application.OpenURL(LinkText);
|
||||
}
|
||||
GUI.backgroundColor = Color.white;
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays an AnimationClass as individual values within the Emerald AI Animation Profile Editor.
|
||||
/// </summary>
|
||||
public static void DrawAnimationClassVariables(AnimationProfile self, AnimationClass AnimationClassValue, string ValueName, string AnimationDescription, int NumberOfSpaces, bool DisplayMirror, bool DisplayLoopMessage, bool BackwardsAnimation = false)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
AnimationClassValue.AnimationClip = (AnimationClip)EditorGUILayout.ObjectField(ValueName + " Animation", AnimationClassValue.AnimationClip, typeof(AnimationClip), false);
|
||||
|
||||
CustomHelpLabelField(AnimationDescription, false);
|
||||
AnimationClassValue.AnimationSpeed = EditorGUILayout.Slider(ValueName + " Speed", AnimationClassValue.AnimationSpeed, -8f, 8f);
|
||||
CustomHelpLabelField("Controls the speed of this animation.", false);
|
||||
|
||||
if (DisplayMirror)
|
||||
{
|
||||
AnimationClassValue.Mirror = EditorGUILayout.Toggle(ValueName + " Mirror", AnimationClassValue.Mirror);
|
||||
CustomHelpLabelField("Mirroring an animation allows you to play an animation in the opposite direction.", false);
|
||||
}
|
||||
|
||||
if (AnimationClassValue.AnimationClip != null && DisplayLoopMessage)
|
||||
{
|
||||
var settings = AnimationUtility.GetAnimationClipSettings(AnimationClassValue.AnimationClip);
|
||||
if (!settings.loopTime)
|
||||
{
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.LabelField("The '" + ValueName + "' animation must be set to loop. To do so, go to your animation settings and set 'Loop Time' to true.", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
}
|
||||
|
||||
GUILayout.Space(NumberOfSpaces * 8);
|
||||
|
||||
//Set any AnimationSpeed values, that equal 0, to 1 to avoid a warning message when generating the Animator Controller.
|
||||
if (AnimationClassValue.AnimationSpeed == 0)
|
||||
AnimationClassValue.AnimationSpeed = 1;
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
self.AnimationsUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void CustomFoldout(SerializedProperty FoldoutValue, string TitleText, bool ToggleOnLabelClick, GUIStyle FoldoutStyle)
|
||||
{
|
||||
GUIContent label = new GUIContent();
|
||||
//EditorGUILayout.BeginVertical("Box");
|
||||
label = EditorGUI.BeginProperty(new Rect(), label, FoldoutValue);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.Foldout(FoldoutValue.boolValue, TitleText, ToggleOnLabelClick);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
FoldoutValue.boolValue = newValue;
|
||||
EditorGUI.EndProperty();
|
||||
//EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
public static void CustomIntField(Rect position, GUIContent label, SerializedProperty property, string Name)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.IntField(Name, property.intValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomIntSlider(Rect position, GUIContent label, SerializedProperty property, string Name, int MinValue, int MaxValue)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.IntSlider(Name, property.intValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomFloatSlider(Rect position, GUIContent label, SerializedProperty property, string Name, float MinValue, float MaxValue)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.Slider(Name, property.floatValue, MinValue, MaxValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.floatValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomFloatField(Rect position, GUIContent label, SerializedProperty property, string Name)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.FloatField(Name, property.floatValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.floatValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomColorField(Rect position, GUIContent label, SerializedProperty property, string Name)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.ColorField(Name, property.colorValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.colorValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomPopupColor(Rect position, GUIContent label, SerializedProperty property, string nameOfLabel, Type typeOfEnum, Color TextColor)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
string[] enumNamesList = System.Enum.GetNames(typeOfEnum);
|
||||
|
||||
var Style = new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter };
|
||||
Style.normal.textColor = TextColor;
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent(nameOfLabel), Style, GUILayout.Width(75));
|
||||
var newValue = EditorGUILayout.Popup("", property.intValue, enumNamesList, GUILayout.Width(65));
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void DrawString(string text, Vector3 worldPos, Color? colour = null)
|
||||
{
|
||||
GUIStyle style = new GUIStyle();
|
||||
style.fontSize = 14;
|
||||
style.fontStyle = FontStyle.Bold;
|
||||
style.normal.textColor = Color.white;
|
||||
|
||||
UnityEditor.Handles.BeginGUI();
|
||||
|
||||
var restoreColor = GUI.color;
|
||||
|
||||
if (colour.HasValue) GUI.color = colour.Value;
|
||||
var view = UnityEditor.SceneView.currentDrawingSceneView;
|
||||
Vector3 screenPos = view.camera.WorldToScreenPoint(worldPos);
|
||||
|
||||
if (screenPos.y < 0 || screenPos.y > Screen.height || screenPos.x < 0 || screenPos.x > Screen.width || screenPos.z < 0)
|
||||
{
|
||||
GUI.color = restoreColor;
|
||||
UnityEditor.Handles.EndGUI();
|
||||
return;
|
||||
}
|
||||
|
||||
Vector2 size = GUI.skin.label.CalcSize(new GUIContent(text));
|
||||
GUI.Label(new Rect(screenPos.x - (size.x / 2), -screenPos.y + view.position.height + 4, size.x, size.y), text, style);
|
||||
GUI.color = restoreColor;
|
||||
UnityEditor.Handles.EndGUI();
|
||||
}
|
||||
|
||||
public static bool Foldout(bool foldout, GUIContent content, bool toggleOnLabelClick, GUIStyle style)
|
||||
{
|
||||
Rect position = GUILayoutUtility.GetRect(40f, 40f, 16f, 22f, style);
|
||||
return EditorGUI.Foldout(position, foldout, content, toggleOnLabelClick, style);
|
||||
}
|
||||
public static bool Foldout(bool foldout, string content, bool toggleOnLabelClick, GUIStyle style)
|
||||
{
|
||||
return Foldout(foldout, new GUIContent(content), toggleOnLabelClick, style);
|
||||
}
|
||||
|
||||
public static void CustomTagField(Rect position, GUIContent label, SerializedProperty property, string Name)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.TagField(Name, property.stringValue);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.stringValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomEnumColor(Rect position, GUIContent label, SerializedProperty property, string Name, Color TextColor)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
var Style = new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter };
|
||||
Style.normal.textColor = TextColor;
|
||||
|
||||
EditorGUILayout.LabelField(new GUIContent(Name), Style, GUILayout.Width(50));
|
||||
var newValue = EditorGUILayout.Popup("", property.intValue, EmeraldDetection.StringFactionList.ToArray(), GUILayout.MaxWidth(100), GUILayout.ExpandWidth(true));
|
||||
|
||||
if (property.intValue == EmeraldDetection.StringFactionList.Count)
|
||||
{
|
||||
property.intValue -= 1;
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomEnum(Rect position, GUIContent label, SerializedProperty property, string Name)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.Popup(Name, property.intValue, EmeraldDetection.StringFactionList.ToArray());
|
||||
if (property.intValue == EmeraldDetection.StringFactionList.Count)
|
||||
{
|
||||
property.intValue -= 1;
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void FactionListEnum(Rect position, GUIContent label, SerializedProperty property, string Name, List<string> FationNames)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.Popup(Name, property.intValue, FationNames.ToArray());
|
||||
if (property.intValue == FationNames.Count)
|
||||
{
|
||||
property.intValue -= 1;
|
||||
}
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.intValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public static void CustomObjectField(Rect position, GUIContent label, SerializedProperty property, string Name, Type typeOfObject, bool IsEssential)
|
||||
{
|
||||
if (IsEssential && property.objectReferenceValue == null)
|
||||
{
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.LabelField("This field cannot be left blank", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var newValue = EditorGUILayout.ObjectField(Name, property.objectReferenceValue, typeOfObject, true);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
property.objectReferenceValue = newValue;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae3c31faf0fe44849af5e6fd47d62aa2
|
||||
timeCreated: 1548288821
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,126 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
[CustomPropertyDrawer(typeof(DrawIfAttribute))]
|
||||
public class DrawIfPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
#region Fields
|
||||
|
||||
// Reference to the attribute on the property.
|
||||
DrawIfAttribute drawIf;
|
||||
|
||||
// Field that is being compared.
|
||||
SerializedProperty comparedField;
|
||||
|
||||
#endregion
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (!ShowMe(property) && drawIf.disablingType == DrawIfAttribute.DisablingType.DontDraw)
|
||||
{
|
||||
return -EditorGUIUtility.standardVerticalSpacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.Generic)
|
||||
{
|
||||
int numChildren = 0;
|
||||
float totalHeight = 0.0f;
|
||||
|
||||
IEnumerator children = property.GetEnumerator();
|
||||
|
||||
while (children.MoveNext())
|
||||
{
|
||||
SerializedProperty child = children.Current as SerializedProperty;
|
||||
//if (child.displayName == property.displayName)
|
||||
|
||||
GUIContent childLabel = new GUIContent(child.displayName);
|
||||
totalHeight += EditorGUI.GetPropertyHeight(child, childLabel) + EditorGUIUtility.standardVerticalSpacing;
|
||||
numChildren++;
|
||||
}
|
||||
|
||||
// Remove extra space at end, (we only want spaces between items)
|
||||
totalHeight -= EditorGUIUtility.standardVerticalSpacing;
|
||||
|
||||
return totalHeight;
|
||||
}
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, label);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Errors default to showing the property.
|
||||
/// </summary>
|
||||
private bool ShowMe(SerializedProperty property)
|
||||
{
|
||||
drawIf = attribute as DrawIfAttribute;
|
||||
// Replace propertyname to the value from the parameter
|
||||
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawIf.comparedPropertyName) : drawIf.comparedPropertyName;
|
||||
|
||||
comparedField = property.serializedObject.FindProperty(path);
|
||||
|
||||
if (comparedField == null)
|
||||
{
|
||||
Debug.LogError("Cannot find property with name: " + path);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the value & compare based on types
|
||||
switch (comparedField.type)
|
||||
{ // Possible extend cases to support your own type
|
||||
case "bool":
|
||||
return comparedField.boolValue.Equals(drawIf.comparedValue);
|
||||
case "Enum":
|
||||
return (comparedField.intValue & (int)drawIf.comparedValue) != 0;
|
||||
default:
|
||||
Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
//Debug.Log(ShowMe(property) + " " + property.name);
|
||||
// If the condition is met, simply draw the field.
|
||||
if (ShowMe(property))
|
||||
{
|
||||
// A Generic type means a custom class...
|
||||
if (property.propertyType == SerializedPropertyType.Generic)
|
||||
{
|
||||
IEnumerator children = property.GetEnumerator();
|
||||
|
||||
Rect offsetPosition = position;
|
||||
|
||||
while (children.MoveNext())
|
||||
{
|
||||
SerializedProperty child = children.Current as SerializedProperty;
|
||||
|
||||
GUIContent childLabel = new GUIContent(child.displayName);
|
||||
|
||||
float childHeight = EditorGUI.GetPropertyHeight(child, childLabel);
|
||||
offsetPosition.height = childHeight;
|
||||
|
||||
EditorGUI.PropertyField(offsetPosition, child, childLabel);
|
||||
|
||||
offsetPosition.y += childHeight + EditorGUIUtility.standardVerticalSpacing;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.PropertyField(position, property, label);
|
||||
}
|
||||
|
||||
} //...check if the disabling type is read only. If it is, draw it disabled
|
||||
else if (drawIf.disablingType == DrawIfAttribute.DisablingType.ReadOnly)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUI.PropertyField(position, property, label);
|
||||
GUI.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d3b97296bcfe804da224341b49e98f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
//Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
|
||||
[CustomPropertyDrawer(typeof(DrawIfRangeAttribute))]
|
||||
public class DrawIfRangePropertyDrawer : PropertyDrawer
|
||||
{
|
||||
#region Fields
|
||||
|
||||
// Reference to the attribute on the property.
|
||||
DrawIfRangeAttribute drawRanageIf;
|
||||
|
||||
// Field that is being compared.
|
||||
SerializedProperty comparedField;
|
||||
|
||||
bool conditionMet;
|
||||
|
||||
#endregion
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
//if (!ShowMe(property))
|
||||
if (!conditionMet)
|
||||
return -2f;
|
||||
|
||||
// The height of the property should be defaulted to the default height.
|
||||
return base.GetPropertyHeight(property, label);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Errors default to showing the property.
|
||||
/// </summary>
|
||||
private bool ShowMe(SerializedProperty property)
|
||||
{
|
||||
drawRanageIf = attribute as DrawIfRangeAttribute;
|
||||
|
||||
// Replace propertyname to the value from the parameter
|
||||
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawRanageIf.comparedPropertyName) : drawRanageIf.comparedPropertyName;
|
||||
|
||||
comparedField = property.serializedObject.FindProperty(path);
|
||||
|
||||
if (comparedField == null)
|
||||
{
|
||||
Debug.LogError("Cannot find property with name: " + path);
|
||||
return true;
|
||||
}
|
||||
|
||||
// get the value & compare based on types
|
||||
switch (comparedField.type)
|
||||
{ // Possible extend cases to support your own type
|
||||
case "bool":
|
||||
return comparedField.boolValue.Equals(drawRanageIf.comparedValue);
|
||||
case "Enum":
|
||||
return comparedField.enumValueIndex.Equals((int)drawRanageIf.comparedValue);
|
||||
//case "int":
|
||||
//return comparedField.intValue.Equals(drawRanageIf.comparedValue);
|
||||
//case "float":
|
||||
//return comparedField.floatValue.Equals(drawRanageIf.comparedValue);
|
||||
default:
|
||||
//Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
// If the condition is met, simply draw the field.
|
||||
if (ShowMe(property))
|
||||
{
|
||||
Rect offsetPosition = position;
|
||||
offsetPosition.x = offsetPosition.x + 30;
|
||||
offsetPosition.width = offsetPosition.width - 30;
|
||||
|
||||
//string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawRanageIf.comparedPropertyName) : drawRanageIf.comparedPropertyName;
|
||||
//comparedField = property.serializedObject.FindProperty(path);
|
||||
var comparedFieldValue = comparedField;
|
||||
var comparedValue = drawRanageIf.comparedValue;
|
||||
//bool conditionMet = false;
|
||||
|
||||
if (comparedField.type == "int" || comparedField.type == "float")
|
||||
{
|
||||
var numericComparedFieldValue = (int)comparedField.intValue;
|
||||
var numericComparedValue = (int)(drawRanageIf.comparedValue);
|
||||
|
||||
// Is the condition met? Should the field be drawn?
|
||||
|
||||
//numericComparedValue = new NumericType(drawRanageIf.comparedValue);
|
||||
|
||||
// Compare the values to see if the condition is met.
|
||||
switch (drawRanageIf.comparisonType)
|
||||
{
|
||||
case DrawIfRangeAttribute.ComparisonType.Equals:
|
||||
if (comparedFieldValue.Equals(drawRanageIf.comparedValue))
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.NotEqual:
|
||||
if (!comparedFieldValue.Equals(drawRanageIf.comparedValue))
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.GreaterThan:
|
||||
if (numericComparedFieldValue > numericComparedValue)
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.SmallerThan:
|
||||
if (numericComparedFieldValue < numericComparedValue)
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.SmallerOrEqual:
|
||||
if (numericComparedFieldValue <= numericComparedValue)
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.GreaterOrEqual:
|
||||
if (numericComparedFieldValue >= numericComparedValue)
|
||||
conditionMet = true;
|
||||
else
|
||||
conditionMet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (comparedField.type == "bool")
|
||||
{
|
||||
switch (drawRanageIf.comparisonType)
|
||||
{
|
||||
case DrawIfRangeAttribute.ComparisonType.Equals:
|
||||
if (comparedFieldValue.Equals(drawRanageIf.comparedValue))
|
||||
conditionMet = true;
|
||||
break;
|
||||
|
||||
case DrawIfRangeAttribute.ComparisonType.NotEqual:
|
||||
if (!comparedFieldValue.Equals(drawRanageIf.comparedValue))
|
||||
conditionMet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (conditionMet)
|
||||
{
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
if (drawRanageIf.styleType == DrawIfRangeAttribute.StyleType.Default)
|
||||
{
|
||||
EditorGUI.PropertyField(offsetPosition, property, label);
|
||||
}
|
||||
else if (drawRanageIf.styleType == DrawIfRangeAttribute.StyleType.FloatSlider)
|
||||
{
|
||||
var newValue = EditorGUI.Slider(offsetPosition, label, property.floatValue, drawRanageIf.min, drawRanageIf.max);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.floatValue = newValue;
|
||||
}
|
||||
}
|
||||
else if (drawRanageIf.styleType == DrawIfRangeAttribute.StyleType.IntSlider)
|
||||
{
|
||||
var newValue = EditorGUI.IntSlider(offsetPosition, label, property.intValue, (int)drawRanageIf.min, (int)drawRanageIf.max);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.intValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e2f820768f3d774daf897a2e654bbc8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(LayerAttribute))]
|
||||
class LayerAttributeEditor : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
property.intValue = EditorGUI.LayerField(position, label, property.intValue);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 597dfc79675464b41a97904253e03255
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,12 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute to select a single layer.
|
||||
/// </summary>
|
||||
public class LayerAttribute : PropertyAttribute
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93381ae66b503b744bd1f51f095e20c9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
public class TagAttribute : PropertyAttribute
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(TagAttribute))]
|
||||
private class TagAttributeDrawer : PropertyDrawer
|
||||
{
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
|
||||
if (property.propertyType != SerializedPropertyType.String)
|
||||
{
|
||||
EditorGUI.HelpBox(position, $"{nameof(TagAttribute)} can only be used for strings!", MessageType.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UnityEditorInternal.InternalEditorUtility.tags.Contains(property.stringValue))
|
||||
{
|
||||
property.stringValue = "";
|
||||
}
|
||||
|
||||
var color = GUI.color;
|
||||
if (string.IsNullOrWhiteSpace(property.stringValue))
|
||||
{
|
||||
GUI.color = Color.red;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var TempTag = EditorGUI.TagField(position, label, property.stringValue);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
property.stringValue = TempTag;
|
||||
}
|
||||
|
||||
GUI.color = color;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef03a8f373691504990d19a6d264e9a1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,169 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
public class VisibilityCheck : MonoBehaviour
|
||||
{
|
||||
#region Variables
|
||||
[HideInInspector] public EmeraldOptimization EmeraldOptimization;
|
||||
[HideInInspector] public EmeraldSystem EmeraldComponent;
|
||||
IDamageable m_IDamageable;
|
||||
bool SystemActivated = false;
|
||||
float DeactivateTimer;
|
||||
#endregion
|
||||
|
||||
void Start()
|
||||
{
|
||||
m_IDamageable = EmeraldOptimization.GetComponent<IDamageable>();
|
||||
Invoke("InitializeDelay", 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to delay the initialization on start to avoid multiple renderer events from triggering.
|
||||
/// </summary>
|
||||
void InitializeDelay()
|
||||
{
|
||||
SystemActivated = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks each of an AI's LOD renderers, if an AI is using LODs and the optimization setting.
|
||||
/// </summary>
|
||||
public void CheckAIRenderers()
|
||||
{
|
||||
if (EmeraldOptimization.OptimizedState == EmeraldOptimization.OptimizedStates.Inactive && EmeraldOptimization.Initialized)
|
||||
{
|
||||
if (!EmeraldOptimization.Renderer1.isVisible && EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.One)
|
||||
{
|
||||
DeactivateTimer += Time.deltaTime;
|
||||
|
||||
if (EmeraldOptimization.UseDeactivateDelay == YesOrNo.Yes && DeactivateTimer >= EmeraldOptimization.DeactivateDelay || EmeraldOptimization.UseDeactivateDelay == YesOrNo.No)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
else if (!EmeraldOptimization.Renderer1.isVisible && !EmeraldOptimization.Renderer2.isVisible && EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Two)
|
||||
{
|
||||
DeactivateTimer += Time.deltaTime;
|
||||
|
||||
if (EmeraldOptimization.UseDeactivateDelay == YesOrNo.Yes && DeactivateTimer >= EmeraldOptimization.DeactivateDelay || EmeraldOptimization.UseDeactivateDelay == YesOrNo.No)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
else if (!EmeraldOptimization.Renderer1.isVisible && !EmeraldOptimization.Renderer2.isVisible && !EmeraldOptimization.Renderer3.isVisible && EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Three)
|
||||
{
|
||||
DeactivateTimer += Time.deltaTime;
|
||||
|
||||
if (EmeraldOptimization.UseDeactivateDelay == YesOrNo.Yes && DeactivateTimer >= EmeraldOptimization.DeactivateDelay || EmeraldOptimization.UseDeactivateDelay == YesOrNo.No)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
else if (!EmeraldOptimization.Renderer1.isVisible && !EmeraldOptimization.Renderer2.isVisible && !EmeraldOptimization.Renderer3.isVisible && !EmeraldOptimization.Renderer4.isVisible && EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Four)
|
||||
{
|
||||
DeactivateTimer += Time.deltaTime;
|
||||
|
||||
if (EmeraldOptimization.UseDeactivateDelay == YesOrNo.Yes && DeactivateTimer >= EmeraldOptimization.DeactivateDelay || EmeraldOptimization.UseDeactivateDelay == YesOrNo.No)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (EmeraldOptimization.OptimizedState == EmeraldOptimization.OptimizedStates.Active)
|
||||
{
|
||||
if (EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Two)
|
||||
{
|
||||
if (EmeraldOptimization.Renderer1.isVisible || EmeraldOptimization.Renderer2.isVisible)
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
else if (EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Three)
|
||||
{
|
||||
if (EmeraldOptimization.Renderer1.isVisible || EmeraldOptimization.Renderer2.isVisible || EmeraldOptimization.Renderer3.isVisible)
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
else if (EmeraldOptimization.TotalLODsRef == EmeraldOptimization.TotalLODsEnum.Four)
|
||||
{
|
||||
if (EmeraldOptimization.Renderer1.isVisible || EmeraldOptimization.Renderer2.isVisible || EmeraldOptimization.Renderer3.isVisible || EmeraldOptimization.Renderer4.isVisible)
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls when an AI is deactivated while using the optimization system.
|
||||
/// </summary>
|
||||
public void Deactivate()
|
||||
{
|
||||
if (!EmeraldComponent.AnimationComponent.IsDead && EmeraldComponent.CombatTarget == null && !EmeraldComponent.MovementComponent.ReturningToStartInProgress && EmeraldComponent.DetectionComponent.CurrentDetectionState == EmeraldDetection.DetectionStates.Unaware)
|
||||
{
|
||||
EmeraldComponent.CombatComponent.TargetDetectionActive = false;
|
||||
EmeraldComponent.AIBoxCollider.enabled = false;
|
||||
EmeraldComponent.DetectionComponent.enabled = false;
|
||||
EmeraldComponent.enabled = false;
|
||||
EmeraldOptimization.OptimizedState = EmeraldOptimization.OptimizedStates.Active;
|
||||
if (EmeraldComponent.UIComponent != null) EmeraldComponent.UIComponent.SetUI(false);
|
||||
if (EmeraldComponent.InverseKinematicsComponent != null) EmeraldComponent.InverseKinematicsComponent.DisableInverseKinematics();
|
||||
EmeraldComponent.m_NavMeshAgent.destination = transform.position + transform.forward * 0.5f;
|
||||
EmeraldComponent.AIAnimator.SetFloat("Speed", 0);
|
||||
EmeraldComponent.AIAnimator.enabled = false;
|
||||
DeactivateTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls when an AI is activated while using the optimization system.
|
||||
/// </summary>
|
||||
public void Activate()
|
||||
{
|
||||
if (m_IDamageable.Health > 0)
|
||||
{
|
||||
EmeraldComponent.CombatComponent.TargetDetectionActive = true;
|
||||
EmeraldComponent.AIBoxCollider.enabled = true;
|
||||
EmeraldComponent.DetectionComponent.enabled = true;
|
||||
EmeraldComponent.enabled = true;
|
||||
EmeraldComponent.AIAnimator.enabled = true;
|
||||
if (EmeraldComponent.InverseKinematicsComponent != null) EmeraldComponent.InverseKinematicsComponent.EnableInverseKinematics();
|
||||
EmeraldOptimization.OptimizedState = EmeraldOptimization.OptimizedStates.Inactive;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the AI's renderer becomes invisible.
|
||||
/// </summary>
|
||||
void OnBecameInvisible()
|
||||
{
|
||||
if (EmeraldComponent.AnimationComponent.IsDead) return;
|
||||
Invoke("Deactivate", EmeraldOptimization.DeactivateDelay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called once on start to allow the AI to be activated, but only if it is visible.
|
||||
/// </summary>
|
||||
void OnWillRenderObject()
|
||||
{
|
||||
if (EmeraldOptimization.OptimizedState == EmeraldOptimization.OptimizedStates.Active)
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called each time the AI's renderer becomes visible.
|
||||
/// </summary>
|
||||
void OnBecameVisible()
|
||||
{
|
||||
if (SystemActivated)
|
||||
{
|
||||
CancelInvoke();
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdb1d70374a80b74fbfbb46bd078d142
|
||||
timeCreated: 1507164265
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user