Emerald AI Wiki
  • Home
  • Getting Started
    • Included Demo Scenes
      • Shooter AI Demo
      • Melee Combat Demo
      • Ranged Combat Demo
      • Summoning AI Demo
      • Healing Demo
      • Patrolling Demo
      • Inverse Kinematics Demo
      • Ragdoll Demo
      • Grenade Demo
      • Footsteps Demo
      • Random Waypoints Demo
      • Dynamic Wandering Demo
      • Health Bar Demo
      • Alignment Demo
      • Explosion Damage Demo
      • Sound Detection Demo
      • Fleeing Demo
      • Mouse Movement Demo
      • Companion Demo
      • Equippable Weapon Demo
      • Optimization Demo
      • Working Villager Demo
      • Debugging Demo Scene
    • Getting Started
    • Baking NavMesh
    • Setting up a Player with Emerald AI
    • Upgrading to URP and HDRP
    • Difference Between Emerald AI 3.0 and Emerald AI 2025
  • Help
    • Solutions to Possible Issues
    • Using the Wiki Search Tool
    • Release Notes
    • Support
  • Emerald Components (Required)
    • Animation Component
      • Creating an Animation Profile
      • Opening the Animation Viewer
    • Behaviors Component
      • Creating an Aggressive AI
      • Creating a Companion AI
      • Creating a Cautious AI
      • Creating a Coward AI
      • Creating a Passive AI
      • Creating a Pet AI
      • Creating Custom AI Behaviors
    • Combat Component
      • Assigning Combat Actions
      • Assigning Attack Transforms
      • Assigning Ability Objects
      • Weapon Type Amounts
    • Detection Component
      • Applying a Head Transform
      • Setting up the Detection Layers and Player Tag
      • Faction Relations
    • Movement Component
      • Using the Align AI Settings
      • Using the Dynamic Wander Type
      • Using the Waypoints Wander Type
      • Using the Stationary Wander Type
      • Using the Destination Wander Type
    • Health Component
      • Setting up an AI's Health
      • Setting up an AI's Hit Effects
    • Sounds Component
      • Creating an AI's Sound Profile
  • Emerald Components (Optional)
    • Adding and Removing Optional Components
    • Cover Component
      • Applying the Cover Component
      • Setting up the Cover Component
      • Setting up Cover Nodes
    • Debugger Component
      • Applying the Debugger Component
      • Drawing an AI's Path
      • Drawing an AI's Destination
      • Drawing an AI's Line of Sight
      • Drawing an AI's Undetected Targets Line
      • Debug Log Targets
      • Debug Log Current Obstruction
    • Decal Component
      • Applying the Decals Component
      • Setting up the Decals Component
    • Events Component
      • Applying the Events Component
      • Creating an Event Through the Editor
      • Creating an Event Through Code
    • Footsteps Component
      • Applying the Footsteps Component
      • Setting up the Footsteps Component
    • Inverse Kinematics Component
      • Applying the IK Component
      • Creating an Animation Rig and Multi-Aim Constraint
      • More Info on the Animation Rigging Package
    • Items Component
      • Applying the Items Component
      • Creating Equippable Weapons
    • Location Based Damage Component
      • Applying the LBD Component
      • Assigning Colliders to the LBD Component
      • Damaging the LBD Component
    • Optimization Component
      • Applying the Optimization Component
      • Setting up the Optimization Component
    • Sound Detector Component
      • Applying the Sound Detector Component
      • Understanding the Sound Detector Settings
      • Using an Attract Modifier
    • Target Position Modifier Component
      • Setting up the TPM Component on an AI
      • Setting up the TPM Component on a Player
    • UI Component
      • Applying the UI Component
      • Setting up the UI Component
    • Weapon Collision Component
      • Applying the Weapon Collision Component
      • Setting up the Weapon Collision Component
  • API
    • Accessing the EmeraldAPI Script
    • Available API
      • Movement API
      • Combat API
      • Faction API
      • Sound API
      • Animation API
      • UI API
      • Detection API
      • Behaviors API
      • Health API
      • Items API
    • Damaging an AI
    • Damaging a Custom Character Controller
    • Using the Built-in Object Pooling
  • Emerald Profiles & Objects
    • Ability Object
      • Bullet Projectile Ability
      • Grenade Ability
      • General Projectile Ability
      • Ground Projectile Ability
      • Aerial Projectile Ability
      • Arrow Projectile Ability
      • Melee Ability
      • Teleport Ability
      • Summon Ability
      • Healing Ability
      • Area of Effect Ability
      • The Collider Module
      • The Damage Module
    • Combat Action Object
      • Blocking Combat Action
      • Dodge Combat Action
      • Strafe Combat Action
      • Random Movement Combat Action
      • Switch Target Combat Action
      • Creating Custom Combat Actions Through Code
    • Reaction Object
      • Creating a Reaction Object
      • Included Reaction Objects
    • Animation Profile
      • Creating an Animator Controller
      • Applying Animations
      • Regenerate Animator Controllers
      • Copying Animation Profiles
    • Sound Profile
      • Creating an AI's Sound Profile
      • Setting up Footstep Sounds
      • Setting up Attack Sounds
      • Setting up Warning Sounds
      • Setting up Death Sounds
    • Waypoint Profile
    • Footstep Surface Object
      • Creating a new Footstep Surface Object
      • Setting up a Footstep Surface Object
  • Emerald Managers
    • Setup Manager
      • Setting up an AI with the Setup Manager
    • AI Duplicator Manager
      • Duplicating an AI
    • Animation Viewer Manager
      • Opening the Animation Viewer
      • Previewing Animations
      • Creating and Applying Animation Events
      • Creating Attack Animation Events
    • Faction Manager
      • Modifying Factions Through the Faction Manager
    • Combat Text Manager
      • Adjusting the Combat Text Settings
      • Accessing the Combat Text System Through Code
  • Integrations
    • Integrations
      • Final IK
      • Invector
      • FPS Engine
      • Dialogue System
      • Quest Machine
      • Love/Hate
