Task System
A possible way to influence the agent's behavior is to assign tasks to the agent which the agent then works on.
Tasks
Tasks are the elements which tell the agent what to do.
Structure
All tasks need to implement the IAgentTask interface. It determines the necessary methods that a task must have like StartExecution(Agent) to start the task's execution or Tick(Agent) which is called every frame during the execution.
Pre-Implemented Tasks
The Virtual Agents Framework contains an ever-growing collection of pre-implemented tasks. These tasks are meant as a starting point for composing behaviors of agents. Currently, the following tasks exist and can already be used:
- AgentAnimationTask: Play animations on the agent
- AgentMovementTask: Let the agent walk to a given location or follow an object dynamically
- AgentWaitTask: Let the agent wait for a specific amount of time
- AgentPickUpTask: Let the agent pickup an object next to them
- AgentDropTask: Let the agent drop an object or all objects that the agent is holding
- AgentAdaptiveGazeTask: Starts or stops the adaptive gaze feature. ### Adding Own Tasks
In addition to the pre-implemented tasks, developers can also add own tasks that implement the IAgentTask interface. It is recommended to inherit from the AgentBaseTask class when creating new tasks. This base class already contains a lot of common logic for tasks, like marking a task as finished and then automatically invoking the event that is defined in the interface.
If you have created a generic and configurable task that might be interesting to other developers, feel welcome to post a pull request on GitHub that contributes the task to the framework as a pre-implemented task.
Task Scheduling
Tasks are scheduled on agents using a priority queue. Each agent has a task manager which will evaluate the queue and start the execution of the next task.
Scheduling a Task Instance on an Agent
To assign a task to an agent, first create an instance of your task by calling its constructor.
MyTask myTask = new MyTask();
Configure the task as required, e.g., by passing arguments to the constructor or by setting properties. After that, call ScheduleTask(IAgentTask, Int32, String) to schedule the task on a specific agent. Optionally, you can set the priority of the task. By default, it is set to 0, so negative values will be executed after all other tasks and positive values take priority over default tasks. The higher the number the earlier the task will be executed. Moreover, you can provide a layer argument to specify which animation layer the task affects. The agent is set up with different layers so that multiple actions can happen in parallel. By default, the "Base Layer" is chosen, so it affects the entire body of the agent. For more information on parallel layers see the documentation on parallel tasks.
Shortcuts
In order to keep the code brief and understandable, it is not always necessary to create the task instance object yourself and to schedule it on the agent explicitly. For common actions, it is also possible to call one of the shortcut functions on the agent. Currently, the following shortcut functions exist:
-
- GoTo(Vector3, Int32): Let the agent walk to the specified coordinates.
- GoTo(Transform, Vector3, Int32): Let the agent walk to the specified transform of an object in the scene. You can add an optional offset so that the agent does not run into the object but stops next to it.
- GoTo(GameObject, Vector3, Int32, Boolean): Let the agent walk to the specified object in the scene. You can add an optional offset so that the agent does not run into the object but stops next to it. The agent can also follow an object dynamically, so that the agent will follow the object until it is reached. Partial incomplete paths will be allowed, when that option is enabled.
WaitForSeconds: The agent waits for the given amount of seconds.
- PlayAnimation: Play an animation for the given time.
Specify a start and stop trigger which will cause the animation to start and stop in the animator.
If you add you own animations, set them up in a way that there are transitions in and out of your animation with the start and stop triggers set as conditions for entering the transition.
Specifying a GameObject as an
aimTarget
for the animation, will start inverse kinematics (IK) on the specified layer. This can be used withNoAnimation
as a start trigger to start the IK with no animation or with animations that benefit from the IK, for example the providedpointingLeft
andpointingRight
animation. - PickUp: Pick up an item that is currently in reach of the agent, see items for more information
- GoToAndPickUp: Schedules an GoTo Task that makes the agent walk to the item before trying to pick it up
- DropItem: Drop the specified item if it is currently hold be the agent, if no item is specified, all items are dropped.
- GoToAndDropItem: Schedules an GoTo Task that makes the agent walk to the specified coordinates or transform before dropping the specified item or all items, if no item is specified.
- ActivateOrDeactivateAdaptiveGaze: Start or stops adaptive gazing until it is stopped or started again. This is realized with a task that only runs once. This also automatically adds a AdaptiveGaze component if the agent doesn't have one.
- StartAdaptiveGazeForTime: Schedule a task that starts adaptive gazing for the specified time and then deactivates it by scheduling a wait task between a start and stop task.