Add readme

This commit is contained in:
Bram verhulst
2025-05-31 21:42:04 +02:00
parent 70f128f092
commit f36f2e015c
5 changed files with 196 additions and 32 deletions

BIN
Assets/ActionExample.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Assets/NoDoctors.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 MiB

View File

@@ -136,9 +136,13 @@ PrefabInstance:
propertyPath: m_Name
value: Robot (2)
objectReference: {fileID: 0}
- target: {fileID: 402548309473215301, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.x
value: -4.68
value: -4.5899997
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.y
@@ -146,7 +150,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.z
value: -4.3199997
value: -3.48
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalRotation.w
@@ -1691,9 +1695,13 @@ PrefabInstance:
propertyPath: m_Name
value: Robot (1)
objectReference: {fileID: 0}
- target: {fileID: 402548309473215301, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.x
value: -5.29
value: -5.2
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.y
@@ -1701,7 +1709,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.z
value: -5.79
value: -4.9500003
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalRotation.w
@@ -1817,9 +1825,13 @@ PrefabInstance:
propertyPath: m_Name
value: Robot (3)
objectReference: {fileID: 0}
- target: {fileID: 402548309473215301, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.x
value: -6.17
value: -6.08
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.y
@@ -1827,7 +1839,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.z
value: -4.6899996
value: -3.85
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalRotation.w
@@ -2304,9 +2316,13 @@ PrefabInstance:
propertyPath: m_Name
value: Robot (4)
objectReference: {fileID: 0}
- target: {fileID: 402548309473215301, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.x
value: -5.21
value: -5.12
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.y
@@ -2314,7 +2330,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.z
value: -3.26
value: -2.4200003
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalRotation.w
@@ -3168,7 +3184,7 @@ Transform:
m_GameObject: {fileID: 1140118200}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0.01, z: 0}
m_LocalPosition: {x: 0, y: 0.001, z: 0}
m_LocalScale: {x: 1.640868, y: 1.640868, z: 1.640868}
m_ConstrainProportionsScale: 0
m_Children: []
@@ -4876,7 +4892,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.x
value: -7.006
value: -6.761
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.y
@@ -4884,11 +4900,11 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.z
value: -6.18
value: -7
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.x
@@ -4896,7 +4912,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.y
value: 0.7071068
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.z
@@ -4908,7 +4924,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 90
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
@@ -5130,7 +5146,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.x
value: -7.006
value: -5.4700003
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.y
@@ -5138,23 +5154,23 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.z
value: -4.46
value: -7
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
value: -1
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.x
value: 0
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.y
value: 0.7071068
value: 0.000004470348
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.z
value: 0
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
@@ -5162,7 +5178,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 90
value: 359.999
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
@@ -6153,7 +6169,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 1400234784062687976, guid: f8e016b523a0d144d9f4264d806309d9, type: 3}
propertyPath: m_LocalPosition.x
value: 13.74
value: 18.07
objectReference: {fileID: 0}
- target: {fileID: 1400234784062687976, guid: f8e016b523a0d144d9f4264d806309d9, type: 3}
propertyPath: m_LocalPosition.y
@@ -6161,7 +6177,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 1400234784062687976, guid: f8e016b523a0d144d9f4264d806309d9, type: 3}
propertyPath: m_LocalPosition.z
value: -11.43
value: 8
objectReference: {fileID: 0}
- target: {fileID: 1400234784062687976, guid: f8e016b523a0d144d9f4264d806309d9, type: 3}
propertyPath: m_LocalRotation.w
@@ -6223,9 +6239,13 @@ PrefabInstance:
propertyPath: m_Name
value: Robot
objectReference: {fileID: 0}
- target: {fileID: 402548309473215301, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.x
value: -4.09
value: -4
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.y
@@ -6233,7 +6253,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalPosition.z
value: -5.39
value: -4.55
objectReference: {fileID: 0}
- target: {fileID: 8622252793202009712, guid: aafd274850c585047933903e37307aef, type: 3}
propertyPath: m_LocalRotation.w
@@ -6278,7 +6298,7 @@ PrefabInstance:
m_Modifications:
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.x
value: -7.006
value: -4.302
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.y
@@ -6286,23 +6306,23 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalPosition.z
value: -2.809
value: -7
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.x
value: 0
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.y
value: 0.7071068
value: 0.0000014454126
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalRotation.z
value: 0
value: -0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
@@ -6310,7 +6330,7 @@ PrefabInstance:
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 90
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2033428506645946689, guid: b08ebdb04bfe34547bf3a3c8b838ddef, type: 3}
propertyPath: m_LocalEulerAnglesHint.z

144
README.md Normal file
View File

@@ -0,0 +1,144 @@
# Goal Oriented Action Planning
Made by Bram Verhulst, 2GD11
## What is Goal Oriented Action Planning?
Goal Oriented Action Planning (Goap for short) is a form of AI decisionmaking that was developed by Jeff Orkin at MIT.
It's an alternative to more conventional AI behaviour machines like the State machine. GOAP is another way of approaching this problem of making AI work in games.
Unlike A Finite State Machine and Behaviour Trees, GOAP decouples actions and goals to achive it's "Goal".
//IMAGE HERE
The biggest downside of GOAP is that it is slower to compute than FSM or BT's, But the upsisde is that it allows to be more flexible when it comes to adding or chaning existing behaviours.
## How does it work?
### Goals
A Agent gets a goal (or several) and knows what actions it can preform to get to a certain goal.
A goal is a state that the agent is trying to achieve. For example:
- To be at home
- To get to the waiting room
- To Get better
### Actions
Every action in a GOAP has PreConditions and Effects.
In order to preform a action all the "conditions" need to met.
![ActionExample](assets/ActionExample.png)
Think of these as "What does the agent need to be able to do this action?"
And "What happens to the world when i do this action"
All of these conditons and effects should lead to a Planner that can string all of these toghder so the agent can get to it's goal.
![ActionTree](assets/ActionTreeExample.png)
### Planner
This is the real "Brain" of the AI. The planner takes 3 pieces of information
- Goals
- Actions
- Current Worldstate
The planner with this information can than try to make a graph of possible plans.
- Plans may only be possible if certain conditions are met.
- Example: Doctor can only get patient if he is charged and a patient is waiting.
- When the action is done, the world should change according to the Effects
- Example: When the Doctor takes a patient, the patient changes the amount of waiting patients in the world
A valid plan gets constructed back to front.
### What if we have 2 valid plans??
Are we doomed?
No, ofcourse not. We just add a cost to each action and take that into account for these plans.
We use can then use A* to find the plan with the lowest "cost"
In my example most action require the agent to move somewhere.
## implementation: __GOAP CyberHospital__
I made a hospital from the future, Where sick patients come in and a Robot doctor treats them.
Let me explain what they both do.
### Doctor
The doctor is quite simple in behaviour. Their main goal is to "TreatPatient". But they also have a limted battery and need to charge often.
Their goals are repeaing so they keep treating patients.
After some random amount of time their battery will deplete, This state is the precondition for the "Charge" action.
I set it up in a way where if there are still more patients than the other doctors can handle it will wait to charge until it can. Thus prioritising helping patients over charging.
In my implemtation i show the first nurses action on the top left.
### Patient
The patient spawns in outside the hospital.
He has 3 main goals
- IsWaiting (Get to the waiting room)
- IsTreated (Get to a bed and get treated)
- IsHome (Get to the home location)
So easy right? The paitient enters, goes to the reception, checks in and goes to the waiting room.
In this gif i have no doctors that come get the patients, you can see how they all checkin and goto the waiting area.
![NoDoctors](./Assets/NoDoctors.gif)
Wait, how does the doctor get the patient from the room? Does the patient know when the doctor gets them? Not really.
The way we fix this is by making the world hold a global state of Patients, Beds, Chargers, etc.
This is stored internally as a Queue of Patients, when a patient enters the waiting room i add him to the queue. When a doctor looks for a patient i just pop him from the queue.
This allows the patient aswell to know when a doctor gets him.
This is how i also show this on the UI on the top left.
- Waiting is decremented when the patient is retrieved from the waiting room
- FreeBeds is decremented becuase the doctor and patient will be using it.
When the patient gets treated he can now start on his final goal which has a preconditon of "IsCured" (Eg. when he is treated by a doctor).
Home in my case is just somewhere outside the map where i remove him from the world.
Here you can see the final result of the doctors and patients working togheder.
![Final](./Assets/Final.gif)
## Conclusion
Looking back on this research i wish i had more time to get deeper into this.
It's an interesting topic in AI i don't see often used in games.
I would guess the reason is because the planner is quite intensive to calculate.
## References
- Intro to GOAP
- For a quick introduction
- [Intro to Goal Oriented Action Planning (GOAP)](https://youtu.be/LhnlNKWh7oc?si=R5zwpf5OPyEYHRVS)
- Building the AI of F.E.A.R. with Goal Oriented Action Planning - AI and Games
- Most of the understanding of GOAP
- [Building the AI of F.E.A.R](https://youtu.be/PaOLBOuyswI?si=cwH2paeVlTySvhkD)
Thank you for reading this, have a amazing day!