Skip to content

Commit 7071684

Browse files
committed
Utility System basics added ; however, it is currently implemented to be easy to debug / edit through the inspector, and can be improved performance wise if needed
1 parent f84d576 commit 7071684

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

Runtime/Action.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using Unity.Collections;
4+
using UnityEngine;
5+
using UnityEngine.Events;
6+
7+
8+
public class Action : MonoBehaviour
9+
{
10+
[System.Serializable]
11+
struct StatImportance
12+
{
13+
public string statName;
14+
15+
[SerializeField]
16+
public AnimationCurve curve; // must return a value between 0 and 1.
17+
}
18+
19+
[SerializeField]
20+
float defaultImportance = 0f;
21+
22+
[SerializeField]
23+
public int priority = 0;
24+
25+
[SerializeField]
26+
List<StatImportance> statsImportance = new List<StatImportance>();
27+
28+
[SerializeField]
29+
UnityEvent<Action> onStart;
30+
[SerializeField]
31+
UnityEvent<Action> onEnd;
32+
33+
[SerializeField]
34+
float lastEvaluation = 0f;
35+
36+
37+
// STATS
38+
public float TotalDurationDoingAction
39+
{
40+
get;
41+
private set;
42+
}
43+
44+
45+
46+
public float EvaluateUtility(Blackboard bb)
47+
{
48+
float totalImportance = defaultImportance;
49+
50+
foreach (StatImportance statImportance in statsImportance)
51+
{
52+
Stat stat = bb.stats.Find((Stat s) => { return s.name == statImportance.statName; });
53+
if (stat != null)
54+
totalImportance += statImportance.curve.Evaluate(stat.Ratio);
55+
else
56+
{
57+
Debug.LogWarning("Stat not found : " + statImportance.statName);
58+
}
59+
}
60+
61+
lastEvaluation = Mathf.Clamp(totalImportance, 0, 1);
62+
63+
return lastEvaluation;
64+
}
65+
66+
public virtual void StartAction()
67+
{
68+
onStart?.Invoke(this);
69+
}
70+
71+
public virtual void UpdateAction()
72+
{
73+
TotalDurationDoingAction += Time.deltaTime;
74+
}
75+
76+
public virtual void EndAction()
77+
{
78+
onEnd?.Invoke(this);
79+
}
80+
}

Runtime/Blackboard.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
public class Blackboard : MonoBehaviour
6+
{
7+
[SerializeField]
8+
public List<Stat> stats = new List<Stat>();
9+
}

Runtime/Stat.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
using UnityEngine.Events;
5+
6+
[System.Serializable]
7+
public class Stat : MonoBehaviour
8+
{
9+
[SerializeField]
10+
private float ratio;
11+
public float Ratio
12+
{
13+
get { return ratio; }
14+
set
15+
{
16+
ratio = Mathf.Clamp(value, 0, 1);
17+
}
18+
}
19+
};

Runtime/UtilitySystem.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
using System.Collections;
2+
using System.Collections.Generic;
3+
using UnityEngine;
4+
5+
6+
7+
public class UtilitySystem : MonoBehaviour
8+
{
9+
[SerializeField]
10+
List<Action> actions = new List<Action>();
11+
public List<Action> Actions
12+
{
13+
get { return actions; }
14+
}
15+
16+
17+
[SerializeField]
18+
Blackboard bb;
19+
20+
Action currentAction = null;
21+
22+
public Action CurrentAction
23+
{
24+
get { return currentAction; }
25+
}
26+
27+
28+
29+
private void Start()
30+
{
31+
if (currentAction != null)
32+
{
33+
currentAction.StartAction();
34+
}
35+
}
36+
37+
private void Update()
38+
{
39+
float highestUtility = 0f;
40+
Action newAction = null;
41+
foreach (Action action in actions)
42+
{
43+
float utility = action.EvaluateUtility(bb);
44+
if (utility > highestUtility || (newAction != null && utility == highestUtility && action.priority > newAction.priority))
45+
{
46+
newAction = action;
47+
highestUtility = utility;
48+
}
49+
}
50+
51+
if (newAction == null)
52+
{
53+
newAction = actions[Random.Range(0, actions.Count)];
54+
}
55+
56+
if (newAction != currentAction)
57+
{
58+
if (currentAction != null)
59+
currentAction.EndAction();
60+
61+
currentAction = newAction;
62+
currentAction.StartAction();
63+
}
64+
65+
// Call update atleast 1 time, even if StartAction() has been called during the same frame
66+
currentAction.UpdateAction();
67+
}
68+
}

0 commit comments

Comments
 (0)