Still having troubles with this AI script

I still can't seem to figure out whay I can't get my Zombie aAliens to actually do an Attack on my FPS player and how to get that attack to inflict damage to my player. Right now they are aware of me when I get within their attack range and they will come after me with their "Run Attack" which is NOT an attack it's just how my Alien Zombies fiercly run towards my player in order to get close enough to do a clawing and biting attack which is just called "Attack"

Also sometimes when I get out of their range they will sort of "Run on the spot" like they are stuck or something and othertimes they will just walk back to their waypoints... so that is kafuddling me somewhat.

It's getting to the point where I'm just going to say "Frak It!" and just give them weapons and make a gun fire animation just like the robots in the FPS tutorial, which is TOATALLY NOT what I want :(

Now I must confess there is so much here I don't understand like how this script calls or knows which animations to play from the AIanimation script in the first place, but it does somehow. I've never been able to fully understand that whole process. (Head Scratch?!?)

You would think this would be simple, I've tried to keep it simple while I learn this stuff. I only gave them 4 animations to work with:

  1. idle
  2. Walk
  3. RunAttack
  4. Attack

Also they are kinda stoopid, they will walk into a tree and sort of get stuck running aganst the tree instead of moving around it. So I don't know how to fix that either. Seems I'm stuck until I can get this part sorted out. I'm so close to just giving up on this stuff alltogether! :(

Maybe some of you code freaks who are far more code savy than I will know what's going on here. After all this stuff like a simple melee that uses an animation should be old hat to a lot of you more experienced folk. Or does everyone here just use cubes to represent their enemies?!? here is my script for what it's worth:

EDIT I changed my Script following your directions so far no error messages but I can't test it as I updated my "Player Script" whith what you gave me and I do get an error on that script? Maybe it should be Hitpoints?? I'll place that script bellow this.

    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;
    Debug.DrawRay(transform.position, transform.forward * 30, Color.red);
    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);

            else
                RotateTowards(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

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

            var angle = Vector3.Angle(targetDirection, forward);
            if (distance < attackRange){

                var damage = 10;
                target.SendMessage("OnAttack", damage);

                // you probably have some other script managing there
                // animations but you'd typically at this point call
                // modelAnimation.Play("Attack");
                // and you could have the attack animation on a higher
                // layer than other animations to override them.

                yield WaitForSeconds(1);
            }

            yield StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
            //Player not visible anymore - stop attacking
            if (!CanSeeTarget())

            return;

        } 

        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;
}

here is a copy of my FPSplayer.js I do get this error message on this one after placing in what you gave me: Assets/WeaponScripts/FPSPlayer.js(46,9): BCE0005: Unknown identifier: 'health'.

var maximumHitPoints = 100.0;
var hitPoints = 100.0;

var hurtTexture : GUITexture;

var grenadesGUI : GUIText;
var bulletGUI : GUIText;
var shotgunGUI : GUIText;
var rocketGUI : DrawRockets;
var healthGUI : GUITexture;

var walkSounds : AudioClip[];
var painLittle : AudioClip;
var painBig : AudioClip;
var die : AudioClip;
var audioStepLength = 0.3;

var heartRate : AudioClip;

private var machineGun : MachineGun;
private var shotgun : Shotgun;
private var rocketLauncher : RocketLauncher;
private var missileLauncher : MissileLauncher;
private var healthGUIWidth = 0.0;
private var gotHitTimer = -1.0;

var rocketTextures : Texture[];

function Update () {
    hurtTexture.color.a = (1 - (hitPoints/maximumHitPoints));
}

function Awake () {
    shotgun = GetComponentInChildren(Shotgun);
    machineGun = GetComponentInChildren(MachineGun);
    rocketLauncher = GetComponentInChildren(RocketLauncher);
    missileLauncher = GetComponentInChildren(MissileLauncher);

    PlayStepSounds();

    healthGUIWidth = healthGUI.pixelInset.width;
}

function OnAttacked(damage : int){
    //Bugger! We're taking damage now!
    health -= damage;
}

function ApplyDamage (damage : float) {
    if (hitPoints < 0.0)

        return;

    // Apply damage
    hitPoints -= damage;

    // Play pain sound when getting hit - but don't play so often
    if (Time.time > gotHitTimer && painBig && painLittle) {
        // Play a big pain sound
        if (hitPoints < maximumHitPoints * 0.2 || damage > 20) {
            audio.PlayOneShot(painBig, 1.0 / audio.volume);
            gotHitTimer = Time.time + Random.Range(painBig.length * 2, painBig.length * 3);

        } else {
            // Play a small pain sound
            audio.PlayOneShot(painLittle, 1.0 / audio.volume);
            gotHitTimer = Time.time + Random.Range(painLittle.length * 2, painLittle.length * 3);
        }
    }

    // Are we dead?
    if (hitPoints < 0.0)
        Die();
}

function Die () {
    if (die)
        AudioSource.PlayClipAtPoint(die, transform.position);

    // Disable all script behaviours (Essentially deactivating player control)
    var coms : Component[] = GetComponentsInChildren(MonoBehaviour);
    for (var b in coms) {
        var p : MonoBehaviour = b as MonoBehaviour;
        if (p)
            p.enabled = false;
    }

    LevelLoadFade.FadeAndLoadLevel(Application.loadedLevel, Color.white, 2.0);
}

