Raycasting completely cancelling instantiation.

In a retro space-invaders styled game, I am attempting to use raycasting to stop the enemies on the upper rows from killing the enemies beneath them. However, instead of doing this, my script stops the enemies from firing projectiles at all. It looks something like this:

#pragma strict
var enemyShot : Transform;

var nextRowLayer : int;

var layerMask = 1 << nextRowLayer;

var shotTime = 1000;
var timeToShot = 0;

var castDistance : float;

var hit : RaycastHit;

function Start () {

}

function Update () {

timeToShot ++;

if (timeToShot == shotTime)
	{
	if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.down), hit, Mathf.Infinity, layerMask))
		{
		Instantiate(enemyShot, transform.position, transform.rotation);
		Debug.Log("shoot");
		}
		timeToShot = 0;
	} 
}

I have tried converting it to Physics2D, but it gives me nothing but a barrage of errors. Feel free to ask for any additional information. Please include code samples in your answers if possible.

Your logic is not taking into account every possibility.

if (timeToShot == shotTime)
{
	Debug.Log("It's time to shoot!");
	if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.down), hit) ) 
	{
		Debug.Log("I have seen something in front of me...");
		if (hit.transform.tag != "Enemy")
		{
			Debug.Log("It was not an Enemy! FIRE!!!!!");
			Instantiate(enemyShot, transform.position, transform.rotation);
		}
		else
		{
			Debug.Log("Oh it's just a friendly Enemy.");
		}
	}
	else
	{
		Debug.Log("Nothing ahead! FIRE!!!!! For the Empire!");
		Instantiate(enemyShot, transform.position, transform.rotation);
	}
	timeToShot = 0;
}

If Enemy never finds something from the raycast, you may want to verify the ray info such as the layers, ray directions, colliders… I would advise you to use a layer mask as a public inspector value:

public var enemyLayerMask : LayerMask;

… and set the value in the inspector by checking “Enemy” only and uncheck everything else. And then, you can use this:

if (timeToShot == shotTime)
{
	Debug.Log("It's time to shoot!");
	if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.down), hit, Mathf.Infinity, enemyLayerMask) )
	{
		Debug.Log("There is a friendly Enemy somewhere in my sight. Let's shoot later.");
	}
	else
	{
		Debug.Log("There is no friendly Enemy! FIRE!!!!! For the Empire!");
		Instantiate(enemyShot, transform.position, transform.rotation);
	}
	timeToShot = 0;
}

The second script is lighter from a performance perspective. Only Enemy objects are tested.

But it differs from the first script’s logic: in the first, if something with a collider passes between two enemies, the Enemy above will still fire because, as every object is checked in the Raycast, the hit will tell “this is not an Enemy”.

In the second script, only Enemies which are at the lowest row of their column will fire. And I think this is what you expected as a behaviour.