public virtual IEnumerator StoppingCoroutine(AgentAction action)
 {
     yield break;
 }
 public virtual IEnumerator OnStop(AgentAction action)
 {
     yield break;
 }
 public virtual IEnumerator OnActionPost(AgentAction action)
 {
     yield break;
 }
 public virtual IEnumerator PerformAction(AgentAction action)
 {
     yield break;
 }
 public abstract IEnumerator InterpretAction(AgentAction action);
 public abstract string ScreenShotName(AgentAction action);
        /// <summary>
        /// The call to actually perform replay of an action.
        /// </summary>
        /// <param name="action"></param>
        //public IEnumerator RunAction(AgentAction action) {
        //    while (!Ready) { yield return 0; }

        //    Debug.LogFormat("Running:{0}",action);
        //    //Debug.Log("runstate " +action);
        //    Time.timeScale = 1.0f;

        //    //interpreter.ResetInterpretation();

        //    if (!InstantiateState(action)) {
        //        Debug.LogWarning("Instatiate State returned false!");
        //        if (Running) {
        //            yield return StartCoroutine(GetNextAction());
        //        }
        //        done = true;
        //        yield break;
        //    }
        //    PerformAction(action);

        //    extender.OnActionPost(action);

        //    //Time.timeScale = timeAcceleraton;
        //    StartCoroutine(WaitForStop(action));
        //}

        //TODO instantiate state is going to need to failure more gracefully in
        //projective replay. Currently it returns a failure if it can't find an
        //object in the state and that won't work if that object just doesn't exist anymore.

        /// <summary>
        /// Instantiates the state described by the action.
        /// Returns true if the state was successfully instantiated.
        /// Otherwise returns false if the state could not be instantiated normally
        /// because one or more of the elements could not be found in the scene.
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        //private bool InstantiateState(AgentAction action) {
        //    if (action.Equals(AgentAction.NullAction))
        //        return false;

        //    if (action.StateObject != null) {
        //        foreach (JObject entry in action.StateObject["Objects"]) {
        //            ReplayBehavior rb = extender.AssumeState(entry, action);
        //            if (rb != null) {
        //                rb.AddTag(RAEConstants.RAE_STATE);
        //            }
        //        }
        //    }
        //    return true;
        //}

        /// <summary>
        /// Retrieves a particular object by name to be altered in assuming state.
        /// The function will first ask the replay extender for the object in case
        /// special processing is necessary before trying to look for an object with
        /// a given name.
        /// </summary>
        /// <param name="node"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        //private GameObject RetrieveGameObject(JObject node, AgentAction action) {
        //    GameObject ret = extender.RetrieveGameObject(node, action);
        //    if (ret == null) {
        //        ret = GameObject.Find(node[RAEConstants.NAME].ToString());
        //    }
        //    return ret;
        //}

        //private void PerformAction(AgentAction action) {
        //    if (action.Equals(AgentAction.NullAction))
        //        return;

        //    extender.PerformAction(action);
        //}

        IEnumerator WaitForStop(AgentAction action)
        {
            Rigidbody[] state = MultiTag.FindAnyComponentsWithTags <Rigidbody>(RAEConstants.RAE_STATE, RAEConstants.RAE_ACTION);

            float callTime = Time.time;

            switch (stopCondition)
            {
            case StoppingCondition.Instant:
                Time.timeScale = NormalSpeed;
                yield return(new WaitForFixedUpdate());

                break;

            case StoppingCondition.WaitForStop:
                bool allSleeping = false;
                while (!allSleeping)
                {
                    allSleeping = true;
                    if (Time.time - callTime > timeOut)
                    {
                        break;
                    }

                    foreach (Rigidbody rigidbody in state)
                    {
                        if (rigidbody != null & !rigidbody.IsSleeping())
                        {
                            allSleeping = false;
                            break;
                        }
                    }
                    yield return(new WaitForFixedUpdate());
                }
                break;

            case StoppingCondition.TimeOut:
                while (Time.time - callTime < timeOut)
                {
                    yield return(null);
                }
                break;

            case StoppingCondition.Simulate:
                float delay = timeOut;
                if (agent.Next.IsSameAttempt(agent.CurrentAction))
                {
                    TimeSpan timeToNext = agent.Next.Time - agent.CurrentAction.Time;
                    delay = Mathf.Min(timeOut, (float)timeToNext.TotalSeconds);
                }
                while (Time.time - callTime < delay)
                {
                    yield return(new WaitForFixedUpdate());
                }
                break;

            case StoppingCondition.Custom:
                yield return(StartCoroutine(extender.StoppingCoroutine(action)));

                break;
            }
            Time.timeScale = PauseSpeed;
            //yield return StartCoroutine(Stop(action));
            yield break;
        }