diff --git a/Package/Runtime/CrashKonijn.Agent.Runtime/ActionBase.cs b/Package/Runtime/CrashKonijn.Agent.Runtime/ActionBase.cs index 3ffef73d..6c3d1068 100644 --- a/Package/Runtime/CrashKonijn.Agent.Runtime/ActionBase.cs +++ b/Package/Runtime/CrashKonijn.Agent.Runtime/ActionBase.cs @@ -8,39 +8,64 @@ public abstract class AgentActionBase { private IActionDisabler disabler; + /// + /// Gets the action data. + /// + /// The action data. public IActionData GetData() { return this.CreateData(); } + /// + /// Creates a new instance of action data. + /// + /// The created action data. public virtual TActionData CreateData() { return new TActionData(); } + /// + /// Gets the action properties. + /// public abstract TActionProperties Properties { get; } + /// + /// Called when the action is created. + /// public virtual void Created() { } + /// + /// Called when the action is started (when it is assigned to an agent). + /// + /// The agent. + /// The action data. public void Start(IMonoAgent agent, IActionData data) => this.Start(agent, (TActionData) data); + /// + /// Called when the action is started (when it is assigned to an agent). + /// + /// The agent. + /// The action data. public virtual void Start(IMonoAgent agent, TActionData data) { } + /// + /// Determines whether the action is enabled. This is used by the planner. + /// + /// The action receiver. + /// True if the action is enabled, otherwise false. public bool IsEnabled(IActionReceiver agent) { return this.IsEnabled(agent, agent.Injector); } - public void Enable() - { - this.disabler = null; - } - - public void Disable(IActionDisabler disabler) - { - this.disabler = disabler; - } - + /// + /// Determines whether the action is enabled. This is used by the planner. + /// + /// The action receiver. + /// The component references. + /// True if the action is enabled, otherwise false. public virtual bool IsEnabled(IActionReceiver receiver, IComponentReference references) { if (this.disabler == null) @@ -56,30 +81,97 @@ public virtual bool IsEnabled(IActionReceiver receiver, IComponentReference refe return true; } + /// + /// Enables the action. + /// + public void Enable() + { + this.disabler = null; + } + + /// + /// Disables the action. + /// + /// The action disabler. + public void Disable(IActionDisabler disabler) + { + this.disabler = disabler; + } + + /// + /// Called once before performing the action. Don't override this method, override the other BeforePerform method + /// instead. + /// + /// The agent. + /// The action data. public void BeforePerform(IMonoAgent agent, IActionData data) => this.BeforePerform(agent, (TActionData) data); + /// + /// Called once before performing the action. Override this method to implement custom logic. + /// + /// The agent. + /// The action data. public virtual void BeforePerform(IMonoAgent agent, TActionData data) { } + /// + /// Performs the action. Don't override this method, override the other Perform method instead. + /// + /// The agent. + /// The action data. + /// The action context. + /// The action run state. public IActionRunState Perform(IMonoAgent agent, IActionData data, IActionContext context) => this.Perform(agent, (TActionData) data, context); + /// + /// Performs the action with the specified action data. Use this method to implement custom logic. + /// + /// The agent. + /// The action data. + /// The action context. + /// The action run state. public abstract IActionRunState Perform(IMonoAgent agent, TActionData data, IActionContext context); + /// + /// Called when the action ends. This is called after the action is completed or stopped. + /// + /// The agent. + /// The action data. public virtual void End(IMonoAgent agent, TActionData data) { } + /// + /// Called when the action is stopped. Don't override this method, override the other Stop method instead. + /// + /// The agent. + /// The action data. public void Stop(IMonoAgent agent, IActionData data) { this.Stop(agent, (TActionData) data); this.End(agent, (TActionData) data); } + /// + /// Called when the action is stopped. Use this method to implement custom logic. + /// + /// The agent. + /// The action data. public virtual void Stop(IMonoAgent agent, TActionData data) { } + /// + /// Called when the action is completed. Don't override this method, override the other Complete method instead. + /// + /// The agent. + /// The action data. public void Complete(IMonoAgent agent, IActionData data) { this.Complete(agent, (TActionData) data); this.End(agent, (TActionData) data); } + /// + /// Called when the action is completed. Use this method to implement custom logic. + /// + /// The agent. + /// The action data. public virtual void Complete(IMonoAgent agent, TActionData data) { } } } diff --git a/Package/Runtime/CrashKonijn.Agent.Runtime/AgentBehaviour.cs b/Package/Runtime/CrashKonijn.Agent.Runtime/AgentBehaviour.cs index 015f715c..f39b693b 100644 --- a/Package/Runtime/CrashKonijn.Agent.Runtime/AgentBehaviour.cs +++ b/Package/Runtime/CrashKonijn.Agent.Runtime/AgentBehaviour.cs @@ -101,6 +101,9 @@ private void Update() this.Run(); } + /// + /// Runs the current action. This is called in the Update method. + /// public void Run() { if (this.ActionState.Action == null) @@ -165,6 +168,12 @@ private bool IsInRange() return this.ActionState.Action.IsInRange(this, distance, this.ActionState.Data, this.Injector); } + /// + /// Sets the action for the agent. This is mostly used by the action provider. + /// + /// The action provider. + /// The action to set. + /// The target of the action. public void SetAction(IActionProvider actionProvider, IAction action, ITarget target) { this.ActionProvider = actionProvider; @@ -188,6 +197,10 @@ public void SetAction(IActionProvider actionProvider, IAction action, ITarget ta this.Events.ActionStart(action); } + /// + /// Stops the current action. + /// + /// Whether to resolve for a new action after stopping. public void StopAction(bool resolveAction = true) { var action = this.ActionState.Action; @@ -201,6 +214,10 @@ public void StopAction(bool resolveAction = true) this.ResolveAction(); } + /// + /// Completes the current action. + /// + /// Whether to resolve for a new action after completing. public void CompleteAction(bool resolveAction = true) { var action = this.ActionState.Action; @@ -214,6 +231,9 @@ public void CompleteAction(bool resolveAction = true) this.ResolveAction(); } + /// + /// Will trigger try and resolve a new action from the action provider. + /// public void ResolveAction() { if (this.ActionProvider == null) diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionBase.cs index de0eabdc..676c3931 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionBase.cs @@ -22,6 +22,10 @@ public abstract class GoapActionBase : AgentActi public override TActionProperties Properties => this.Config.Properties as TActionProperties; + /// + /// Sets the configuration for the action. + /// + /// The action configuration. public void SetConfig(IActionConfig config) { this.Config = config; @@ -33,26 +37,57 @@ public virtual float GetCost(IActionReceiver agent, IComponentReference referenc return this.Config.BaseCost; } + /// + /// Returns the cost of the action. + /// + /// The action receiver. + /// The component references. + /// The target of the action. + /// The cost of the action. public virtual float GetCost(IActionReceiver agent, IComponentReference references, ITarget target) { return this.Config.BaseCost; } + /// + /// Gets the move mode for the action. + /// + /// The agent. + /// The move mode for the action. public ActionMoveMode GetMoveMode(IMonoAgent agent) { return this.Config.MoveMode; } + /// + /// Gets the stopping distance for the action. + /// + /// The stopping distance for the action. public virtual float GetStoppingDistance() { return this.Config.StoppingDistance; } + /// + /// Determines whether the agent is in range for the action. + /// + /// The agent. + /// The distance to the target. + /// The action data. + /// The component references. + /// True if the agent is in range, otherwise false. public virtual bool IsInRange(IMonoAgent agent, float distance, IActionData data, IComponentReference references) { return distance <= this.GetStoppingDistance(); } + /// + /// Determines whether the action is valid. Don't override this method, use IsValid(IActionReceiver agent, TActionData + /// data) instead. + /// + /// The action receiver. + /// The action data. + /// True if the action is valid, otherwise false. public bool IsValid(IActionReceiver agent, IActionData data) { if (agent.ActionProvider is not GoapActionProvider goapAgent) @@ -82,11 +117,24 @@ public bool IsValid(IActionReceiver agent, IActionData data) return this.IsValid(agent, (TActionData) data); } + /// + /// Determines whether the action is valid with the specified action data. This is the method you should overwrite (in + /// most instances). + /// + /// The action receiver. + /// The action data. + /// True if the action is valid, otherwise false. public virtual bool IsValid(IActionReceiver agent, TActionData data) { return true; } + /// + /// Determines whether the action is executable. + /// + /// The action receiver. + /// Whether the conditions are met. + /// True if the action is executable, otherwise false. public bool IsExecutable(IActionReceiver agent, bool conditionsMet) { var goapAgent = agent.Injector.GetCachedComponent(); diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionProvider.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionProvider.cs index 4bb4c76a..e1114387 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionProvider.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Behaviours/GoapActionProvider.cs @@ -100,6 +100,11 @@ private IGoalRequest GetRequestCache() return this.requestCache; } + /// + /// Requests a goal of type TGoal. + /// + /// The type of the goal. + /// Whether to resolve the action after requesting the goal. Defaults to true. public void RequestGoal(bool resolve = true) where TGoal : IGoal { @@ -112,6 +117,12 @@ public void RequestGoal(bool resolve = true) this.RequestGoal(request, resolve); } + /// + /// Requests two goals of types TGoal1 and TGoal2. + /// + /// The type of the first goal. + /// The type of the second goal. + /// Whether to resolve the action after requesting the goals. Defaults to true. public void RequestGoal(bool resolve = true) where TGoal1 : IGoal where TGoal2 : IGoal @@ -126,6 +137,13 @@ public void RequestGoal(bool resolve = true) this.RequestGoal(request, resolve); } + /// + /// Requests three goals of types TGoal1, TGoal2, and TGoal3. + /// + /// The type of the first goal. + /// The type of the second goal. + /// The type of the third goal. + /// Whether to resolve the action after requesting the goals. Defaults to true. public void RequestGoal(bool resolve = true) where TGoal1 : IGoal where TGoal2 : IGoal @@ -142,6 +160,14 @@ public void RequestGoal(bool resolve = true) this.RequestGoal(request, resolve); } + /// + /// Requests four goals of types TGoal1, TGoal2, TGoal3, and TGoal4. + /// + /// The type of the first goal. + /// The type of the second goal. + /// The type of the third goal. + /// The type of the fourth goal. + /// Whether to resolve the action after requesting the goals. Defaults to true. public void RequestGoal(bool resolve = true) where TGoal1 : IGoal where TGoal2 : IGoal @@ -160,6 +186,15 @@ public void RequestGoal(bool resolve = true) this.RequestGoal(request, resolve); } + /// + /// Requests five goals of types TGoal1, TGoal2, TGoal3, TGoal4, and TGoal5. + /// + /// The type of the first goal. + /// The type of the second goal. + /// The type of the third goal. + /// The type of the fourth goal. + /// The type of the fifth goal. + /// Whether to resolve the action after requesting the goals. Defaults to true. public void RequestGoal(bool resolve = true) where TGoal1 : IGoal where TGoal2 : IGoal @@ -181,6 +216,11 @@ public void RequestGoal(bool resolve = t this.RequestGoal(request, resolve); } + /// + /// Requests a specific goal. + /// + /// The goal to request. + /// Whether to resolve the action after requesting the goal. public void RequestGoal(IGoal goal, bool resolve) { this.ValidateSetup(); @@ -193,6 +233,11 @@ public void RequestGoal(IGoal goal, bool resolve) this.RequestGoal(request, resolve); } + /// + /// Requests a goal based on the provided goal request. This will allow you to request multiple goals at once. + /// + /// The goal request. + /// Whether to resolve the action after requesting the goal. public void RequestGoal(IGoalRequest request, bool resolve = true) { this.ValidateSetup(); @@ -228,6 +273,10 @@ public static bool AreEqual(List array1, List array2) return true; } + /// + /// Sets the action based on the provided goal result. This method is called by the resolver. + /// + /// The goal result. public void SetAction(IGoalResult result) { if (result == null) @@ -269,6 +318,9 @@ public override IActionReceiver Receiver } } + /// + /// Will try and resolve for a new action based on the current goal request. + /// public override void ResolveAction() { this.ValidateSetup(); @@ -277,11 +329,19 @@ public override void ResolveAction() this.Receiver.Timers.Resolve.Touch(); } + /// + /// Clears the current goal. + /// public void ClearGoal() { this.CurrentPlan = null; } + /// + /// Sets the distance multiplier for the agent. This is used by the resolver to calculate the cost of distance between + /// actions. + /// + /// The distance multiplier. public void SetDistanceMultiplier(float multiplier) { if (multiplier < 0f) @@ -290,6 +350,12 @@ public void SetDistanceMultiplier(float multiplier) this.DistanceMultiplier = multiplier; } + /// + /// Sets the distance multiplier for the agent based on speed, based on the assumption that speed is in units per + /// second and cost is similar to a second. + /// This is used by the resolver to calculate the cost of distance between actions. + /// + /// The distance multiplier. public void SetDistanceMultiplierSpeed(float speed) { if (speed <= 0f) @@ -307,6 +373,11 @@ private void ValidateSetup() throw new GoapException($"There is no ActionReceiver assigned to the agent '{this.name}'! You're probably missing the ActionProvider on the AgentBehaviour."); } + /// + /// Gets the actions of the specified type. + /// + /// The type of the actions. + /// A list of actions of the specified type. public List GetActions() where TAction : IGoapAction => this.AgentType.GetActions(); #region Obsolete Methods diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/ActionBuilder.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/ActionBuilder.cs index ecb0a432..a934be25 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/ActionBuilder.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/ActionBuilder.cs @@ -11,6 +11,11 @@ public class ActionBuilder : ActionBuilder { public ActionBuilder(WorldKeyBuilder worldKeyBuilder, TargetKeyBuilder targetKeyBuilder) : base(typeof(T), worldKeyBuilder, targetKeyBuilder) { } + /// + /// Sets the target key for the action. + /// + /// The type of the target key. + /// The current instance of . public ActionBuilder SetTarget() where TTargetKey : ITargetKey { @@ -18,30 +23,56 @@ public ActionBuilder SetTarget() return this; } + /// + /// Sets the base cost for the action. + /// + /// The base cost. + /// The current instance of . public ActionBuilder SetBaseCost(float baseCost) { this.config.BaseCost = baseCost; return this; } + /// + /// Sets whether the target should be validated when running the action. + /// + /// True if the target should be validated; otherwise, false. + /// The current instance of . public ActionBuilder SetValidateTarget(bool validate) { this.config.ValidateTarget = validate; return this; } + /// + /// Sets whether the action requires a target. + /// + /// True if the action requires a target; otherwise, false. + /// The current instance of . public ActionBuilder SetRequiresTarget(bool requiresTarget) { this.config.RequiresTarget = requiresTarget; return this; } + /// + /// Sets whether the conditions should be validated when running the action. + /// + /// True if the conditions should be validated; otherwise, false. + /// The current instance of . public ActionBuilder SetValidateConditions(bool validate) { this.config.ValidateConditions = validate; return this; } + /// + /// Sets the stopping distance for the action. This is the distance at which the action will stop moving towards the + /// target. + /// + /// The stopping distance. + /// The current instance of . public ActionBuilder SetStoppingDistance(float inRange) { this.config.StoppingDistance = inRange; @@ -55,12 +86,24 @@ public ActionBuilder SetInRange(float inRange) return this; } + /// + /// Sets the move mode for the action. + /// + /// The move mode. + /// The current instance of . public ActionBuilder SetMoveMode(ActionMoveMode moveMode) { this.config.MoveMode = moveMode; return this; } + /// + /// Adds a condition to the action. + /// + /// The type of the world key. + /// The comparison type. + /// The amount for the condition. + /// The current instance of . public ActionBuilder AddCondition(Comparison comparison, int amount) where TWorldKey : IWorldKey { @@ -87,6 +130,12 @@ public ActionBuilder AddEffect(bool increase) return this; } + /// + /// Adds an effect to the action. + /// + /// The type of the world key. + /// The effect type. + /// The current instance of . public ActionBuilder AddEffect(EffectType type) where TWorldKey : IWorldKey { @@ -99,6 +148,11 @@ public ActionBuilder AddEffect(EffectType type) return this; } + /// + /// Sets the properties for the action. + /// + /// The action properties. + /// The current instance of . public ActionBuilder SetProperties(IActionProperties properties) { this.ValidateProperties(properties); @@ -107,6 +161,11 @@ public ActionBuilder SetProperties(IActionProperties properties) return this; } + /// + /// Sets the callback for when the action is created. This can be used to set up the action with custom data. + /// + /// The callback action. + /// The current instance of . public ActionBuilder SetCallback(Action callback) { this.config.Callback = (obj) => callback((T) obj); diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/AgentTypeBuilder.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/AgentTypeBuilder.cs index 956a2406..606cceb1 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/AgentTypeBuilder.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/AgentTypeBuilder.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using CrashKonijn.Agent.Core; using CrashKonijn.Goap.Core; namespace CrashKonijn.Goap.Runtime @@ -18,6 +17,11 @@ public AgentTypeBuilder(string name) this.agentTypeConfig = new AgentTypeConfig(name); } + /// + /// Creates a new capability with the specified name. + /// + /// The name of the capability. + /// A new instance of . public CapabilityBuilder CreateCapability(string name) { var capabilityBuilder = new CapabilityBuilder(name); @@ -27,6 +31,11 @@ public CapabilityBuilder CreateCapability(string name) return capabilityBuilder; } + /// + /// Creates a new capability with the specified name and applies the given callback. + /// + /// The name of the capability. + /// The callback to apply to the capability builder. public void CreateCapability(string name, Action callback) { var capabilityBuilder = new CapabilityBuilder(name); @@ -36,37 +45,65 @@ public void CreateCapability(string name, Action callback) this.capabilityBuilders.Add(capabilityBuilder); } + /// + /// Adds a capability of the specified type. + /// + /// The type of the capability. public void AddCapability() where TCapability : CapabilityFactoryBase, new() { this.capabilityConfigs.Add(new TCapability().Create()); } + /// + /// Adds a capability using the specified capability factory. + /// + /// The capability factory. public void AddCapability(CapabilityFactoryBase capabilityFactory) { this.capabilityConfigs.Add(capabilityFactory.Create()); } + /// + /// Adds a capability using the specified mono capability factory. + /// + /// The mono capability factory. public void AddCapability(MonoCapabilityFactoryBase capabilityFactory) { this.capabilityConfigs.Add(capabilityFactory.Create()); } + /// + /// Adds a capability using the specified scriptable capability factory. + /// + /// The scriptable capability factory. public void AddCapability(ScriptableCapabilityFactoryBase capabilityFactory) { this.capabilityConfigs.Add(capabilityFactory.Create()); } + /// + /// Adds a capability using the specified capability builder. + /// + /// The capability builder. public void AddCapability(CapabilityBuilder capabilityBuilder) { this.capabilityConfigs.Add(capabilityBuilder.Build()); } + /// + /// Adds a capability using the specified capability config. + /// + /// The capability config. public void AddCapability(ICapabilityConfig capabilityConfig) { this.capabilityConfigs.Add(capabilityConfig); } + /// + /// Builds the agent type configuration. + /// + /// The built . public AgentTypeConfig Build() { this.capabilityConfigs.AddRange(this.capabilityBuilders.Select(x => x.Build())); @@ -80,87 +117,4 @@ public AgentTypeConfig Build() return this.agentTypeConfig; } } - - public class CapabilityBuilder - { - private readonly CapabilityConfig capabilityConfig; - private readonly List actionBuilders = new(); - private readonly List goalBuilders = new(); - private readonly List targetSensorBuilders = new(); - private readonly List worldSensorBuilders = new(); - private readonly List multiSensorBuilders = new(); - private readonly WorldKeyBuilder worldKeyBuilder = new(); - private readonly TargetKeyBuilder targetKeyBuilder = new(); - - public CapabilityBuilder(string name) - { - this.capabilityConfig = new CapabilityConfig(name); - } - - public ActionBuilder AddAction() - where TAction : IAction - { - var actionBuilder = ActionBuilder.Create(this.worldKeyBuilder, this.targetKeyBuilder); - - this.actionBuilders.Add(actionBuilder); - - return actionBuilder; - } - - public GoalBuilder AddGoal() - where TGoal : IGoal - { - var goalBuilder = GoalBuilder.Create(this.worldKeyBuilder); - - this.goalBuilders.Add(goalBuilder); - - return goalBuilder; - } - - public WorldSensorBuilder AddWorldSensor() - where TWorldSensor : IWorldSensor - { - var worldSensorBuilder = WorldSensorBuilder.Create(this.worldKeyBuilder); - - this.worldSensorBuilders.Add(worldSensorBuilder); - - return worldSensorBuilder; - } - - public TargetSensorBuilder AddTargetSensor() - where TTargetSensor : ITargetSensor - { - var targetSensorBuilder = TargetSensorBuilder.Create(this.targetKeyBuilder); - - this.targetSensorBuilders.Add(targetSensorBuilder); - - return targetSensorBuilder; - } - - public MultiSensorBuilder AddMultiSensor() - where TMultiSensor : IMultiSensor - { - var multiSensorBuilder = MultiSensorBuilder.Create(); - - this.multiSensorBuilders.Add(multiSensorBuilder); - - return multiSensorBuilder; - } - - public WorldKeyBuilder GetWorldKeyBuilder() - { - return this.worldKeyBuilder; - } - - public CapabilityConfig Build() - { - this.capabilityConfig.Actions = this.actionBuilders.Select(x => x.Build()).ToList(); - this.capabilityConfig.Goals = this.goalBuilders.Select(x => x.Build()).ToList(); - this.capabilityConfig.TargetSensors = this.targetSensorBuilders.Select(x => x.Build()).ToList(); - this.capabilityConfig.WorldSensors = this.worldSensorBuilders.Select(x => x.Build()).ToList(); - this.capabilityConfig.MultiSensors = this.multiSensorBuilders.Select(x => x.Build()).ToList(); - - return this.capabilityConfig; - } - } } diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs new file mode 100644 index 00000000..b6d39800 --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs @@ -0,0 +1,119 @@ +using System.Collections.Generic; +using System.Linq; +using CrashKonijn.Agent.Core; +using CrashKonijn.Goap.Core; + +namespace CrashKonijn.Goap.Runtime +{ + public class CapabilityBuilder + { + private readonly CapabilityConfig capabilityConfig; + private readonly List actionBuilders = new(); + private readonly List goalBuilders = new(); + private readonly List targetSensorBuilders = new(); + private readonly List worldSensorBuilders = new(); + private readonly List multiSensorBuilders = new(); + private readonly WorldKeyBuilder worldKeyBuilder = new(); + private readonly TargetKeyBuilder targetKeyBuilder = new(); + + public CapabilityBuilder(string name) + { + this.capabilityConfig = new CapabilityConfig(name); + } + + /// + /// Adds an action to the capability. + /// + /// The type of the action. + /// An instance of . + public ActionBuilder AddAction() + where TAction : IAction + { + var actionBuilder = ActionBuilder.Create(this.worldKeyBuilder, this.targetKeyBuilder); + + this.actionBuilders.Add(actionBuilder); + + return actionBuilder; + } + + /// + /// Adds a goal to the capability. + /// + /// The type of the goal. + /// An instance of . + public GoalBuilder AddGoal() + where TGoal : IGoal + { + var goalBuilder = GoalBuilder.Create(this.worldKeyBuilder); + + this.goalBuilders.Add(goalBuilder); + + return goalBuilder; + } + + /// + /// Adds a world sensor to the capability. + /// + /// The type of the world sensor. + /// An instance of . + public WorldSensorBuilder AddWorldSensor() + where TWorldSensor : IWorldSensor + { + var worldSensorBuilder = WorldSensorBuilder.Create(this.worldKeyBuilder); + + this.worldSensorBuilders.Add(worldSensorBuilder); + + return worldSensorBuilder; + } + + /// + /// Adds a target sensor to the capability. + /// + /// The type of the target sensor. + /// An instance of . + public TargetSensorBuilder AddTargetSensor() + where TTargetSensor : ITargetSensor + { + var targetSensorBuilder = TargetSensorBuilder.Create(this.targetKeyBuilder); + + this.targetSensorBuilders.Add(targetSensorBuilder); + + return targetSensorBuilder; + } + + /// + /// Adds a multi sensor to the capability. + /// + /// The type of the multi sensor. + /// An instance of . + public MultiSensorBuilder AddMultiSensor() + where TMultiSensor : IMultiSensor + { + var multiSensorBuilder = MultiSensorBuilder.Create(); + + this.multiSensorBuilders.Add(multiSensorBuilder); + + return multiSensorBuilder; + } + + public WorldKeyBuilder GetWorldKeyBuilder() + { + return this.worldKeyBuilder; + } + + /// + /// Builds the capability configuration. + /// + /// The built . + public CapabilityConfig Build() + { + this.capabilityConfig.Actions = this.actionBuilders.Select(x => x.Build()).ToList(); + this.capabilityConfig.Goals = this.goalBuilders.Select(x => x.Build()).ToList(); + this.capabilityConfig.TargetSensors = this.targetSensorBuilders.Select(x => x.Build()).ToList(); + this.capabilityConfig.WorldSensors = this.worldSensorBuilders.Select(x => x.Build()).ToList(); + this.capabilityConfig.MultiSensors = this.multiSensorBuilders.Select(x => x.Build()).ToList(); + + return this.capabilityConfig; + } + } +} diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs.meta b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs.meta new file mode 100644 index 00000000..d01004e4 --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/CapabilityBuilder.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: c4f5cdc8bd6a4a96b0b6454e88d8c672 +timeCreated: 1732617132 \ No newline at end of file diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/GoalBuilder.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/GoalBuilder.cs index d8c50d76..1f82d1a7 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/GoalBuilder.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Classes/Builders/GoalBuilder.cs @@ -9,12 +9,24 @@ public class GoalBuilder : GoalBuilder { public GoalBuilder(WorldKeyBuilder worldKeyBuilder) : base(typeof(T), worldKeyBuilder) { } + /// + /// Sets the base cost for the goal. + /// + /// The base cost. + /// The current instance of . public GoalBuilder SetBaseCost(float baseCost) { this.config.BaseCost = baseCost; return this; } + /// + /// Adds a condition to the goal. + /// + /// The type of the world key. + /// The comparison type. + /// The amount for the condition. + /// The current instance of . public GoalBuilder AddCondition(Comparison comparison, int amount) where TWorldKey : IWorldKey { @@ -22,6 +34,11 @@ public GoalBuilder AddCondition(Comparison comparison, int amount) return this; } + /// + /// Sets the callback for the goal. This will be called when the goal is created. + /// + /// The callback action. + /// The current instance of . public GoalBuilder SetCallback(Action callback) { this.config.Callback = (obj) => callback((T) obj); @@ -45,6 +62,10 @@ public GoalBuilder(Type type, WorldKeyBuilder worldKeyBuilder) }; } + /// + /// Builds the goal configuration. + /// + /// The built . public IGoalConfig Build() { this.config.Conditions = this.conditions; diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs new file mode 100644 index 00000000..eac8d8c8 --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs @@ -0,0 +1,17 @@ +using System; +using CrashKonijn.Goap.Core; + +namespace CrashKonijn.Goap.Runtime +{ + public class GlobalSensor : IGlobalSensor + { + public Action SenseMethod; + public Type Key { get; set; } + + public void Created() { } + + public Type[] GetKeys() => new[] { this.Key }; + + public void Sense(IWorldData data) => this.SenseMethod(data); + } +} diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs.meta b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs.meta new file mode 100644 index 00000000..2f5a21f1 --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalSensor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f483f943239147b48585b2bbc35ea739 +timeCreated: 1732616122 \ No newline at end of file diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalTargetSensorBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalTargetSensorBase.cs index bd368eaa..4ac462bb 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalTargetSensorBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalTargetSensorBase.cs @@ -13,8 +13,15 @@ public abstract class GlobalTargetSensorBase : IGlobalTargetSensor public void SetConfig(ITargetSensorConfig config) => this.Config = config; public Type[] GetKeys() => new[] { this.Key.GetType() }; + /// + /// Called when the sensor is created. + /// public abstract void Created(); + /// + /// Senses the world data using this sensor. Do not override this method. + /// + /// The world data. public void Sense(IWorldData worldData) { var state = worldData.GetTargetState(this.Key.GetType()); @@ -25,6 +32,11 @@ public void Sense(IWorldData worldData) worldData.SetTarget(this.Key, this.Sense(state?.Value)); } + /// + /// Senses the world data using the specified existing target. + /// + /// The existing target. (The previously returned instance by this sensor). + /// The sensed target. public abstract ITarget Sense(ITarget target); } } diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalWorldSensorBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalWorldSensorBase.cs index d08c18fd..ee91a431 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalWorldSensorBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/GlobalWorldSensorBase.cs @@ -10,9 +10,17 @@ public abstract class GlobalWorldSensorBase : IGlobalWorldSensor public IWorldSensorConfig Config { get; private set; } public void SetConfig(IWorldSensorConfig config) => this.Config = config; + /// + /// Called when the sensor is created. + /// public abstract void Created(); + public Type[] GetKeys() => new[] { this.Key.GetType() }; + /// + /// Senses the world data using this sensor. Don't override this method. + /// + /// The world data. public void Sense(IWorldData data) { var state = data.GetWorldState(this.Key.GetType()); @@ -23,6 +31,10 @@ public void Sense(IWorldData data) data.SetState(this.Key, this.Sense()); } + /// + /// Senses the world data. + /// + /// The sensed value. public abstract SenseValue Sense(); } } diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs new file mode 100644 index 00000000..82669476 --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs @@ -0,0 +1,20 @@ +using System; +using CrashKonijn.Agent.Core; +using CrashKonijn.Goap.Core; + +namespace CrashKonijn.Goap.Runtime +{ + public class LocalSensor : ILocalSensor + { + public Action SenseMethod; + public Type Key { get; set; } + + public Type[] GetKeys() => new[] { this.Key }; + + public void Created() { } + + public void Update() { } + + public void Sense(IWorldData data, IActionReceiver agent, IComponentReference references) => this.SenseMethod(data, agent, references); + } +} diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs.meta b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs.meta new file mode 100644 index 00000000..9a6a20af --- /dev/null +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalSensor.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8e25528c1c9441fcaec14dde1d3ae157 +timeCreated: 1732616122 \ No newline at end of file diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalTargetSensorBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalTargetSensorBase.cs index 5aabcdeb..e2b66e1c 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalTargetSensorBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalTargetSensorBase.cs @@ -15,6 +15,12 @@ public abstract class LocalTargetSensorBase : ILocalTargetSensor public abstract void Update(); public Type[] GetKeys() => new[] { this.Key.GetType() }; + /// + /// Senses the world data using this sensor. Don't override this method, override the other Sense method instead. + /// + /// The world data. + /// The action receiver. + /// The component references. public void Sense(IWorldData worldData, IActionReceiver agent, IComponentReference references) { var state = worldData.GetTargetState(this.Key.GetType()); @@ -25,6 +31,13 @@ public void Sense(IWorldData worldData, IActionReceiver agent, IComponentReferen worldData.SetTarget(this.Key, this.Sense(agent, references, state?.Value)); } + /// + /// Senses the world data using the specified action receiver, component references, and existing target. + /// + /// The action receiver. + /// Use this to get cached component references on the agent. + /// The existing target. (The previously returned instance by this sensor). + /// The sensed target. public abstract ITarget Sense(IActionReceiver agent, IComponentReference references, ITarget existingTarget); [Obsolete("This should not be used anymore! Use 'Sense(IActionReceiver agent, IComponentReference references, ITarget existingTarget) instead'")] diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalWorldSensorBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalWorldSensorBase.cs index 07421cf4..eb4c39e4 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalWorldSensorBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/LocalWorldSensorBase.cs @@ -11,11 +11,24 @@ public abstract class LocalWorldSensorBase : ILocalWorldSensor public IWorldSensorConfig Config { get; private set; } public void SetConfig(IWorldSensorConfig config) => this.Config = config; + /// + /// Called when the sensor is created. + /// public abstract void Created(); + /// + /// Called when the sensor needs to update. Use this for caching data. + /// public abstract void Update(); + public Type[] GetKeys() => new[] { this.Key.GetType() }; + /// + /// Senses the world data using this sensor. + /// + /// The world data. + /// The action receiver. + /// Use this to get cached component references on the agent public void Sense(IWorldData data, IActionReceiver agent, IComponentReference references) { var state = data.GetWorldState(this.Key.GetType()); @@ -26,6 +39,12 @@ public void Sense(IWorldData data, IActionReceiver agent, IComponentReference re data.SetState(this.Key, this.Sense(agent, references)); } + /// + /// Senses the world data using the specified action receiver and component references. + /// + /// The action receiver. + /// Use this to get cached component references on the agent. + /// The sensed value. public virtual SenseValue Sense(IActionReceiver agent, IComponentReference references) { #pragma warning disable CS0618 // Type or member is obsolete diff --git a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/MultiSensorBase.cs b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/MultiSensorBase.cs index 21cdd577..f7082836 100644 --- a/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/MultiSensorBase.cs +++ b/Package/Runtime/CrashKonijn.Goap.Runtime/Sensors/MultiSensorBase.cs @@ -4,6 +4,7 @@ using System.Linq; using CrashKonijn.Agent.Core; using CrashKonijn.Goap.Core; +using Debug = UnityEngine.Debug; namespace CrashKonijn.Goap.Runtime { @@ -14,16 +15,31 @@ public abstract class MultiSensorBase : IMultiSensor public Dictionary LocalSensors { get; private set; } = new(); public Dictionary GlobalSensors { get; private set; } = new(); + /// + /// Sets the configuration for the multi-sensor. + /// + /// The multi-sensor configuration. public void SetConfig(IMultiSensorConfig config) { this.Config = config; } public Type Key { get; set; } + + /// + /// Called when the sensor is created. Don't use this method to add sensors, use the constructor instead. + /// public abstract void Created(); + /// + /// Called when the sensor should update. Use this for caching or other performance optimizations. + /// public abstract void Update(); + /// + /// Gets the keys of the sensors. + /// + /// An array of sensor keys. public Type[] GetKeys() { var keys = new List(); @@ -41,6 +57,10 @@ public Type[] GetKeys() return keys.ToArray(); } + /// + /// Senses the world data using global sensors. + /// + /// The world data. public void Sense(IWorldData data) { foreach (var sensor in this.GlobalSensors.Values) @@ -49,6 +69,11 @@ public void Sense(IWorldData data) } } + /// + /// Senses the world data using specific global sensors. + /// + /// The world data. + /// The keys of the sensors to use. public void Sense(IWorldData data, Type[] keys) { foreach (var key in keys) @@ -60,6 +85,12 @@ public void Sense(IWorldData data, Type[] keys) } } + /// + /// Senses the world data using local sensors. + /// + /// The world data. + /// The action receiver. + /// The component references. public void Sense(IWorldData data, IActionReceiver agent, IComponentReference references) { foreach (var sensor in this.LocalSensors.Values) @@ -68,6 +99,13 @@ public void Sense(IWorldData data, IActionReceiver agent, IComponentReference re } } + /// + /// Senses the world data using specific local sensors. + /// + /// The world data. + /// The action receiver. + /// The component references. + /// The keys of the sensors to use. public void Sense(IWorldData data, IActionReceiver agent, IComponentReference references, Type[] keys) { foreach (var key in keys) @@ -79,6 +117,12 @@ public void Sense(IWorldData data, IActionReceiver agent, IComponentReference re } } + /// + /// Adds a local world sensor. + /// + /// The type of the world key. + /// The sense function. + /// The sensor timer. public void AddLocalWorldSensor(Func sense, ISensorTimer timer = null) where TKey : IWorldKey { @@ -101,6 +145,12 @@ public void AddLocalWorldSensor(Func + /// Adds a global world sensor. + /// + /// The type of the world key. + /// The sense function. + /// The sensor timer. public void AddGlobalWorldSensor(Func sense, ISensorTimer timer = null) where TKey : IWorldKey { @@ -123,6 +173,12 @@ public void AddGlobalWorldSensor(Func sense, ISensorTimer time }); } + /// + /// Adds a local target sensor. + /// + /// The type of the target key. + /// The sense function. + /// The sensor timer. public void AddLocalTargetSensor(Func sense, ISensorTimer timer = null) where TKey : ITargetKey { @@ -145,6 +201,12 @@ public void AddLocalTargetSensor(Func + /// Adds a global target sensor. + /// + /// The type of the target key. + /// The sense function. + /// The sensor timer. public void AddGlobalTargetSensor(Func sense, ISensorTimer timer = null) where TKey : ITargetKey { @@ -167,6 +229,10 @@ public void AddGlobalTargetSensor(Func sense, ISensorTim }); } + /// + /// Gets the names of the sensors. + /// + /// An array of sensor names. public string[] GetSensors() { var sensors = new List(); @@ -197,34 +263,8 @@ private void ValidateCalledFromConstructor() ); if (!calledFromConstructor) - UnityEngine.Debug.LogWarning("Multi sensor registration must be added from the constructor of the sensor, not the Created method."); + Debug.LogWarning("Multi sensor registration must be added from the constructor of the sensor, not the Created method."); #endif } } - - public class GlobalSensor : IGlobalSensor - { - public Action SenseMethod; - public Type Key { get; set; } - - public void Created() { } - - public Type[] GetKeys() => new[] { this.Key }; - - public void Sense(IWorldData data) => this.SenseMethod(data); - } - - public class LocalSensor : ILocalSensor - { - public Action SenseMethod; - public Type Key { get; set; } - - public Type[] GetKeys() => new[] { this.Key }; - - public void Created() { } - - public void Update() { } - - public void Sense(IWorldData data, IActionReceiver agent, IComponentReference references) => this.SenseMethod(data, agent, references); - } }