Search Unity

Official NPC movement / Navigation / AI

Discussion in 'Open Projects' started by cirocontinisio, Feb 3, 2021.

  1. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
    Basecamp for discussions related to how NPCs (both critters and humanoid) move around, and about the AI governing their aggressive behaviour. Also discussing Navmesh and related navigation tools.
     
  2. cirocontinisio

    cirocontinisio

    Joined:
    Jun 20, 2016
    Posts:
    884
  3. Dnalsi

    Dnalsi

    Joined:
    Feb 11, 2014
    Posts:
    9
    I was looking into it until I saw that the critter already have a Roaming State.

    Maybe I don't understand the card, so could you clarify what features are missing?
     
    cirocontinisio likes this.
  4. treivize

    treivize

    Joined:
    Jan 27, 2016
    Posts:
    136
    Hey @Island212!

    Indeed, there is already one of the roaming strategy implemented (roaming randomly around a center point / spawning point), but currently the movement is fully set in FSM all the same for all the non static critters. Here the idea is to be able to support at least one additional strategy which is the roaming following a path defined by a list of ordered positions/waypoints (Vector3/2) and be able to inject this strategy at prefab level to be able to change from one type to another or to change the list of waypoints depending of the NPC.

    Based on my own experience on this topic, the idea might be to inject the desired strategy and the associated config (roaming radius/waypoint stop duration/list of waypoints) from a new MB controller (NPCMovement) (see how Damageable is doing for dropping determination) and next in the FSM when defining the roaming action use the provided strategy and the config to drive the NavMeshAgent next destination.

    I hope it clarifies the topic in the right direction :)
     
    Amel-Unity and cirocontinisio like this.
  5. murkesz

    murkesz

    Joined:
    Aug 10, 2013
    Posts:
    5
    Hi,
    I saw that the "Pathway component" is still unassigned
    I'd like to give it a try as my first contribution to the project. The example on the card is specified quite well. I'm planning to implement something like that.

    @Island212 Are you still planning to work on this? In case you are, I can choose a different task.

    @cirocontinisio Please let me know if I can start to work on it.
     
    Last edited: Feb 11, 2021
  6. Dnalsi

    Dnalsi

    Joined:
    Feb 11, 2014
    Posts:
    9
    @murkesz No, something has come up so you are free to work on it
     
  7. treivize

    treivize

    Joined:
    Jan 27, 2016
    Posts:
    136
    Hi @murkesz, welcome on board! The cards are never assigned until the core team has confirmed / merged a proposal from the community. The aim is to not discourage anyone to work on any task even if someone else has already started to work on it.

    Here is the case, there is someone "AlexandreGheraibia" who has already opened a PR for this feature: https://github.com/UnityTechnologies/open-project-1/pull/359. Looking at the number of commits pushed in the last couple of days, I would say it is not finished yet. (Actually, I would suggest you to amend your first commit when changing it or wait to have something working before creating your first commit. Here for instance, not sure that 35 commits for 4 new files, is really a good practice)
    I do not know who he is on the forum and the quality of his implementation. There are not a lots of details in the PR...

    So, you have two options:
    - Option 1: Pull the PR from AlexandreGheraibia and have a look at what he is doing and provide comment in his PR where you see area of improvements or propose to work with him on it to build something together.
    - Option 2: Propose an alternative solution to address this feature and open your own PR for the same card.

    In general, I would suggest to post here what is your approach, how it works internally and how other will be able to use it. Add some screenshots / video are often really appreciated by the core team and the community. Personally I am doing both implementation and providing my approach at the same time, even if it means changing the implementation later based on the feedback, I feel less frustrated like that: crafting something and not just designing a proposal, it is up to you ;)

    Good luck and have fun in contributing to this project!
     
    itsLevi0sa likes this.
  8. itsLevi0sa

    itsLevi0sa

    Joined:
    Oct 26, 2019
    Posts:
    128
    Hey y’all! Jumping in the discussion from the Quests and Scenario thread one, a part of which regards this thread too.

    Long story short, we were discussing about a quest in the Rocky Path area where you’d probably need to find a special Rock Critter Egg from one of the Rock Critters nests. We were wondering if this could be achieved after some kind of puzzle thinking, regarding how Rock Critters behave. We imagined them being very protective of their eggs and very aggressive. So they wouldn’t move much and they would definitely attack you if you approach them. They would also be really strong, in order to force the player to think of a strategy to distract them (instead of attack them) by throwing an item that would make them abandon their nests (something that would look like one of their eggs). You think its doable/interesting to work on? Don’t know if it’s something to be officially implemented in the end, but why not try and see (stating that because this is a community suggestion). I would also like to share with you an interesting gameplay example @calculus7 has posted, which is pretty much on point on what we were thinking about:



    You can go to 10:05 to get a glimpse of what the game is about (really fun game, and surprisingly relatable at some aspects). Also given the fact that Rock Critters can headbutt into things, we might want to make them headbutt one another and have them either stunned or fallen from some height (this probably regards the Animation?). You can go to 28:55 to see a similar example on the above video.

    Any comment on that would be really appreciated! This is just an idea, to see if this could be done/is interesting. It could also affect the Whiteboxing of the Rocky Path level as well. Cheers.
     
  9. murkesz

    murkesz

    Joined:
    Aug 10, 2013
    Posts:
    5
    Hey @treivize,
    thank you for the clarification and the suggestions.
    I've checked the PR you mentioned and it looks promising even if the solution it provides is not well documented yet. Since I would not be able to create a better tool at the moment, I'm going to turn my attention toward other tasks in the project. (Fortunately there is plenty. :)) Cheers.
     
    cirocontinisio and treivize like this.
  10. treivize

    treivize

    Joined:
    Jan 27, 2016
    Posts:
    136
    @itsLevi0sa, happy to see you here in a coding thread :). I really like the idea of having some puzzles mechanics in the game and not only killing critters, talk to NPC and cook some recipes.

    @cirocontinisio, Actually regarding the pathway position list storage, it is requested to store it into a new component (MB script) but it would be great to store it into a SO instead and then in the NPC movement component defines a default pathway SO and be able to change the pathway SO based on a PathWayChannelEventSO that could be triggered to switch from one path to another based on a trigger in the game (accomplish a quest, trigger something in the scene, kill a critter, etc...), do you think it could make sense here?
     
  11. itsLevi0sa

    itsLevi0sa

    Joined:
    Oct 26, 2019
    Posts:
    128
    @treivize Hello there! I do occasionally pass by, as a silent observer ^^ Appreciate all the great work! (so many people I never really cross paths in the threads but would like to give a big thumbs up!) Anyway, hope my post was not out of context of what should be discussed here, and if it was, well, consider this a happy break. Good luck, keep it up :)
     
  12. treivize

    treivize

    Joined:
    Jan 27, 2016
    Posts:
    136
    Hello,

    Here is a proposition to implement the NPC moving on NavMesh. Ready? Steady? Go!

    As said above currently the moving critter is fully driven by the FSM with absolute conditions and actions, so there is no capability to assign different movement from one critter (or NPC) to another without duplicating the whole FSM table.

    Here again, the approach could be to move the FSM configuration of the actions and conditions related to the movement into another SO attached to the game object like done with Damageable and Attack scripts. And next fetch this configuration in FSM to drive the conditions/actions.

    So a new script NPCMovement would be added and it would hold one NPCMovementConfigSO and one NPCMovementEventChannelSO.
    upload_2021-2-13_23-17-34.png

    There would be two implementations of NPCMovementConfigSO:
    - RoamingAroundCenterConfigSO
    upload_2021-2-13_23-21-2.png
    This config would describe the movement of the NPC with a random roaming strategy around a center (spawning point or a custom point) a maximum distance around this center (radius), the speed of the NPC and how long the NPC would stop between each random destination. This would map the current hard coded strategy into FSM (just adding the capability to define a custom center instead of always being the spawning point).

    - NPCPAthwayConfigSO
    upload_2021-2-13_23-25-3.png
    This config would describe the movement of the NPC following a path based on waypoints. Like the previous strategy, the speed and how long the NPC would wait at each waypoint before resuming his movement could be configured independently and out of the FSM.

    On the FSM side, the configuration would almost not change: only the actions/conditions implementations of the currently wired roaming conditions/actions. Here both movement strategies are mapped to 2 action strategies injected through a controller action would replace the current RoamingAroundSpawningPointActionSO: NPCMovementActionSO

    Code (CSharp):
    1.  
    2. [CreateAssetMenu(fileName = "NPCMoveToNextDestination", menuName = "State Machines/Actions/NPC Move To Next Destination")]
    3. public class NPCMoveToNextDestinationSO : StateActionSO
    4. {
    5.     protected override StateAction CreateAction() => new NPCMoveToNextDestination();
    6. }
    7.  
    8. public class NPCMoveToNextDestination : StateAction
    9. {
    10.     private NPCMovement _npcMovement;
    11.     private NPCMovementConfigSO _config;
    12.     private NPCMovementAction _action;
    13.     private NavMeshAgent _agent;
    14.  
    15.     public override void Awake(StateMachine stateMachine)
    16.     {
    17.         _agent = stateMachine.GetComponent<NavMeshAgent>();
    18.         _npcMovement = stateMachine.GetComponent<NPCMovement>();
    19.         InitMovementStrategy(_npcMovement.NPCMovementConfig);
    20.     }
    21.  
    22.     public override void OnStateEnter()
    23.     {
    24.         if (_config != _npcMovement.NPCMovementConfig)
    25.         {
    26.             InitMovementStrategy(_npcMovement.NPCMovementConfig);
    27.         }
    28.         _action.OnStateEnter();
    29.     }
    30.  
    31.     public override void OnUpdate()
    32.     {
    33.         _action.OnUpdate();
    34.     }
    35.  
    36.     public override void OnStateExit()
    37.     {
    38.         _action.OnStateExit();
    39.     }
    40.  
    41.     private void InitMovementStrategy(NPCMovementConfigSO config)
    42.     {
    43.         _config = config;
    44.         if (_npcMovement.NPCMovementConfig is RoamingAroundCenterConfigSO)
    45.         {
    46.             _action = new RoamingMovementAction(
    47.                 (RoamingAroundCenterConfigSO)_npcMovement.NPCMovementConfig,
    48.                 _agent,
    49.                 _npcMovement.transform.position);
    50.         }
    51.         else if (_npcMovement.NPCMovementConfig is PathwayConfigSO)
    52.         {
    53.             _action = new PathwayMovementAction(
    54.                 (PathwayConfigSO)_npcMovement.NPCMovementConfig,
    55.                 _agent);
    56.         }
    57.     }
    58. }
    59.  
    Note: OnStateEnter, the previously stored config would be checked to verify if it would have changed during runtime and so it would inject the new strategy and config.

    Finally regarding the channel attribute, it could be added to implement the functionality raised by @itsLevi0sa, thanks to it any other element in the game could trigger an event through this channel to switch the movement config of an NPC.

    Here is a simple script that would achieve this trigger:

    Code (CSharp):
    1.  
    2. public class NPCMovementSwitcher : MonoBehaviour
    3. {
    4.     [SerializeField] private NPCMovementEventChannelSO _movementChannel;
    5.  
    6.     [SerializeField] private NPCMovementConfigSO _movementConfig;
    7.  
    8.     [ContextMenu("Trigger NPC Movement switch")]
    9.     public void SwitchMovement()
    10.     {
    11.         if (_movementChannel != null && _movementConfig != null)
    12.         {
    13.             _movementChannel.RaiseEvent(_movementConfig);
    14.         }
    15.     }
    16. }
    17.  
    upload_2021-2-13_23-31-37.png

    This trigger is replacing the ongoing slime random roaming strategy by a pathway strategy at runtime.

    Here is a short demo:


    So that is why I have the feeling that storing the pathway config (waypoints) into a SO instead of an MB would be more powerful. @cirocontinisio, does it make sense? I know it is not aligned with the card and the on-going implementation from AlexandreGheraibia. I do not know either if it could be adapted / transposed easily to SO storage.
     

    Attached Files:

    Last edited: Feb 13, 2021
    Amel-Unity and itsLevi0sa like this.
  13. treivize

    treivize

    Joined:
    Jan 27, 2016
    Posts:
    136