title: Triggers and Actions for Creature AI
body: <p>Despite my creature AI working (for the most part), I feel like the way I've set it up is terribly inefficient and likely committing some programming sins. I want to rewrite it to be more clean, efficient, and easier to maintain but I'm not exactly sure where to begin. </p>
  
  <p>In my creature AI, I have a list of triggers, such as OnSpawn, OnDeath, or OnCollisionEnter. Within each trigger is a list of actions such as "Cast a Spell" or "Play an Animation". When a trigger's conditions are met, its list of actions are processed to check if it's not already in our processing list, adds it, and then plays their associated actions. When the trigger's conditions are not met, the list of actions are removed from this process list, and similarly processes through some remove functions to clean up behavior.</p>
  
  <p>Some code that I've simplified:</p>
  
  <pre><code>    void Update()
      {
          if (canAct &amp;&amp; !dead)
          {
              CheckTriggers();
              PlayAllActions();
         }
       }
  
  
     private void CheckTriggers()
      {
          for (int i = 0; i &lt; actions.Length; i++)
          {
              switch (actions[i].trigger)
              {
                  case ActionTrigger.Trigger.OnCollisionEnter:
                      if (isColliding)
                          AddActionList(actions[i].actionSetList);
                      else
                          RemoveActionList(actions[i].actionSetList);
                      break;
  
                  case ActionTrigger.Trigger.UponBeingAttacked:
                      if (hasBeenAttacked)
                          AddActionList(actions[i].actionSetList);
                      break;
              }
          }
      }
  
      public void AddActionList(ActionSetList actionSetList)
      {
          bool containsItem = existingActionsList.Any(item =&gt; item == actionSetList);
          if (containsItem)
              return;
  
          existingActionsList.Add(actionSetList);
      }
  
      private void PlayAllActions()
      {
          if (existingActionsList.Count &gt; 0)
              for (int i = 0; i &lt; existingActionsList.Count; i++)
                  ActionPlayEffect(existingActionsList[i]);
      }
  
      public void ActionPlayEffect(ActionSetList actionSetList)
      {
          for (int i = 0; i &lt; actionSetList.Length; i++)
          {
              switch (actionSetList[i].type)
              {
                  case ActionSet.Type.CastSpell:
                      if (spellRoutine == null &amp;&amp; actionSetList[i].cooldownTimeRemaining &lt;= 0)
                          spellRoutine = StartCoroutine(Cast(actionSetList[i]));
                      break;
  
                  case ActionSet.Type.PlayAnim:
                      if (!isInActionPose)
                      {
                          animator.SetTrigger("ActionTrigger");
                          animator.SetInteger("Action", (int)actionSetList[i].animToPlay+1);
                          isInActionPose = true;
                      }
                      break;
              }
          }
      }
  
      public void RemoveActionList(ActionSetList actionSetList)
      {
          bool containsItem = existingActionsList.Any(item =&gt; item == actionSetList);
          if (containsItem)
          {
              ActionRemoveEffect(actionSetList);
              existingActionsList.Remove(actionSetList);
          }
      }
  
      public void ActionRemoveEffect(ActionSetList actionSetList)
      {
          for (int i = 0; i &lt; actionSetList.Length; i++)
          {
              switch (actionSetList[i].type)
              {
                  case ActionSet.Type.CastSpell:
                      CancelCast();
                      break;
  
                  case ActionSet.Type.PlayAnim:
                      animator.SetTrigger("ActionTrigger");
                      animator.SetInteger("Action", 0);
                      isInActionPose = false;
                      break;
              }
          }
      }
  
  </code></pre>
  
  <p>What can I do to build a more efficient creature AI?</p>