Create a Basic Npc AI // Pause Coroutines

Warning: Lot’s of confusing stuff ahead. Sorry. My main questions are the bold ones.

Heho!

I kinda need a push in the right direction, I am doing this project to learn unity better and I am a little bit stuck.

So I have a bunch of npcs which supposed to do certain tasks on their own (like a sim, but automated).

Basically I made a hierarchy of importance and then I just wanted to put them all after each other into the Update Function so they get called after each other. Here’s some pseudocode for that:

if (thirsty){
GoDrink();
return;

if (hungry){
GoEat();
return;

etc…
But after playing around with it a little bit, I have the feeling this is already the wrong direction, is it?

Does anyone know a good tutorial for that? Or can you help me out a little bit and tell me how this is usually done? I mostly only find stuff for enemies.

It basically gets complicated at the point where they have to actually go somewhere (lets say a well) to drink and I need to wait until they are there, or until a certain action is fulfilled (“cooking”).

I keep coming back to Coroutines, but how do I make the whole script pause when I use them and not just have them run next to the normal functions?
Or can I use WaitForSeconds without a return?

This is for example how my Drink Function looks right now,
the game checks where you are and if that building has water. If yes, you can drink as much as it has, but maximum 100. The Problem is, during the waiting time it already continues with the Update function and calls other Coroutines/Functions.

How do I make a “cooldown” in which the npc is not being able to pick up a new action?

    IEnumerator Drink()
    {
        if (currentPlace.gameObject.GetComponent<Object_ressources>() != null)
        {
            int temp = currentPlace.gameObject.GetComponent<Object_ressources>().water;
            int temp2 = 100-thirst;


            if ((temp + thirst) <= 100)
            {
                thirst += temp;
            }
            else
            {
                thirst = 100;
            }

            currentPlace.gameObject.GetComponent<Object_ressources>().water -= temp2;

        }

        yield return new WaitForSeconds(5);
    }

edit: Also the term Finite State Machine was thrown at me, is that the solution?

I’m not prepared to suggest a full solution to your system, but it may help to have a coroutine that yields your other coroutines.

Within a coroutine, something like this could work, but it’s just pseudocode:

private void CheckNeeds() {
    if(hunger >= 0.5) {
        needs.Add(Eat());
    }
    if(thirst >= 0.5) {
        needs.Add(Drink());
    }
}

// something would start this coroutine, or it can always be running perhaps
private IEnumerator HandleNeeds(){
    foreach(IEnumerator need in needs) {
        yield return need; // starts the function and waits for it to return
        yield return new WaitForSeconds(cooldown); // waits before starting next function
    }
}

You’ve got a lot of questions for which there is no single right answer - this is all about different styles and designs of AI, and there are a thousand different ways to go, all valid for different purposes.

One question which can be fairly easily answered though:

You can replace Update with a coroutine loop - while a coroutine is in progress, it won’t return to the loop.

void Start() {
StartCoroutine(UpdateLoop());
}

IEnumerator UpdateLoop() {
while (true) {
if (hungry) {
yield return StartCoroutine(Eat() );
}
if (thirsty) {
yield return StartCoroutine(Drink() );
}
Debug.Log("At this moment I am neither eating nor drinking, and am free to make other decisions!");
yield return 0;
}
}

Yes state machines are the way to go. Using a whole bunch of if-else statements makes the code brittle and easy to break.

Using a state machine helps modularize the logic so if there’s a bug, it’s easier to pinpoint it. Plus you can add more states over time.

Definitely invest some time into creating a simple state machine.

As far as state machines go, if your goal isn’t specifically learn how to work, just get one from the asset store. I’m pretty sure there are free ones.

Finite State Machine (FSM) is very fundamental for game programming, I’d suggest to read and master the concept. It’s very simple, yet it can become a useful tool to organize and to make simple AIs.

After you’ve mastered FSM, have a look at Behaviour Tree for a more advanced AI technique. Here is a list of resources if you want to go deeper in that subject.