135 lines
3.8 KiB
C#
135 lines
3.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public class SubGoal
|
|
{
|
|
public Dictionary<string, int> goals;
|
|
public bool shouldRemove;
|
|
|
|
public SubGoal(string goalName, int value, bool shouldRemove)
|
|
{
|
|
goals = new Dictionary<string, int>
|
|
{
|
|
{ goalName, value }
|
|
};
|
|
this.shouldRemove = shouldRemove;
|
|
}
|
|
}
|
|
|
|
public class AI_Agent : MonoBehaviour
|
|
{
|
|
public List<AI_Action> actions = new List<AI_Action>();
|
|
public Dictionary<SubGoal, int> goals = new Dictionary<SubGoal, int>();
|
|
public AI_Inventory inventory = new AI_Inventory();
|
|
public AIStates agentWorldStates = new AIStates();
|
|
|
|
public float taskRange = 2.5f;
|
|
|
|
protected AI_Planner planner;
|
|
protected Queue<AI_Action> actionQueue;
|
|
protected AI_Action currentAction;
|
|
protected SubGoal currentGoal;
|
|
protected bool actionInvoked;
|
|
|
|
protected virtual void Start()
|
|
{
|
|
AI_Action[] actionsArray = GetComponents<AI_Action>();
|
|
foreach (AI_Action action in actionsArray)
|
|
{
|
|
actions.Add(action);
|
|
}
|
|
}
|
|
|
|
private void CompleteAction()
|
|
{
|
|
currentAction.isRunning = false;
|
|
currentAction.PostPerform();
|
|
actionInvoked = false;
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
Gizmos.color = Color.yellow;
|
|
Gizmos.DrawWireSphere(transform.position, taskRange);
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if(currentAction != null && currentAction.isRunning)
|
|
{
|
|
float distanceToTarget = Vector3.Distance(currentAction.target.transform.position, transform.position);
|
|
if(currentAction.agent.hasPath && distanceToTarget < taskRange)
|
|
{
|
|
if(!actionInvoked)
|
|
{
|
|
Invoke(nameof(CompleteAction), currentAction.duration);
|
|
actionInvoked = true;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(planner == null || actionQueue == null)
|
|
{
|
|
planner = new AI_Planner();
|
|
|
|
var sortedGoals = from entry in goals orderby entry.Value descending select entry;
|
|
|
|
foreach(KeyValuePair<SubGoal, int> subGoal in sortedGoals)
|
|
{
|
|
actionQueue = planner.Plan(actions, subGoal.Key.goals, agentWorldStates);
|
|
if (actionQueue != null)
|
|
{
|
|
currentGoal = subGoal.Key;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(actionQueue != null && actionQueue.Count == 0)
|
|
{
|
|
if(currentGoal.shouldRemove)
|
|
{
|
|
goals.Remove(currentGoal);
|
|
}
|
|
planner = null;
|
|
}
|
|
|
|
if (actionQueue != null && actionQueue.Count > 0)
|
|
{
|
|
currentAction = actionQueue.Dequeue();
|
|
if (currentAction.PrePerform())
|
|
{
|
|
if (currentAction.target == null && !string.IsNullOrEmpty(currentAction.targetTag))
|
|
{
|
|
currentAction.target = GameObject.FindWithTag(currentAction.targetTag);
|
|
}
|
|
|
|
if (currentAction.target != null)
|
|
{
|
|
currentAction.isRunning = true;
|
|
|
|
// Check for AI_Area component
|
|
AI_Area area = currentAction.target.GetComponent<AI_Area>();
|
|
Vector3 destination;
|
|
|
|
if (area != null)
|
|
{
|
|
destination = area.GetRandomPointInArea();
|
|
}
|
|
else
|
|
{
|
|
destination = currentAction.target.transform.position;
|
|
}
|
|
|
|
currentAction.agent.SetDestination(destination);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
actionQueue = null;
|
|
}
|
|
}
|
|
}
|
|
} |