- Home /
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.
Seriously, I need help with this. I know the solution is probably something simple, but I rarely use raycasting.
in my code maybe need to replace transform.down with just vector3.down and use Debug.drawRay for see what happens with your cast
debug.drawray(transform.position, transform.down, color.red, 1);
if (Physics.Raycast (transform.position, transform.down, hit) )
{
if(hit.transform.compareTag("Enemy")) //dont remember mark enemy prefab with tag Enemy
{
//shoot
}
}
Now my code looks like this:
#pragma strict
var enemyShot : Transform;
var shotTime = 1000;
var timeToShot = 0;
var castDistance : float;
var hit : RaycastHit2D;
function Start () {
}
function Update () {
timeToShot ++;
if (timeToShot == shotTime)
{
Debug.DrawRay(transform.position, Vector3.down, Color.red, 1);
if (Physics.Raycast (transform.position, transform.rotation, hit))
{
if (hit.transform.compareTag("Enemy"))
{
Instantiate(enemyShot, transform.position, transform.rotation);
Debug.Log("shoot");
}
}
timeToShot = 0;
}
}
And triggers 2 errors:
Assets/Scripts/Enemy1Control.js(24,35): BCE0019: 'compareTag' is not a member of 'UnityEngine.Transform'.
Assets/Scripts/Enemy1Control.js(22,29): BCE0023: No appropriate version of 'UnityEngine.Physics.Raycast' for the argument list '(UnityEngine.Vector3, UnityEngine.Quaternion, UnityEngine.RaycastHit2D)' was found.
Any advice from anyone? I'm open to suggestions.
Try this
if (Physics.Raycast (transform.position, Vector3.down, out hit))
{
if (hit.transform.tag != "Enemy") //only shoot if no enemy is seen below
{
Instantiate(enemyShot, transform.position, transform.rotation);
Debug.Log("shoot");
}
}
Seriously, I need help. At the moment, none of my Debug.Log lines are triggering, and my enemies are not shooting at all, whether or not there is an enemy in its way. $$anonymous$$y code looks like this:
#pragma strict
var enemyShot : Transform;
var shotTime = 1000;
var timeToShot = 0;
var castDistance : float;
function Start () {
}
function Update () {
var layer$$anonymous$$ask = 1 << 8;
layer$$anonymous$$ask = ~layer$$anonymous$$ask;
var hit : RaycastHit;
timeToShot ++;
if (timeToShot == shotTime)
{
if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.down), hit) )
{
if (hit.transform.tag != "Enemy")
{
Instantiate(enemyShot, transform.position, transform.rotation);
Debug.Log("shoot");
}
}
timeToShot = 0;
}
}
This gives me no errors, but does not perform in the intended fashion, in that it keeps all enemies from shooting, ins$$anonymous$$d of just those with enemies blocking them. Please help.
It will shoot when time to shoot == 1000? So you probably have to wait like 17 seconds for it to shoot if your game is running at 60fps in Update
Answer by Dakwamine · Nov 28, 2016 at 04:44 PM
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.
Unfortunately, I'm still having a problem. The enemies are firing, but they are killing the enemies beneath them. I'm currently using the second script you posted and I have tried the first one, with the same results. Looks like this has come full circle...
The log says "It's time to shoot" and "There is no freindly in my sight! Fire! For the empire!"
Here is my exact code:
#pragma strict
var enemyShot : Transform;
var shotTime = 1000;
var timeToShot = 0;
public var enemyLayer$$anonymous$$ask : Layer$$anonymous$$ask;
var castDistance : float;
function Start () {
}
function Update () {
var hit : RaycastHit;
timeToShot ++;
if (timeToShot == shotTime)
{
Debug.Log("It's time to shoot");
if (Physics.Raycast (transform.position, transform.TransformDirection (Vector3.down), hit, $$anonymous$$athf.Infinity, enemyLayer$$anonymous$$ask) ){
Debug.Log("There is a freindly in my sight. I'll shoot later");
} else {
Debug.Log("There is no freindly in my sight! Fire! For the empire!");
Instantiate(enemyShot, transform.position, transform.rotation);
}
timeToShot = 0;
}
}
@roman_sedition Yes I have, by inserting this code:
Debug.DrawRay(transform.position, Vector3.down, Color.red, 1);
immediately above the line where the ray is cast
Then maybe there's something wrong outside of the scope of what you are showing us, enemies on wrong layers, enemies without tags, raycasting on wrong layers, enemies without colliders, triggers on colliders are set etc. If you are following somebody else's tutorial for making a space invader's game, maybe there was an error you made in reproducing the code. If you aren't, then probably look at some tutorials of similar games and find out why yours doesn't work out.
Then could you update your raycast for peace of $$anonymous$$d?
if (Physics.Raycast (transform.position, Vector3.down, hit, $$anonymous$$athf.Infinity, enemyLayer$$anonymous$$ask) )