Making AI jump on a spot effectively

Posted by Pasquale Sada on Game Development See other posts from Game Development or by Pasquale Sada
Published on 2012-09-29T15:41:40Z Indexed on 2012/10/05 15:57 UTC
Read the original article Hit count: 253

Filed under:

How to calculate, in 3D environment, the closest point, from which an AI character can jump onto a platform?

Setup

I have an initial velocity V(Vx,Vy,VZ) and a spot where the character stands still at S(Sx,Sy,Sz). What I'm trying to achieve is a successful jump on a spot E(Ex,Ey,Ez) where you have clicked on(only lower or higher spot, because I've in place a simple steering behavior for even terrains). There are no obstacles around.

I've implemented a formula that can make him jump in a precise way on a spot but you need to declare an angle: the problem arise when the selected spot is straight above your head. It' pretty lame that the char hang there and can reach a thing that is 1cm above is head. I'll share the code I'm using:

    Vector3 dir = target - transform.position;  // get target direction
    float h = dir.y;  // get height difference
    dir.y = 0;  // retain only the horizontal direction
    float dist = dir.magnitude ;  // get horizontal distance
    float a = angle * Mathf.Deg2Rad;  // convert angle to radians
    dir.y = dist * Mathf.Tan(a);  // set dir to the elevation angle
    dist += h / Mathf.Tan(a);  // correct for small height differences
    // calculate the velocity magnitude
    float vel = Mathf.Sqrt(dist * Physics.gravity.magnitude / Mathf.Sin(2 *a));
    return vel * dir.normalized;

Ended up using the lowest angle (20 degree) and checking for collision on the trajectory. If found any increase the angle. Here some code (to improve the code maybe must stop the check at the highest point of the curve):

Vector3 BallisticVel(Vector3 target, float angle) 
    {
        Vector3 dir = target - transform.position;  // get target direction
        float h = dir.y;  // get height difference
        dir.y = 0;  // retain only the horizontal direction
        float dist = dir.magnitude ;  // get horizontal distance
        float a = angle * Mathf.Deg2Rad;  // convert angle to radians
        dir.y = dist * Mathf.Tan(a);  // set dir to the elevation angle
        dist += h / Mathf.Tan(a);  // correct for small height differences
        // calculate the velocity magnitude
        float vel = Mathf.Sqrt(dist * Physics.gravity.magnitude / Mathf.Sin(2 * a));
        return vel * dir.normalized;
    }

    Vector3 TrajectoryPoint(Vector3 startingPosition, Vector3 startingVelocity, float n )
    {
         float t = 1/60 ; // seconds per time step 
      Vector3 stepVelocity = t * startingVelocity; // m/s
      Vector3 stepGravity = t * t * Physics.gravity; // m/s/s


      return startingPosition + n * stepVelocity + 0.5f * (n*n+n) * stepGravity;
    }

    bool CheckTrajectory(Vector3 startingPosition,Vector3 target, float angle_jump)
    {
        Debug.Log("checking");
        if(angle_jump < 80f)
        {
            Debug.Log("if");

            Vector3 startingVelocity = BallisticVel(target, angle_jump);

            for (int i = 0; i < 180; i++) 
            { 
                //Debug.Log(i);
                Vector3 trajectoryPosition = TrajectoryPoint( startingPosition, startingVelocity, i );


                if(Physics.Raycast(trajectoryPosition,Vector3.forward,safeDistance))
                {
                    angle_jump += 10;
                    break; // restart loop with the new angle
                }
                else
                    continue;

            }

                return true;
                JumpVelocity = BallisticVel(target, angle_jump);
            }

        return false;
    }

© Game Development or respective owner

Related posts about physics