Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Unity Issue: AI Ally Twitching (Top down shooter)

Options
  • 22-08-2013 1:18pm
    #1
    Registered Users Posts: 454 ✭✭


    Hi guys, posted this on unity answers. Thought i'd try it here to see if anyone can figure it out.



    I've encountered a problem with an AI ally (armed with a gun) twitching (rotating rapidly side to side on the Y axis) when enemies get close. I think it's either caused by the ally and enemy rigidbodies bumping off one another, or the ally trying to keep its weapon pointed at an up close enemy.


    I tried changing some of the properties of the rigidbody (mass, drag, angular) to no avail. Also commented out the code which rotates the ally toward the enemy. This prevents the twitching, but the ally isn't much use if it doesn't aim at enemies.


    Update 1: Increasing the radius of the ally's capsule collider from 0.3 to 0.6 seems to have solved the problem. The enemies can't get so close now. This might suggest that the targetting/rotation code for the ally doesn't handle close up calculations very well, rather than it being a problem with collisions between rigidbodies. Using a oversize collider isn't a very good solution though, so an alternate one would be nice.

    I've included the code the ally uses to rotate/track targets. If you need any more info, please ask. Thanks!
    1. public void RotateToTarget()
    2. {
    3. // Predict time it will take a bullet to reach enemy
    4. float secsFlightTime = (targetPosition - centreBulletSpawn.transform.position).magnitude / bulletSpeed;
    5. // Get current velocity of target
    6. Vector3 targetMovePerSec = target.rigidbody.velocity;
    7. targetMovePerSec.y=0;
    8. // Predict the future position of the target
    9. Vector3 estHitPos = targetPosition + targetMovePerSec * secsFlightTime;
    10. // Get the rotation needed to hit the enemy
    11. Vector3 aimDirection = estHitPos - centreBulletSpawn.transform.position;
    12. // Rotate turret to face that position
    13. Quaternion neededRotation = Quaternion.LookRotation(aimDirection);
    14. transform.rotation = Quaternion.Slerp(transform.rotation, neededRotation, rotationSpeed * Time.deltaTime);
    15. //transform.rotation = neededRotation;
    16. }


Comments

  • Registered Users Posts: 454 ✭✭Kilgore__Trout


    Just after I posted, I remembered I'd thought of a possible solution last night, but hadn't tried it yet. Can't delete the post, so may as well bring closure. Figured it might have something to do with trying to estimate the future position of an enemy who is already really close, so I added a distance check and only estimated the future position of the target if it was more than 2 units away.

    Here's the new code:

    // Estimates the target's position when the bullet will hit, and rotates toward it
    public void RotateToTarget()
    {
    // Do a distance check to see how far away the enemy is
    float distToEnemy = Vector3.Distance(position, targetPosition);

    // If the enemy is more than 2 units away
    if(distToEnemy > 2)
    {
    // Predict time it will take a bullet to reach enemy
    float secsFlightTime = (targetPosition - centreBulletSpawn.transform.position).magnitude / bulletSpeed;

    // Get current velocity of target
    Vector3 targetMovePerSec = target.rigidbody.velocity;
    targetMovePerSec.y=0;

    // Predict the future position of the target
    Vector3 estHitPos = targetPosition + targetMovePerSec * secsFlightTime;

    // Get the rotation needed to hit the enemy
    Vector3 aimDirection = (estHitPos - centreBulletSpawn.transform.position).normalized;

    // Rotate turret to face that position
    Quaternion neededRotation = Quaternion.LookRotation(aimDirection);
    transform.rotation = Quaternion.Slerp(transform.rotation, neededRotation, rotationSpeed * Time.deltaTime);
    }

    // Else, the enemy is less than 2 units away
    else
    {
    // Get the rotation needed to hit the enemy
    Vector3 aimDirection = (targetPosition - position).normalized;

    // Rotate turret to face that position
    Quaternion neededRotation = Quaternion.LookRotation(aimDirection);
    transform.rotation = Quaternion.Slerp(transform.rotation, neededRotation, rotationSpeed * Time.deltaTime);
    }
    }


Advertisement