Enemy Police Guy won't attack player

Hi Guys

I have done the 3d Platform Tutorial and had no problem with robot detecting and attacking the Player.

I built another 3d platform based on the tutorial just using my own models.

Using the Enemy Police Guy Script I created the same animations threaten attackrun etc. all the setting seem the same and I can find no reference to Copper in the script.

I have played with it for days but for some reason the enemy will not detect or attack the player?

I have attached a screen shot showing most of the settings.

Any input would be great.

Thanks
Thor

You may want to attach your Enemy Police Guy script and screenshots of the collider component settings for both the enemy and the player character so that folks can get a better idea of where your problem lies.

Also, try adding:

print(“see Something”);

(or something to that effect) to your OnTriggerEnter function so you can determine whether the problem is actually with detecting the player or with executing his attack. My guess would be that it is just the detection, which in turn fails to execute the attack.

Which version of Unity are you using? 2.x or 3? There are different variables to consider for different versions.

You might check your collider/rigidbody settings against the Collision Action Matrix(Unity - Manual: Box collider component reference).

But start by providing a bit more info in your post.

EDIT: I just noticed the Unity3 interface in your screenshot. So you may also want to check your Layer Collision Matrix settings, under Edit>Project Settings>Physics, and make sure your two characters are in layers that will collide.

It’s hard to suggest what could be wrong without more information. A good approach would be to add a print statement to the Attack function to check whether or not it is being called. You can then refine the process by placing the print statement in different places within the function. Basically, you need to place it inside the “while” and “if” statements to see if execution ever goes into them. If not, it implies that the loop condition is never met - this gives you more information that can help narrow down the cause of the problem.

Hi andeee and Psychor

I have attached as per your suggestion the enemypoliceguy script as js hope it can be seen. It is just the unchanged script which comes with the Lerpz tutorial.

Could not find a Layer Collision Matrix settings under Edit Project Settings Physics?

When you speak of the collider component settings of enemy and player, both of the models/characters have a character controller attached as per the tutorial instructions.
I assume these are the same as a Rigid Body collider?

Regards
Thor

382341–13199–$enemypoliceguy_427.js (6.15 KB)

I took a look at your script and will post it here so it’s easier for more people to help you.

I wonder what is supposed to trigger the attack? Usually you have a big sphere collider around the NPC that is set “isTrigger” so when the player enters it there is a OnTriggerEnter() function that begins attack.

Also, there is no Update() function. That’s the function that is checked every frame. Even if the NPC is triggered from some other game object, there will need to be an Update() function that has a state for attacking like this:

var attacking:boolean = false;
Function Update()
{
    if(attacking)
    // move towards player
    // attack, keep track of damage, etc.
}

Here is your original code:

/*
	animations played are:
	idle, threaten, turnjump, attackrun
*/

var attackTurnTime = 0.7;
var rotateSpeed = 120.0;
var attackDistance = 17.0;
var extraRunTime = 2.0;
var damage = 1;

var attackSpeed = 5.0;
var attackRotateSpeed = 20.0;

var idleTime = 1.6;

var punchPosition = new Vector3 (0.4, 0, 0.7);
var punchRadius = 1.1;

// sounds
var idleSound : AudioClip;	// played during "idle" state.
var attackSound : AudioClip;	// played during the seek and attack modes.

private var attackAngle = 10.0;
private var isAttacking = false;
private var lastPunchTime = 0.0;

var target : Transform;

// Cache a reference to the controller
private var characterController : CharacterController;
characterController = GetComponent(CharacterController);

// Cache a link to LevelStatus state machine script:
var levelStateMachine : LevelStatus;

