I'm still having Trouble with this AI script

OK I've made some changes to my Alien Zombie AI script but I still can't seem to get it to function the way it sould. Right now my Alien Zombies will follow me arround like lost puppies if I get within their attack range. And when I get out of range instead of returning to their patrol routine or even going back to just plain "Idle" they kind of run on the spot doing their "RunAttack" animation?? It's cufuddling me buggy trying to figure out why they are doing that.

Also I can't figure out how to get my Alien Zombie to inflict damage to my FPS player using his "Attack" animation when he is right in front of him or right up close if you like??

Here is my code so far: Sorry for posting this same question only asked differently but they seem to get lost after a while and get no more responses.

var speed = 3.0;
var rotationSpeed = 5.0;
var attackRange = 30.0;
var dontComeCloserRange = 5.0;
var pickNextWaypointDistance = 2.0;
var target : Transform;
var modelAnimation : Animation;

// Make sure there is always a character controller
@script RequireComponent (CharacterController)

function Start () {
    // Auto setup player as target through tags
    if (target == null && GameObject.FindWithTag("Player"))
        target = GameObject.FindWithTag("Player").transform;

    Patrol();
}

function Patrol () {
    var curWayPoint = AutoWayPoint.FindClosest(transform.position);
    while (true) {
        var waypointPosition = curWayPoint.transform.position;
        // Are we close to a waypoint? -> pick the next one!
        if (Vector3.Distance(waypointPosition, transform.position) < pickNextWaypointDistance)
            curWayPoint = PickNextWaypoint (curWayPoint);

        // Attack the player and wait until
        // - player is killed
        // - player is out of sight     
        if (CanSeeTarget ())
            yield StartCoroutine("AttackPlayer");

        // Move towards our target
        MoveTowards(waypointPosition);

        yield;
    }
}

function CanSeeTarget () : boolean {
    if (Vector3.Distance(transform.position, target.position) > attackRange)
        return false;

    var hit : RaycastHit;
    if (Physics.Linecast (transform.position, target.position, hit))
        return hit.transform == target;

    return false;
}

function AttackPlayer () {
    var lastVisiblePlayerPosition = target.position;
    while (true) {
        if (CanSeeTarget ()) {
            // Target is dead - stop hunting
            if (target == null)
                return;

            // Target is too far away - give up 
            var distance = Vector3.Distance(transform.position, target.position);
            if (distance > attackRange * 3)
                return;

            lastVisiblePlayerPosition = target.position;
            if (distance > dontComeCloserRange)
                MoveTowards (lastVisiblePlayerPosition);

                //Attack player with "Attack" animation which is       basically a clawing and biting animation
            //this "Attack" is supposed to inflict damage to the FPS player
            else {
                modelAnimation.CrossFade("Attack");
                RotateTowards(lastVisiblePlayerPosition);
            }

            var forward = transform.TransformDirection(Vector3.forward);
            var targetDirection = lastVisiblePlayerPosition - transform.position;
            targetDirection.y = 0;

            var angle = Vector3.Angle(targetDirection, forward);
        } 

        yield;
    }
}

function SearchPlayer (position : Vector3) {
    // Run towards the player but after 3 seconds timeout and go back to Patroling
    var timeout = 3.0;
    while (timeout > 0.0) {
        MoveTowards(position);

        // We found the player
        if (CanSeeTarget ())
            return;

        timeout -= Time.deltaTime;
        yield;
    }
}

function RotateTowards (position : Vector3) {
    SendMessage("SetSpeed", 0.0);

    var direction = position - transform.position;
    direction.y = 0;
    if (direction.magnitude < 0.1)
        return;

    // Rotate towards the target
    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);
}

function MoveTowards (position : Vector3) {
    var direction = position - transform.position;
    direction.y = 0;
    if (direction.magnitude < 0.5) {
        SendMessage("SetSpeed", 0.0);
        return;
    }

    // Rotate towards the target
    transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime);
    transform.eulerAngles = Vector3(0, transform.eulerAngles.y, 0);

    // Modify speed so we slow down when we are not facing the target
    var forward = transform.TransformDirection(Vector3.forward);
    var speedModifier = Vector3.Dot(forward, direction.normalized);
    speedModifier = Mathf.Clamp01(speedModifier);

    // Move the character
    direction = forward * speed * speedModifier;
    GetComponent (CharacterController).SimpleMove(direction);

    SendMessage("SetSpeed", speed * speedModifier, SendMessageOptions.DontRequireReceiver);
}

function PickNextWaypoint (currentWaypoint : AutoWayPoint) {
    // We want to find the waypoint where the character has to turn the least

    // The direction in which we are walking
    var forward = transform.TransformDirection(Vector3.forward);

    // The closer two vectors, the larger the dot product will be.
    var best = currentWaypoint;
    var bestDot = -10.0;
    for (var cur : AutoWayPoint in currentWaypoint.connected) {
        var direction = Vector3.Normalize(cur.transform.position - transform.position);
        var dot = Vector3.Dot(direction, forward);
        if (dot > bestDot && cur != currentWaypoint) {
            bestDot = dot;
            best = cur;
        }
    }

    return best;
}

The animation can fool you -- for example, your code may be correctly not moving for a while, but the runAttack animation you started 6 seconds ago is still playing, so you think the code is trying to run.

Maybe leave animation off, so you can focus on the movement and turning. Once the code works, there are usually very obvious places to set animation. For example, whenever the code sets direction to 0, also play "idle."

For checking the move code, these are two old programming tricks, Unity style:

o Add things like `Debug.Log("Back to patrol from attack");` so you can see if the flow is correct.

o Show some vars in the inspector: Make `public var ShowWayPnt : Transform;` and set it in Patrol: `ShowWayPnt = waypointPosition;` This will tell you if the stall is because you're on the Waypoint already, or if `direction` is somehow always set to 0 (do the same thing to show `direction`.)

Eventually, you'll get a result that isn't what you expected, which leads to the problem.

Try setting rotation speed a little bit higher, if they spin around you in circles. I hope this answers your question! :wink: