Playing animations in basic AI

Sooooo I’ve been trolling through the forums for quite some time and tried numerous suggestions people have offered for issues I would consider similar to mine, only nothing will work for me…

Basically, the “KillerPlant” you see before you has 2 animations, being “idle” and “attack”.

I’ve managed to get the plant to rotate and spit it’s little spore things at the player which is what it should be doing, but I can’t for the life of me get the idle and attack animations to play at all(and this is stupidly basic).

When the plant Spits, I want the “attack” animation to blend in and for it to idle at any other time.

Here is my code (yes i did say it was basic :smile: ) Obviously there is another script on the spore launcher game object too… Just after suggestions on how to fix this/why it didn’t work in the first place?? Cheers.

//AI PLANT 

var spittingRange = 30.0; 
var spittingAngleDistance = 10.0; 
var target : Transform; 

function Start () 
{ 

	//Set animations to loop 
	animation.wrapMode = WrapMode.Loop; 
	
	animation.CrossFade("idle"); 
	animation["attack"].wrapMode = WrapMode.Once; 
	
	if (target == null  GameObject.FindWithTag("Player")) 
	{ 
		target = GameObject.FindWithTag("Player").transform; 
	} 
} 


function Update () 
{ 
	if (target == null) 
	{ 
		return; 
	} 
	
	if (!CanSeeTarget ()) 
	{ 
		return; 
	} 
	
	// Rotate towards target 
	var targetPoint = target.position; 
	var targetRotation = Quaternion.LookRotation (targetPoint - transform.position, Vector3.up); 
	transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * 2.0); 
	
	// If we are almost rotated towards target - fire one clip of ammo 
	var forward = transform.TransformDirection(Vector3.forward); 
	var targetDir = target.position - transform.position; 
	if (Vector3.Angle(forward, targetDir) < spittingAngleDistance) 
	{ 
		//SendMessage("Fire"); 
		BroadcastMessage("Spit"); 
		SendMessage("playAttack"); 
	} 
} 

function playAttack() 
{ 
	animation.CrossFade("attack"); 
} 

function CanSeeTarget () : boolean 
{ 
	if (Vector3.Distance(transform.position, target.position) > spittingRange) 
		return false; 
	
	var hit : RaycastHit; 
	
	if (Physics.Linecast (transform.position, target.position, hit)) 
		return hit.transform == target; 
	
	return false; 
}

Mmm, edited your post, I have. (The image was too big for the page and added very little; also, I’ve put some code tags on your script to make it more readable.)

First things to try… put a Debug.Log after the CanSeeTarget “if” statement to check if the code after that point gets executed. If so, try another Debug.Log just after the SendMessage(“playAttack”) (still inside the curly brace, I mean). You need to establish whether the animation code is being called at all.

Sooo apologies here, I broke the link to the animations somehow when rotating the plant around to make it look down the X-axis instead of the Z-axis, but I had no way of knowing that. I re-added the model as part of some mad plan and wouldn’t you know it, it worked…

Now I’m finding that when trying to adapt your FPS AI script for a melee character, I’m having an issue whereby my character keeps rotating on the spot at the same time as it walks towards you… all the animations are playing, only it looks like it’s trying to do something it shouldn’t which confuses me since this is practically the FPS animation scrip, just without the Waypoints code and some different animations as they are melee-type characters. I’m currently studying and I’ve had my tutors look over the code without any joy in terms of a solution.

Would be forever greatful if someone can shed some light here.

var speed = 3.0;
var rotationSpeed = 5.0;
var swingRange = 5.0;
var attackRange = 30.0;
//var swingAngle = 30.0;
var dontComeCloserRange = 4.0;
var delaySwingTime = 0.5;
//var pickNextWaypointDistance = 2.0;
var target : Transform;

private var lastSwing = -10.0;

// 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 () 
{
	while (true) 
	{
		if (CanSeeTarget ())
		{
			yield StartCoroutine("AttackPlayer");
		}
		
		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 Melee () 
{
	// Start swinging ("attack") animation
	//animation.CrossFade("attack, 0.3");
	Debug.Log("running melee");
	animation.Play("attack");

	// Wait until half the animation has played
	yield WaitForSeconds(delaySwingTime);		//make this the time it takes to backswing.
	
	// Wait for the rest of the animation to finish
	yield WaitForSeconds(animation["attack"].length - delaySwingTime);
}


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);
			}
			
			var forward = transform.TransformDirection(Vector3.forward);
			var targetDirection = lastVisiblePlayerPosition - transform.position;
			targetDirection.y = 0;

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

			// Starting if close and player is in sight
			//if (distance <= swingRange  angle <= swingAngle)
			if (distance <= swingRange)
				yield StartCoroutine("Melee");
				
		yield;		
		} 
		else 
		{
			yield StartCoroutine("SearchPlayer", lastVisiblePlayerPosition);
			// Player not visible anymore - stop attacking
			if (!CanSeeTarget ())
				return;
		}
	}
}

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);							//don't know what this does???
	
	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);
}

Problem Solved… Once again, a matter of re-making the prefab from scratch. I can’t find any reason for this, but at least I know my script was working. Can close this off if you like.