I have an enemy that is supposed to go in one direction and after hitting the wall or if a certain amount of time passes, it should turn around and go back. After hitting another wall, it should turn around again and keep doing this in a loop.
-
2\$\begingroup\$ Want to show us your code so we can help you build on it? \$\endgroup\$– DMGregory ♦Commented Feb 3, 2021 at 1:27
-
\$\begingroup\$ i dont have any code at all i tried a few things but they didnt do much so i just asked if theres code that can do that cuz i was tired of doing google searches i was using transform.position that was the only one that moved the object and this is a 2D game \$\endgroup\$– anonymous person i guessCommented Feb 3, 2021 at 1:48
-
2\$\begingroup\$ We don't even know if you're working in 2D or 3D, using Rigidbodies or navmesh or transform.position, so we need a lot more specifics to be able to help you with this. \$\endgroup\$– DMGregory ♦Commented Feb 3, 2021 at 1:52
-
\$\begingroup\$ 2D and transform \$\endgroup\$– anonymous person i guessCommented Feb 3, 2021 at 1:54
-
1\$\begingroup\$ @D.Kallan that looks like about the best advice we can offer this user, given the dearth of information they've given us to work with. Want to post it as an answer below? \$\endgroup\$– DMGregory ♦Commented Feb 3, 2021 at 13:12
2 Answers
As mentioned in my comment, I would look at what exactly you need and make steps that you can work on.
"An enemy has to move in a direction until conditions are met, then turn around."
So you can start by looking up how to move an object (either by transform.position or by physics with rigidbodies, etc.). Instead of going to position x or y, you can let it move indefinitly.
You can add a boolean somewhere in that movement, if it is changed, the direction it moves in inverts. When your conditions are met again, the boolean flips back to it's initial state, turning the character back around to the original direction, etc.
Then have checks to change that bool. Certain amount of time: make a timer and when it elapses, change the bool. For hitting a wall: search for object collision with walls (maybe a trigger on the enemy and collider on the wall, so when the wall enters the trigger, the bool is flipped)?
These are just some pointers to go on, there are multiple ways to approach it, but this should get you something workable and steps to lookup / learn.
Build a Finite State Machine
Finite State Machines (FSM) are a simple but effective programming pattern which is very useful for implementing the behavior of AI enemies.
FSM's in a nutshell:
- An enemy can be in different states
- Its current behavior depends on what state they are currently in
- Certain conditions might cause them to switch to a different state, thus changing their behavior
In this case, the state machine which describes the behavior of your enemy has only two states:
- MOVE_LEFT state:
- Move to the left.
- When a certain amount of time passed, reset that timer and change to the MOVE_RIGHT state.
- When there is a wall to the left, reset the timer and transit to the MOVE_RIGHT state.
- MOVE_RIGHT state:
- Move to the right
- When a certain amount of time passed, reset that timer and change to the MOVE_LEFT state
- When there is a wall to the right, reset the timer and transit to the MOVE_LEFT state.
So how would a basic implementation of this pattern look in Unity?
First you need to define the states and a variable to store the current state. You only have two states right now, so a bool currentState
variable could do the job. But you might want to add more than those two states later, so I would recommend to use an enum
instead:
private enum States {
MOVE_RIGHT,
MOVE_LEFT
}
private State currentState;
Then your Update()
method could use a switch(currentState)
to execute different code depending on the current state: Moving left it's in the MOVE_LEFT state and move right when it's in the MOVE_RIGHT state. That code should also include the code to check if the condition for switching the state is met, and when that's the case change currentState
to the respective other state.
How would a more advanced implementation look?
When you have an enemy with a lot of states and when those states get pretty complex regarding their behavior and transition logic, then it can be useful to not just create an enumeration and a large switch
statement, but to create a separate C# class for every possible state. All these classes which represent states for the same type of entity should implement the same interface (or alternatively: extend the same abstract base-class). When I implement the FSM state pattern this way, then my IState
interface usually has these methods
Enter
which gets called when transitioning to this state.Update
which gets called each frame while the FSM is in this state.Leave
which gets called when transitioning out of this state.
The actual MonoBehaviour
which implements the FSM itself then looks something like this:
public class GoombaAI : MonoBehaviour {
public IState<GoombaAI> moveLeftState;
public IState<GoombaAI> moveRightState;
Start() {
moveLeftState = new GoombaMoveLeftState(this);
moveRightState = new GoombaMoveRightState(this);
currentState = moveLeftState;
}
Update() {
currentState.Update();
}
public void SwitchState(IState<GoombaAI> newState) {
currentState.Leave();
newState.Enter();
currentState = newState;
}
}