Instantiate enemies in front of a moving ship

Hi all!

I have a spaceship that is moving straight on the z axis. I have a variable that records its position on the z axis every frame. I want to instantiate objects (as enemies) in front of the ship when its position on the z axis goes up.

I tried for example to instantiate a shpere 10 meters distance in front of the ship, when the ship crosses 3 meters. Here is the script:

var speed = 1.0;
var posZ = 0.0;
var sphere : Transform;

function Update () {
	
	//move forward according to given "speed"
	transform.Translate ( 0, 0, speed * Time.deltaTime);
	
	//the position of the ship on z axis
	posZ = transform.position.z;
	
	//instantiate enemy when the ship has moved forward 3 meters
	if (posZ == 3.0) {
		
	 Instantiate (sphere, Vector3(0, 0, posZ+10), Quaternion.identity);  
	}
}

but it does not instantiate the sphere. I tried to change the the if statement into if (posZ >3.0), but then instantiates a sphere everyframe (it was expected though :!: ). Does anyone has a clue what I’m doing wrong??

Here’s a solution that instantiates an enemy at a certain offset from the ship for every x metres the ship moves in the Z direction.

var speed : float = 1.0;

var enemyAppearsEvery : float = 3.0;
var nextEnemyZ : float = 3.0;

var enemyOffset : Vector3 = Vector3(0, 0, 10);
var sphere : Transform;

function Update () { 
    
	//move forward according to given "speed" 
	transform.Translate ( 0, 0, speed * Time.deltaTime);
    
	//instantiate enemy when the ship has moved forward "enemyAppearsEvery" meters 
	if (transform.position.z > nextEnemyZ) {
		Instantiate (sphere, transform.position + enemyOffset, Quaternion.identity);
		nextEnemyZ += enemyAppearsEvery;
	} 
}

The problem with == is that the position is generally never exactly 3.0 - it will go from 2.9886675 to 3.0235412.

Yes, I forgot to mention this. Comparing floating point values should almost never be done using ==, because as StarManta pointed out, it’s usually incredibly unlikely that two floats will have the same value (unless you’ve set them both explicitly).

Thanx! It seems to work for what I need at the moment.

However, still cannot understand why the if (posZ ==3.0) I had in my script, doesn’t work.

Because it will be a very rare case that your position is EXACTLY 3.0. It might be 3.0000001, or even 2.999999, neither of which will equate to 3.0.

It’s generally a bad idea to ever use == with floating point numbers. However, you can use Mathf.Approximately instead.

–Eric

Ohhhh! Of course…

How could I use that? Mathf.Approximately is for checking if two floating numbers are equal. I tried this:

if (Mathf.Approximately (posZ, 3.0)) {
		
	 Instantiate (sphere, Vector3(0, 0, posZ+10), Quaternion.identity);  
	}

but it didn’t work.

Basically, you don’t want to be checking whether floats are equal in this case, even using Mathf.Approximately(). That function is still only useful when numbers are nearly the same. In your case, the numbers will almost never be the same or even close because the frame rate varies and moves you a different amount every frame.

Think of it this way: using == or Mathf.Approximately() is like waiting for someone to step on a specific crack in the sidewalk. Most of the time, people will step right over it. What you actually care about is whether they’ve passed that point, so you should use an inequality.

By that I assume you mean that you get no script errors, it’s just that Instantiate is never called? I’m not sure how close two numbers have to be to get a true result returned from Approximately and my immediate guess is that your posz goes from being below the threshold to above it, never being quite approximately equal to each other (as the Approximately function sees things). Perhaps you can use some Debug.Log() statements to output the posz values to see what they look like?

Alternatively, why not go with posz > someNumber, and have someNumber increase as the game progresses:

var speed = 1.0;
var posZ = 0.0;
var triggerZ = 3.0;
var sphere : Transform;

function Update () {
   
   //move forward according to given "speed"
   transform.Translate ( 0, 0, speed * Time.deltaTime);
   
   //the position of the ship on z axis
   posZ = transform.position.z;
   
   //instantiate enemy when the ship has moved forward 3 meters
   if (posZ > triggerZ) {
      
    Instantiate (sphere, Vector3(0, 0, posZ+10), Quaternion.identity); 
    triggerZ += triggerZ;

   }
}

That way you don’t Instantiate every frame after passing z = 3.0, instead it will call Instantiate when you pass 3.0, then again at 6.0, then 9.0, and so on.

Sorry, that was more of a general comment about == and not intended to apply here. In this case, since you’re dealing with Time.deltaTime and who knows what the framerate could be, it’s likely not even Mathf.Approximately equal. :slight_smile:

–Eric

I see what is going on. Thanx everyone for the ==, Mathf.Aproximately lesson!!

HiggyB, thanx for the alternative script, though I think it does the same with Muriac’s script. But it’s always good to see the same idea scripted in a different way.

I was thinking that maybe I should place invisible walls across the level and when the ship triggers them instantiate the enemies. Do you think that it would be a good idea? If yes, how can I be sure that those walls won’t be triggered by anything else (missiles, enemies) but the ship???

Doh, I’ll have to learn to read better before posting. :stuck_out_tongue: FWIW, I like Muriac’s solution better anyway. Heh.

As to your new question about triggers, you’d just have to check what body is intersecting the trigger and only respond if it’s the player’s ship (or whatever other bodies you want to trigger the instantiation - if there are any).

So if I have a script like that attached to a wall:

function OnTriggerEnter (other : Collider) {

if (ship is triggering the wall) {

Instantiate (enemies, where I want);
}
}

how can I specify the if statement, what would it be inside the parenthesis?

EDIT: Is this correct?? if (collision.gameObject.name == “spaceship”) ??

My quick forum code scan says you’re on the right track there.

Alright then!! I’m going to try that path then. Maybe it will take more time than the first idea but I think that the scripts and the enemies will be more organized if I want to track and change something later in the development.

Once again, thanx everyone!!!