function Start ()
{
	levelStateMachine = GameObject.Find("/Level").GetComponent(LevelStatus);

	if (!levelStateMachine)
	{
		Debug.Log("EnemyPoliceGuy: ERROR! NO LEVEL STATUS SCRIPT FOUND.");
	}

	if (!target)
		target = GameObject.FindWithTag("Player").transform;
	
	animation.wrapMode = WrapMode.Loop;

	// Setup animations
	animation.Play("idle");
	animation["threaten"].wrapMode = WrapMode.Once;
	animation["turnjump"].wrapMode = WrapMode.Once;
	animation["gothit"].wrapMode = WrapMode.Once;
	animation["gothit"].layer = 1;
	
	// initialize audio clip. Make sure it's set to the "idle" sound.
	audio.clip = idleSound;
	
	yield WaitForSeconds(Random.value);
	
	// Just attack for now
	while (true)	
	{
		// Don't do anything when idle. And wait for player to be in range!
		// This is the perfect time for the player to attack us
		yield Idle();

		// Prepare, turn to player and attack him
		yield Attack();
	}
}


function Idle ()
{
	// if idling sound isn't already set up, set it and start it playing.
	if (idleSound)
	{
		if (audio.clip != idleSound)
		{
			audio.Stop();
			audio.clip = idleSound;
			audio.loop = true;
			audio.Play();	// play the idle sound.
		}
	}
	
	// Don't do anything when idle
	// The perfect time for the player to attack us
	yield WaitForSeconds(idleTime);

	// And if the player is really far away.
	// We just idle around until he comes back
	// unless we're dying, in which case we just keep idling.
	while (true)
	{
		characterController.SimpleMove(Vector3.zero);
		yield WaitForSeconds(0.2);
		
		var offset = transform.position - target.position;
		
		// if player is in range again, stop lazyness
		// Good Hunting!		
		if (offset.magnitude < attackDistance)
			return;
	}
} 

function RotateTowardsPosition (targetPos : Vector3, rotateSpeed : float) : float
{
	// Compute relative point and get the angle towards it
	var relative = transform.InverseTransformPoint(targetPos);
	var angle = Mathf.Atan2 (relative.x, relative.z) * Mathf.Rad2Deg;
	// Clamp it with the max rotation speed
	var maxRotation = rotateSpeed * Time.deltaTime;
	var clampedAngle = Mathf.Clamp(angle, -maxRotation, maxRotation);
	// Rotate
	transform.Rotate(0, clampedAngle, 0);
	// Return the current angle
	return angle;
}

function Attack ()
{
	isAttacking = true;
	
	if (attackSound)
	{
		if (audio.clip != attackSound)
		{
			audio.Stop();	// stop the idling audio so we can switch out the audio clip.
			audio.clip = attackSound;
			audio.loop = true;	// change the clip, then play
			audio.Play();
		}
	}
	
	// Already queue up the attack run animation but set it's blend wieght to 0
	// it gets blended in later
	// it is looping so it will keep playing until we stop it.
	animation.Play("attackrun");
	
	// First we wait for a bit so the player can prepare while we turn around
	// As we near an angle of 0, we will begin to move
	var angle : float;
	angle = 180.0;
	var time : float;
	time = 0.0;
	var direction : Vector3;
	while (angle > 5 || time < attackTurnTime)
	{
		time += Time.deltaTime;
		angle = Mathf.Abs(RotateTowardsPosition(target.position, rotateSpeed));
		move = Mathf.Clamp01((90 - angle) / 90);
		
		// depending on the angle, start moving
		animation["attackrun"].weight = animation["attackrun"].speed = move;
		direction = transform.TransformDirection(Vector3.forward * attackSpeed * move);
		characterController.SimpleMove(direction);
		
		yield;
	}
	
	// Run towards player
	var timer = 0.0;
	var lostSight = false;
	while (timer < extraRunTime)
	{
		angle = RotateTowardsPosition(target.position, attackRotateSpeed);
			
		// The angle of our forward direction and the player position is larger than 50 degrees
		// That means he is out of sight
		if (Mathf.Abs(angle) > 40)
			lostSight = true;
			
		// If we lost sight then we keep running for some more time (extraRunTime). 
		// then stop attacking 
		if (lostSight)
			timer += Time.deltaTime;	
		
		// Just move forward at constant speed
		direction = transform.TransformDirection(Vector3.forward * attackSpeed);
		characterController.SimpleMove(direction);

		// Keep looking if we are hitting our target
		// If we are, knock them out of the way dealing damage
		var pos = transform.TransformPoint(punchPosition);
		if(Time.time > lastPunchTime + 0.3  (pos - target.position).magnitude < punchRadius)
		{
			// deal damage
			target.SendMessage("ApplyDamage", damage);
			// knock the player back and to the side
			var slamDirection = transform.InverseTransformDirection(target.position - transform.position);
			slamDirection.y = 0;
			slamDirection.z = 1;
			if (slamDirection.x >= 0)
				slamDirection.x = 1;
			else
				slamDirection.x = -1;
			target.SendMessage("Slam", transform.TransformDirection(slamDirection));
			lastPunchTime = Time.time;
		}

		// We are not actually moving forward.
		// This probably means we ran into a wall or something. Stop attacking the player.
		if (characterController.velocity.magnitude < attackSpeed * 0.3)
			break;
		
		// yield for one frame
		yield;
	}

	isAttacking = false;
	
	// Now we can go back to playing the idle animation
	animation.CrossFade("idle");
}