function LateUpdate () {
    // Update gui every frame
    // We do this in late update to make sure machine guns etc. were already executed
    UpdateGUI();
}

function PlayStepSounds () {
    var controller : CharacterController = GetComponent(CharacterController);

    while (true) {
        if (controller.isGrounded && controller.velocity.magnitude > 0.3) {
            audio.clip = walkSounds[Random.Range(0, walkSounds.length)];
            audio.Play();
            yield WaitForSeconds(audioStepLength);
        } else {
            yield;
        }
    }
}

function UpdateGUI () {
    // Update health gui
    // The health gui is rendered using a overlay texture which is scaled down based on health
    // - Calculate fraction of how much health we have left (0...1)
    var healthFraction = Mathf.Clamp01(hitPoints / maximumHitPoints);

    // - Adjust maximum pixel inset based on it
    healthGUI.pixelInset.xMax = healthGUI.pixelInset.xMin + healthGUIWidth * healthFraction;

    // Update machine gun gui
    // Machine gun gui is simply drawn with a bullet counter text
    if (machineGun) {
        bulletGUI.text = machineGun.GetBulletsLeft().ToString();
    }

    // Update Shotgun gui
    // Shotgun gui is simply drawn with a bullet counter text
    if (shotgun) {
        shotgunGUI.text = shotgun.GetBulletsLeft().ToString();
    }

    // Update Missile Launcher gui
    // Missile Launcher gui is simply drawn with a bullet counter text
    //if (missileLauncher) {
        //grenadesGUI.text = missileLauncher.GetBulletsLeft().ToString();
    //}

    // Update rocket gui
    // This is changed from the tutorial PDF. You need to assign the 20 Rocket textures found in the GUI/Rockets folder
    // to the RocketTextures property.
    if (rocketLauncher) {
        rocketGUI.UpdateRockets(rocketLauncher.ammoCount);
        /*if (rocketTextures.Length == 0) {
            Debug.LogError ("The tutorial was changed with Unity 2.0 - You need to assign the 20 Rocket textures found in the GUI/Rockets folder to the RocketTextures property.");
        } else {
            rocketGUI.texture = rocketTextures[rocketLauncher.ammoCount];
        }*/
    }
}

And here is a copy of my "ZombieAlienAIAnimation,js" for you to have a look at and figure out where I might better improve on that one cause I'm sure it needs it. I feel we might be getting close on this one guys :D

Although I'm not sure I fully undersatnd what is taked about "Layers" with animations??

var modelAnimation : Animation;
var minimumRunSpeed = 1.0;

function Start () {
    // Set all animations to loop
    modelAnimation.wrapMode = WrapMode.Loop;

    // Except our action animations, Dont loop those
    //modelAnimation["Attack"].wrapMode = WrapMode.Once;

    // Put idle and run in a lower layer. They will only animate if our action animations are not playing
    modelAnimation["idle"].layer = -1;
    modelAnimation["Walk"].layer = -1;
    modelAnimation["RunAttack"].layer = -1;
    modelAnimation["Attack"].layer = -1;

    modelAnimation.Stop();
}

function SetSpeed (speed : float) {
    if (speed > minimumRunSpeed)
        modelAnimation.CrossFade("RunAttack");
    else
        modelAnimation.CrossFade("idle");

}

I still can't seem to figure out whay I can't get my Zombie Aliens to actually do an Attack on my FPS player and how to get that attack to inflict damage to my player.

You could send a message like "OnAttacked" to the target with the amount of damage inflicted.

// In your AttackPlayer function, change:
// if (distance < attackRange);
// To...

if (distance < attackRange) {

    var damage = 10;
    target.SendMessage("OnAttacked", damage);

    // You probably have some other script managing the
    // animations but you'd typically at this point call 
    // modelAnimation.Play("Attack");
    // and you could have the attack animation on a higher 
    // layer than other animations to override them.

    yield WaitForSeconds(1);
}


// In your Player script:
function OnAttacked(damage : int) {
    // Bugger! We're taking damage now!
    health -= damage;
}

Also sometimes when I get out of their range they will sort of "Run on the spot" like they are stuck or something and othertimes they will just walk back to their waypoints... so that is kafuddling me somewhat.

Well, in your AttackPlayer function, you have this loop:

while (true) {
    if (CanSeeTarget ()) {
       // Code that chase and attack player
    } 
    yield;
}

Imagine what this code will do. If the player hides behind something or walks away from range, CanSeeTarget would return false and it would just yield and try the same thing again. It would be stuck in place. Maybe you could instead change it to a while loop, so it breaks out once it cant see the target.

while (CanSeeTarget()) {
    // Code that chase and attack player
    yield;
}

A general tip would be to try use as small functions as you can. That way spotting these problems become much easier.

Also they are kinda stoopid, they will walk into a tree and sort of get stuck running aganst the tree instead of moving around it.

Sounds like you want pathfinding. I also think there's a ready to use plugin in the asset store to save you some time - at a cost. Pathfinding is a rather lengthy topic to cover in an answer but you could search for A* algorithm. Otherwise you could do obstacle avoidance which isn't true pathfinding but hopefully makes your character avoid obstacles.

A simple implementation of obstacle avoidance would be to see if you can walk forward, then do so. Otherwise, rotate to any free direction. You could have two raycasts to left and right forward side (think a V shape) and whatever raycast return the longest distance should be favored the correct turn direction.