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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Hovering enemy AI and navigation

Discussion in 'Physics' started by AgentParsec, Jan 27, 2017.

  1. AgentParsec

    AgentParsec

    Joined:
    May 5, 2012
    Posts:
    403
    In an app I'm working on, there will be enemies that will need to hover around, avoiding terrain and obstacles and moving in relation to the player's position (who also had the ability to hover in limited quantities, so they will not always be on the ground). The normal navmesh pathfinding is restricted to movement directly on the mesh, at least as far as I've been able to determine. Is there an easy way to accomplish this kind of movement? I see games do it all the time, so I imagine it can't be THAT hard, yet I could find surprisingly little about how to actually do it. Does anyone have a good place to start?

    *EDIT* I should mention that it's a 3D game, not 2D.
     
  2. AgentParsec

    AgentParsec

    Joined:
    May 5, 2012
    Posts:
    403
    Bumping this. Does anyone have any info I could use?
     
  3. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,120
    I'm not sure how helpful this will all be, as I'm still in the process of building this exact functionality into my game. (I have some drones that wander around seeking out the player, then pursue the player when they get close enough.) But this might be one approach to get you started.

    My first pass approach to this was to build a very simple PID controller for the position of the drone. At any given time, the drone has a TargetPosition (Vector3). The PID controller applies force to the drone to push the drone to that position. When the drone is patrolling, it just cycles through a list of positions it should visit in order. When the player gets close enough, it switches to Attack mode, and instead of following a pre-defined path, it continually targets the player's location. The result is that the drone will patrol an area, then chase the player.

    Here's the code for my PID controller:

    Code (CSharp):
    1.    
    2.     Vector3 totalError = new Vector3( 0, 0, 0 );
    3.     Vector3 lastError = new Vector3( 0, 0, 0 );
    4.  
    5.     void FixedUpdate()
    6.     {
    7.         var currentError = gameObject.transform.position - this._interimDestinationPosition;
    8.  
    9.         Vector3 cp = currentError * Kp;
    10.         Vector3 cd = Kd * (lastError - currentError) / Time.deltaTime;
    11.         Vector3 ci = totalError * Ki * Time.deltaTime;
    12.  
    13.         lastError = currentError;
    14.         totalError += currentError;
    15.  
    16.         var navigationForce = Vector3.ClampMagnitude( cp + ci + cd, 300 );
    17.         var standardForce = _rigidbody.useGravity ? (Physics.gravity * _rigidbody.mass * -1) : new Vector3( 0, 0, 0 );
    18.  
    19.         var finalForce = standardForce - navigationForce;
    20.  
    21.         _rigidbody.AddForce( finalForce );
    22.     }
    Kp, Kd, and Ki are all constants you can tweak to fine tune the controller. "_interimDestinationPosition" is the position I want the drone to end up. I change _interimDestinationPosition to either the player's position, or one of my patrol positions, with some other logic I didn't include here.


    This all works kind of well, but it has a major downside: The drone can easily get stuck. If it chases the player off in some direction, for example around a corner, then it gives up, it's not smart enough to find its way back to its patrol route. I currently self-destruct my drone if it gets stuck.

    The much better approach, which I'm still finishing up, is using a proper path-finding algorithm, like A*, to move between points efficiently without getting stuck. That's a MUCH bigger effort, which involves determining all the valid positions your object can occupy in your level, and implementing A* in 3D. I've done that work, and it functions reasonably well, but now I'm improving it with a 3D Jump Point search implementation to make it faster. (My levels tend to be large, wide-open rooms, so Jump Point should be more efficient than A*). Anyway, no code to share for that yet, as it's not done.

    Hope this helped a little.