function ApplyDamage ()
{
	animation.CrossFade("gothit");
}

function OnDrawGizmosSelected ()
{
	Gizmos.color = Color.yellow;
	Gizmos.DrawWireSphere (transform.TransformPoint(punchPosition), punchRadius);
	Gizmos.color = Color.red;
	Gizmos.DrawWireSphere (transform.position, attackDistance);
}

@script RequireComponent(AudioSource)

I have tried adding a collider which then wants to replace the character controller but the enemypoliceguy script wants to find the character controller when the script runs.

I have also removed the character controller (which works) in the Lerpz tutorial and replace with a collider and it stops working.

Seems the attack distance should trigger the attack and does so in the Lerpz tutorial.

It’s strange hard to figure out as I don’t really know javascript.

When I add the copper prefab (in Leprz tutorial) which has a character controller
already it works fine, if add new model then a character controller and the enemy script it won’t work in the Leprz tutorial neither which leads me to think it only work with the copper (Leprz tutorial) animations and prefab?

So far following the tutorial everything works, pick up’s, GUI, player controller everything but the enemy script.

Regards
Thor

http://www.digitalviking.com/3D/idle_viking1.html

Thor,

Sorry I can’t be of more help. I hope someone with the Lerpz tutorial still on their computer can see what is missing for you.

Keep at it, though. I started with the Lerpz tutorial 8 months ago and have been learning and learning. By now I could make that script work in three different ways, but I don’t want to start you on a wild goose chase when there’s probably just some minor thing missing. At your stage it’s a good idea to re-use that tutorial so you can just make a game and have some fun. Later on, though, you will be able to trigger enemies in different ways, such as:

  1. Have a collider for each enemy as a child object. Since the collider is attached to an empty game object and is a child of the player, it won’t interfere with the character controller. When that collider gets triggered then it would tell the main script to attack.

  2. Have a collider atttached to the boat that detects when the player comes on board and tells the enemies that he’s there. Use this with number 3.

  3. Have the enemies’ script check the distance to the player, and when he’s close, then trigger the attack. You want to use this with number 2, turning it on when the player is on the boat, turning off when player leaves, because having every enemy check distance every frame on entire level would slow your game down quick.

I just mention these to point you in the right direction for the future. You could use them now, but there will be tricks and complications for each one. For now I hope someone will come on and give you the ‘quick fix’ so you can keep on having fun.

Cheers!

Hi Vimalakirti

Thanks for the input Vimalakirti, I too think I am just missing something simple.

Not much for it but to just keep at it.

Regards
Thor

On line 39 in the enemy Police guy script I changlevelStateMachine = GameObject.Find(“level”)
to levelStateMachine = GameObject.Find(“Player”)

Thanks to Runner 1018

thor your change is not working but i found something rather interesting.
around the line 162 something got messed up here the funny thing is it not even showing up in debug.
// depending on the angle, start moving
animation[“attackrun”].weight = animation[“attackrun”].speed = move; :face_with_spiral_eyes:

so i separate them like it should be
// well … if you change weight value above 0,01 something around your robot wont walk .
animation[“attackrun”].weight = 0;
//or you can comment it
animation[“attackrun”].speed = 0;

et Voila it working now.