That depends on how you’d like to go about it. You can have a timer within the rotate and idle independently, use the Wait node, or make a call to an external timer helper which could use coroutines or any other kind of timer. I’ve made use of the Wait node in a few spots as a placeholder since I’ve got my own external timer class, but it works great by itself. The Wait node is from the example graph, but it is easy to replicate should you not have it and want to use it:

public class WaitAction : Action
{
public BlackboardVariable<float> SecondsToWait;
float m_Timer = 0.0f;
protected override Status OnStart()
{
m_Timer = 0.0f;
return Status.Running;
}
protected override Status OnUpdate()
{
m_Timer += Time.deltaTime;
if (m_Timer >= SecondsToWait)
{
return Status.Success;
}
return Status.Running;
}
}
If you’d like you have a MonoBehavior working for the Action you’d have to use a helper class. Depending on the helper you can have it on the agent, a reference to another object, use an event, or use a singleton to call it.
If it’s on the agent you can have a node need a reference to the Agent / Self and call Self.Value.GetComponent in the action class like with your sensory system.
For one of my managers that spawns my agents, I have it put the spawned agents into a list and then cycle through them to assign some values. Example:
public class NPCManager : MonoBehaviour
{
[SerializeField] private Transform _npcParent;
[SerializeField] private List<BehaviorGraphAgent> _npcGraphs;
private void SpawnTest()
{
SpawnNPCs();
_npcGraphs = _npcParent.GetComponentsInChildren<BehaviorGraphAgent>().ToList();
}
private void SetStates(int start, int length, AIState state)
{
for (int i = start; i < start + length; i++)
{
_npcGraphs[i].Blackboard.TrySetVariableValue("AIState", state);
_npcGraphs[i].Blackboard.TrySetVariableValue("NPCManager", transform.gameObject);
}
}
}
The Agents then sometimes use that reference to the manager to keep track of certain things in the world and could easily call a coroutine that way if wanted. They have to have that Blackboard variable already for the TrySetVariableValue to work.
You should be able to call any Singleton MonoBehavior or event from the Action as well and you could just call it that way.
public class ExampleTimers : Action
{
TimerUtil _timer;
bool _doneRotate = false;
protected override Status OnStart()
{
_timer = TimerManagerUtil.onTimerCreated?.Invoke();
_timer.SetupTimer(3.0f, ()=> TimerDone(_timer));
return Status.Running;
}
protected override Status OnUpdate()
{
if (_doneRotate)
{
return Status.Success;
}
return Status.Running;
}
private void TimerDone(TimerUtil timer)
{
TimerManagerUtil.onTimerRemove?.Invoke(timer);
_doneRotate = true;
}
protected override void OnEnd()
{
}
}
I don’t have a singleton example but it’d be similar. Essentially though you can get a reference to any monobehavior pretty easily and use that for an external one if you want to use a coroutine or any other kind of timer. Alternatively use a timer node or make a timer within the wanted node.