Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question NPC Random movement

Discussion in 'Scripting' started by theheheheo, Oct 24, 2020.

  1. theheheheo

    theheheheo

    Joined:
    Jul 10, 2019
    Posts:
    8
    Hello,

    I am making a game where you play as a doctor and want to save your village from a pandemic...
    I want to make the villagers(approximately 20) follow this cycle:

    1) Go to a random place on the map (walk maximally 5 seconds).
    2) Play some working animation (5 seconds).
    3) Find the closest villager and go to meet him.
    4) Play talking animation - again 5 seconds, but if the other villager leaves sooner (for example 2 of them were talking and then this one came and joined them) he should restart the cycle too...

    I tried. I even had parts of it working, but whenever I tried to make it functional as a whole cycle, it never did.
    Can someone help me? (All villagers are stored in a static dictionary with ID)
     
  2. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Hey,

    to help you we would need your code,

    if you want an explanation, here it is:

    - You could do that with a Behaviour Tree (pretty simple to code) , your AI would be flexible and so on ..
    - You could do an FSM(Finite State Machine) which is also easy to code , you could track your actions very easly and so on ..

    But lets say you dont know how to do those then i would recommend you to make first components for walking, animation, interacting with other entitys (find the closest villager and go to meet him),

    you would need that components anyway but before you would implement a state machine, check first if ea. function works individualy :)
     
  3. theheheheo

    theheheheo

    Joined:
    Jul 10, 2019
    Posts:
    8
    Thank you for your reply...
    We are working in a team (it's a school project) and I don't have models or animations yet (so I skipped it for now).
    Walking component I made never actually worked... And here is the interaction part:
    In FixedUpdate:
    Code (CSharp):
    1.  float distanceToClosestCitizen = Single.PositiveInfinity;
    2.                 foreach (var citizen in GameManager.citizens)
    3.                 {
    4.                     if (id != citizen.Key)
    5.                     {
    6.                         float distance = Vector3.Distance(transform.position, citizen.Value.transform.position);
    7.                         if (distance < distanceToClosestCitizen)
    8.                         {
    9.                             friend = citizen.Value.gameObject;
    10.                             distanceToClosestCitizen = distance;
    11.                         }  
    12.                     }
    13.                 }
    And then I have this coroutine:
    Code (CSharp):
    1.  IEnumerator WalkToFriend()
    2.     {
    3.         if (Vector3.Distance(transform.position, friend.transform.position) > 2)
    4.         {
    5.             transform.LookAt(friend.transform.position);
    6.             transform.Translate(Vector3.forward * (Time.deltaTime * moveSpeed));
    7.             yield return new WaitForSeconds(0.5f);
    8.             StartCoroutine(WalkToFriend());
    9.         }
    10.         else
    11.         {
    12.             //talking animation
    13.         }
    14.     }
    that's all I have for now...
     
  4. Terraya

    Terraya

    Joined:
    Mar 8, 2018
    Posts:
    646
    Ok, so since its AI i would recommed you to use "NavAgents" ,
    they deliver you already most of the functions you need,

    your "mover" component which handles the "movement" of the AI should then
    have something like this:

    Code (CSharp):
    1. private NavMeshAgent agent;
    2. public NavMeshAgent Agent => agent;
    3.  
    4. Awake()
    5.      => agent = GetComponent<NavMeshAgent>();
    then you need an IEnumerator as you have done already,
    there you would wait until AIMover calculates the Path, then until it reaches the waypoint,
    and your finisht :)

    Code (CSharp):
    1.         public override IEnumerator MoveToWaypoint(GameObject waypoint)
    2.         {
    3.             aiMover.WalkTo(waypoint.transform.position);
    4.             yield return new WaitUntil(() => !agent.pathPending);
    5.             yield return new WaitForSeconds(0.4f);
    6.             yield return new WaitUntil(() => agent.ReturnDistanceToTarget() <= 0.15);
    7.         }
    something like that,

    you obv. want to make it more flexible since this is only a small piece of code,
    but start with that :)