Search Unity

Navmesh AI, how flexible is the agent?

Discussion in 'Navigation' started by cthomas1970, Apr 18, 2019.

  1. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    So, I have a game where the bad guy will be a ball that rolls around. To that end, it will not need to turn to change direction, you just supply a force in a direction, and the ball will change its motion vector (over time) to roll that way. So, no steering left/right and then applying speed, instead just provide it a vector,and that force is applied to its spin to make it move that way.

    So, will this work ok with the Navmesh agent? The system itself looks pretty easy to setup, in terms of giving it a mesh to navigate over, its just then getting that agent to mesh with my own baddies particular motion control.

    Should I give this system a roll in my game....

    (sorry...)
     
  2. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Hmmmm, I don't think you'll get this to feel nice using the NavMesh system. There are some ways to tweak movement values such as speed and rotation speed and such, but I doubt it'll be enough to make the ball feel convincing.
    Why not just make a physics ball and use some simple controller to "pool cue" it towards your player over time?
     
  3. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    Well, I guess what I want to leverage in the Navmesh system is the whole navmesh system, you know, how it works out where your character can move too, and the auto-waypoint system, so it will then make its way around obstacles. Now, I know thats not the whole banana in terms of making a baddy. I'll need to give it some kind of AI, can it see or hear you, all that. But the navmesh itself seems like a pretty hard thing to engineer from scratch.

    The Navmesh Agent itself seems to actually DRIVE a mesh by making it move, rotate left, right, move, and so on. I need that to happen in a sightly different way, instead I guess I could make things work if it JUST had callbacks which I could intercept and use to define a point in space to move towards. Then I could drive the Marble in the right direction, using the same control system as I use for the players controls.
     
  4. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Well, you could use the NavmeshAgent to exclusively calculate the path your baddy needs to take.
    I'm theorycrafting here, but you basically give your baddy the agent, use SetDestination to begin calculating a path, and then when it has finished calculating immediately tell it to stop.
    Then you get the path as an array of vectors, those are the corner points of the path. With those you could probably calculate a sequence of forces you need to apply to the ball to replicate it, like in a game of pool.
    You'll probably need to come up with a way for your baddy to detect when it's going too far off course and recalculate to correct itself.
     
  5. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    Yandalf, I kind of did as you suggested, I went off last night and decided to experiment, it took a while but I got something working in the end.

    BTW, the way a sphere moves works best when you ROLL it, rather than firing it along like a pool ball. This uses Apply TORQUE (internal spin) rather than FORCE, a kind of external hit or push. With Torque, its like the ball has its own motor, which is trying to make it roll. This uses friction between the ball and the floor, so on ice it will spin, rubber will give it super grip and all that goodness. So all you need is the vector from the balls center to a target point and then apply that vector with a 90 degree rotation applied, and the ball will roll in that direction. Anyway....

    This is what I do....
    • Put an Agent on my Baddie, but on a child node, so it cannot actually move my Baddie itself
    • Create a Baddie Class and apply to the top level of my Baddie
    • Get my class to get the Agent object
    • Use the Agent to calculate a Path, when this is done, the Agent will auto set off on the path :(
    • Use Agent.nextTarget = this.transform.position to LOCK the agent to its parent, stopping it wandering off
    • Use Agent.getPointOnPath to get a position, x units along the current path
    • Calculate a vector between the Baddie and the path point
    • Use the vector to apply Torque to the Baddie Marbles Rigid Body, and it rolls towards that path point.

    And the Baddie will safely navigate to the player, smoothly following the path, going round obstacles and so on :)

    There are some issues though...
    • The Baddie seems to have a fixed top speed, not sure what is applying this, needs more work, but right now it hits that speed pretty quickly and then trundles everywhere. I need to break this limit....
    • The AGENT is trying to navigate at the same time as I am also doing this, waste of CPU, need to turn it off once we have a path....

    I'd also like to see some future work done on the Agent system to make this kind of hackery less necessary. I mean, the Agent moves in a VERY particular way, and that does not suit all games, like mine for instance. So more methods to just allow you to set paths, set your agent as not auto-follow, and then use callbacks and so on to make your own application of it, would be ideal. What I have done above works, but Im not sure if I'll EVER be able to turn the Agents navigation off.
     
  6. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Why not just use NavMeshAgent.IsStopped=true? From my understanding you could also just use NavMeshAgent.CalculatePath to get a path without setting it on your agent, hence not causing it to move.

    I agree the agent and navigation system in Unity needs more work and less blackboxing. Progress seems unfortunately really slow on that. The most we have right now is the NavMeshComponents repo which unfortunately does nothing for the agents.
     
  7. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    NavMeshAgent.IsStopped=true certainly looks like something I should try out. You see when I calc a path, you get a path object back, which is fine. But the find point on path method seems to only work on a path that has been SET on the Agent. You cant just pass a path object in, which would be ideal for me, to totally circumvent the Agents own navigation. When you SET a path, the Agent immediately then sets off following it, which is where IsStopped=true should help.

    As for my Marble rolling at a fixed top speed, thats more of a mystery. If I can get that issue out the way as well, the system should be totally flexible and to my needs.
     
  8. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    That's why you could use NavMeshPath.corners instead. If you simply calculate the path without setting it back on the agent, you could use the corners to calculate the movement vectors you need to move your ball.
    This will probably mean you'll have to check if the returned path is valid, but would all in all be a lot easier.
    If you wish to cut out the NavmeshAgent completely, you can even calculate a path directly on the NavMesh using your target position and ball's position.
     
  9. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    Hey, thanks for the advice again. I tried re-working the navigation using corners last night and it works. Previously I had used sample point along path, with the Marble looking 1 unit ahead, and re-generating the path once per second or so (this worked well), but this is a feature of an Agent, as it needs a point to sample from.

    Im now using the Path gen from NavMesh directly, and have dumped the Agent totally. I am now looking at a path traversal method, as I dont have the Agent code to do this. Basically aiming for Corner 1, detecting proximity, and then indexing up to 2 and so on. This should work well for patrol type Baddies. For more close quarters persuit, I think Ill still use the technique of travelling for corner1 with frequent path updates, maybe I can base the frequency on a combo of distance to player, or how far the player has moved as this would stale the path eh.

    I'm in the process of developing a Baddie class, which will be inherited by various baddie types each with different key behaviours, like a Guard, Patroller, HunterKiller, Persuer and so on. I had considered rolling these all into a single Badie class, but it would become to cluttered. I'll try and keep all the core stuff in the Baddie Class, the navigation system, and various utilities. Should be fun to code up. I really hope this will add some extra zing to the game mechanic :)
     
  10. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    491
    Great to hear things are working themselves out!
    I personally would advise to not use inheritance with Unity, at least not where behaviour is concerned.
    Instead, the code you're currently working on could just be a navigator that you can control with another component on your object, a brain if you will. That way you can just make different brains for the different behaviours you want, like patrolling and pursueing, without everything being locked inside an inheritance tree.
    This would for example be useful if you want other things besides baddies to move as well, plus things will generally be easier to debug since you will have more smaller classes responsible for single operations.
     
  11. cthomas1970

    cthomas1970

    Joined:
    Sep 12, 2017
    Posts:
    75
    Regarding inheritance, yeah, I agree. Thats something I am bearing in mind. The Baddie class will be just the core abilities that can be shared, like navigation, attack methods, emoting (blinking eyes, looking around) etc.

    Then the actually MIND of the Baddie will be in separate classes, so each can be VERY distinct and specific to that Baddie type. The way a Patroller will work, is very specific, whereas a Hunter Killer would have a whole different set of behaviours, like ad-hoc patrolling, and how it moves at high speed.

    Im thinking of starting with a Baddie that follows a kind of Pac Man Ghost kind of pattern, something that is always on the move, patrolling, but which can then swap to low speed pursuit if it spots the player. I'll then test a level with these in before investing any more time in this whole sub-project.

    Putting Baddies in my game is something I had not planned on 100%, but had thought for a while could given an interesting extra dynamic on some levels, and would differentiate the game from other recent games of this ilk. It'll be fun to spin the wheel and see where it points.
     
  12. MrG

    MrG

    Joined:
    Oct 6, 2012
    Posts:
    368
    Care to share that bit of code?
     
  13. person4u2nv

    person4u2nv

    Joined:
    Nov 9, 2019
    Posts:
    1
    Please can you show a simple code on how you made the ball roll?