Powered by GitBook
On this page

Was this helpful?

  1. Emerald Profiles & Objects
  2. Combat Action Object

Creating Custom Combat Actions Through Code

Note: It is expected that you have C# coding knowledge before proceeding.

Combat Actions are created through the EmeraldAction class and allows users to create their own custom Combat Actions through a derived class. This is done through Scriptable Objects.

Each Combat Action has a derived UpdateAction function is updated through the Combat Component. Users can override this function to trigger their own functionality. All of the included Combat Actions were created using this method. Feel free to use or build upon these included examples.

For creating your first Combat Action, start off with the example below. This monitors the Enter Conditions to see if the Execute function can be called. When it can, start a coroutine that sets the action to true, debug logs a random number to the Unity Console, wait 1 second, do the same thing, and reset the cooldown and action state.

Each function is instanced to the AI that is passed through the UpdateAction function, however, this does not allow the usage of local variables. The ActionsClass contains helpful variables that users can use as local variables. You can see the Blocking, Strafing, and Dodging Combat Actions for examples utilizing this.

Coroutines can be used through ScriptableObjects by using the MonoBehavior of the passed EmeraldComponent. This also allows users to use local variables within the Coroutine.

Note: This example action script is included with Emerald AI 2024.

using UnityEngine;
using System.Collections;

namespace EmeraldAI
{
    /// <summary>
    /// An example Combat Action that Debug Logs a random number to the Unity Console.
    /// </summary>
    [CreateAssetMenu(fileName = "Example Action", menuName = "Emerald AI/Combat Action/Example Action")]
    public class ExampleActionUpdated : EmeraldAction
    {
        /// <summary>
        /// Continiously updates the EmeraldAction. This acts like an Update function that can run 
        /// within this action using the information from the passed EmeraldComponent and its ActionClass.
        /// </summary>
        public override void UpdateAction(EmeraldSystem EmeraldComponent, ActionsClass ActionClass)
        {
            if (!CanExecute(EmeraldComponent, ActionClass))
                return;

            Execute(EmeraldComponent, ActionClass);
        }

        /// <summary>
        /// Conditions required for the EmeraldAction to execute.
        /// </summary>
        bool CanExecute(EmeraldSystem EmeraldComponent, ActionsClass ActionClass)
        {
            var Conditions = (((int)EnterConditions) & ((int)EmeraldComponent.AnimationComponent.CurrentAnimationState)) != 0;
            return ActionClass.CooldownLengthTimer >= CooldownLength && Conditions && !ActionClass.IsActive;
        }

        /// <summary>
        /// Executes the Action because all conditions from CanExecute have been met.
        /// </summary>
        void Execute(EmeraldSystem EmeraldComponent, ActionsClass ActionClass)
        {
            //Use the monobehavior from EmeraldComponent to create an individual coroutine. This can allow localized variables if needed.
            EmeraldComponent.GetComponent<MonoBehaviour>().StartCoroutine(cAction(EmeraldComponent, ActionClass));
        }

        IEnumerator cAction(EmeraldSystem EmeraldComponent, ActionsClass ActionClass)
        {
            //Set the Action as active
            ActionClass.IsActive = true;

            //Debug log a random number using a local variable from the passed EmeraldComponent's MonoBehaviour.
            int LocalVariableExample = Random.Range(0, 256);
            Debug.Log(EmeraldComponent.gameObject.name + "  " + LocalVariableExample);

            //Wait 1 second
            yield return new WaitForSeconds(1);

            //After waiting a second, do the same thing.
            LocalVariableExample = Random.Range(0, 256);
            Debug.Log(EmeraldComponent.gameObject.name + "  " + LocalVariableExample);

            //Reset the cooldown timer and set the IsActive to false
            ActionClass.CooldownLengthTimer = 0;
            ActionClass.IsActive = false;
        }
    }
}

Last updated 1 year ago

Was this helpful?