OnTriggerEnter - storing the target

Hello everyone,

I’m relatively new to Unity but I’m having a blast with it so far. I’ve got a syntax question that I was hoping someone could help me with.

In my game, I want my AI to damage objects as they pass by them. I’m got a sphere collider on the objects and have tagged them as “destructibleBuildings”. Once the AI hit the trigger they pass a message to the object that reduces their health by n amount. That all works fine right now.

But now I want the AI to do a few more things, specifically I want them to continue to attack on a slight delay for as long as they’re near the object. To do that I think that I’ll need to know which object specifically the AI is targeting.

I believe step one is to assign/store the object in question to a variable and I have no idea how to do that.

This is what I have now as the basic test:
function OnTriggerEnter(other : Collider)
{
if(other.gameObject.tag == “DestructibleBuilding”)
{
Debug.Log(“The Enemy Has Attacked”);
other.gameObject.SendMessage(“Damage”, Damage);

}
}

My plan is that once I can store the object as “Target” then I can add an if/then to the Update function to have the AI attack the target object on whatever delay I want.

Can anyone help me with learning how to assign other.gameobject to a variable?

It’s as simple as creating a GameObject variable and just assiging other.gameObject to it.

var target : GameObject;

function OnTriggerEnter(other : Collider)
{
     if(other.gameObject.tag == "DestructibleBuilding")
     {
          target = other.gameObject;
          Debug.Log("The Enemy Has Attack");
          target.SendMessage("Damage", Damage);
     }
}
1 Like

To assign other.gameObject to a variable in your script you have to do two things:

  1. Declare a GameObject member variable inside of your class.

  2. Assign other.gameObject to that variable.

If you want to make it accessible from other scripts, make it a public member variable. You can then reference your script and its public GameObject variable via another script.

Example code for attacking your target with a specified delay:

#pragma strict

public var enemyObject : GameObject;
public var Damage : float;
public var attackCooldown : float;

function OnTriggerEnter(other : Collider) {
	if (other.gameObject.tag == "DestructibleBuilding") {
		enemyObject = other.gameObject;
		Attack();
		Debug.Log("The Enemy Has Attacked.");
	}
}

function OnTriggerStay(other : Collider) {
	if (other.gameObject == enemyObject) {
		StartCoroutine(AttackCoroutine());
	}
}

function AttackCoroutine() {
	yield WaitForSeconds(attackCooldown);
	Attack();
}

function Attack() {
	enemyObject.SendMessage("Damage", Damage);
}

Note that this uses a coroutine, and not an if-statement in the Update() method. I highly suggest looking into coroutines for situations like this one, they’re very useful and make the task you’re trying to accomplish much easier than dealing with if-statements and timers in Update().

Thanks guys! This is a huge help!

Ruub - I tried doing exactly what you’ve got listed above (and several different versions), but I ran into similar problems no matter what I tried.

First - Wait for seconds doesn’t seem to be seconds - it seems like its more like frames as my enemy object health drops rapidly. So rapidly its often hard to catch.

Second - OnTriggerStay seems to be slowing the game down to a near stand still. I’ve got maybe 5 or 6 AI on the screen and just a few simple shapes. As soon as my AI start to enter the collision area things slow down. When they leave, it’s back to normal.

I also tried doing all of this in an Update function to see if that would work, but once I started typing it out I realized I don’t know if its even possible to call and If on a function like OnTriggerEnter inside of an update.

I’m going to keep thinking about it and do so more digging, but if any you guys out there could lend a novice a hand, I’d really appreciate it! :slight_smile:

The way I would probably do it is with a coroutine like Ruub said, but I personally wouldn’t use OnTriggerStay. I’d do something like this.

var enemyTarget : GameObject;
var Damage : float;
var attackCooldown : float;
var attacking : bool;
 

function OnTriggerEnter(other : Collider)
{
     if(other.gameObject.tag == "DestructibleBuilding")
     {
          enemyTarget = other.gameObject;
          Debug.Log("The Enemy Has Attack");
          attacking = true;
          Attack();
     }
}

function OnTriggerExit(other : Collider){
     if(other.gameObect = enemyTarget){
          attacking = false;
     }
}

function Attack(){
     while(attacking == true){
          enemyObject.SendMessage("Damage", Damage);
          yield WaitForSeconds(attackCooldown);
     }
}

Ah, sorry about that, that’s my bad for not testing the code. I can see what the problem is with OnTriggerStay(). Astrauk’s method should eliminate that problem. The issue with my code is that AttackCoroutine() is being started every frame an AI is within range of a target. If you throw in a boolean in to check whether or not the coroutine has already been started you should be in the clear.

#pragma strict

public var enemyObject : GameObject;
public var Damage : float;
public var attackCooldown : float;

private var _isAttacking : boolean = false;
 
function OnTriggerEnter(other : Collider) {
    if (other.gameObject.tag == "DestructibleBuilding") {
        enemyObject = other.gameObject;
        _isAttacking = false;

        Attack();
        Debug.Log("The Enemy Has Attacked.");
    }
}
 
function OnTriggerStay(other : Collider) {
    if (other.gameObject == enemyObject  !_isAttacking) {
        _isAttacking = true;
        StartCoroutine(AttackCoroutine());
    }
}

function OnTriggerExit(other : Collider) {
    if (other.gameObject == enemyObject) {
        _isAttacking = false;
    }
}
 
function AttackCoroutine() {
    yield WaitForSeconds(attackCooldown);
    Attack();
}
 
function Attack() {
    enemyObject.SendMessage("Damage", Damage);
}

Astrauk’s method is a bit cleaner, so I’d suggest going with his, just wanted to give you a proper version of mine as well.

That did the trick! Thanks guys, you rock!

I think I’ll also need to set the target to null to the OnTriggerExit so that it can pick up a new target.

Anyway - thanks again, really appreciate the help!