Skip to content

Instantly share code, notes, and snippets.

@dinukapj
Last active July 4, 2021 17:47
Show Gist options
  • Save dinukapj/25931d44c003728a46e6b0cba76da8fa to your computer and use it in GitHub Desktop.
Save dinukapj/25931d44c003728a46e6b0cba76da8fa to your computer and use it in GitHub Desktop.
Goal Oriented Action Planning. Simple implementation of GOAP in Unity 3D
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using System;
public class Goaper : MonoBehaviour
{
[TitleGroup("Parameters")]
[OnValueChanged("OnParameterChanged")]
public List<Parameter> parameters = new List<Parameter>();
[TitleGroup("Goals")]
public List<Goal> goals = new List<Goal>();
[Serializable]
public class Parameter
{
public string parameterName;
public int value;
}
[Serializable]
public class Goal
{
public string ID;
public List<Condition> conditions = new List<Condition>();
}
[Serializable]
public class Condition
{
//if value of
public string parameter1;
//operator
public enum Operator { GREATER_THAN, LESS_THAN, EQUAL_TO, NOT_EQUAL_TO }
public Operator _operator;
//compared to the value of
public int value;
//do this
public Result result;
}
[Serializable]
public class Result
{
//perform
public enum Outcome { INCREMENT, DECREMENT, EXIT }
public Outcome outcome;
//on
public string parameter;
//by a value of
public int effectValue;
}
void OnParameterChanged()
{
}
private int goalIndex = 0;
private Goal currentGoal;
void Start()
{
ExecuteGoal();
}
bool withinCondition;
bool completedAll;
void ExecuteGoal()
{
currentGoal = goals[goalIndex];
Debug.Log("Running: " + currentGoal.ID);
foreach (Condition condition in currentGoal.conditions)
{
CheckCondition(condition);
do
{
Debug.Log("Affecting: " + condition.result.parameter);
switch (condition.result.outcome)
{
case Result.Outcome.INCREMENT:
LookupParameter(condition.result.parameter).value += condition.result.effectValue;
Debug.Log(condition.result.parameter + ": " + LookupParameter(condition.result.parameter).value);
break;
case Result.Outcome.DECREMENT:
LookupParameter(condition.result.parameter).value -= condition.result.effectValue;
Debug.Log(condition.result.parameter + ": " + LookupParameter(condition.result.parameter).value);
break;
case Result.Outcome.EXIT:
completedAll = true;
withinCondition = false;
break;
}
CheckCondition(condition);
}
while (withinCondition);
if (!withinCondition)
{
Debug.Log("Goal Completed");
if (!completedAll)
{
goalIndex++;
ExecuteGoal();
}
else
{
Debug.Log("All Goals Completed");
}
}
}
}
void CheckCondition(Condition condition)
{
switch (condition._operator)
{
case Condition.Operator.EQUAL_TO:
if (LookupParameter(condition.parameter1).value.Equals(condition.value))
{
withinCondition = true;
}
else
{
withinCondition = false;
}
break;
case Condition.Operator.LESS_THAN:
if (LookupParameter(condition.parameter1).value < condition.value)
{
withinCondition = true;
}
else
{
withinCondition = false;
}
break;
case Condition.Operator.GREATER_THAN:
if (LookupParameter(condition.parameter1).value > condition.value)
{
withinCondition = true;
}
else
{
withinCondition = false;
}
break;
case Condition.Operator.NOT_EQUAL_TO:
if (!LookupParameter(condition.parameter1).value.Equals(condition.value))
{
withinCondition = true;
}
else
{
withinCondition = false;
}
break;
}
}
Parameter LookupParameter(string id)
{
foreach (Parameter parameter in parameters)
{
if (parameter.parameterName.Equals(id))
{
return parameter;
}
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment