please help, I am trying to use raycasts to shoot enemies, I have used them many times before and I don’t understand what is causing my problem. Bullets will randomly not connect with enemies, so sometimes I can get through all 6 shots with all of them connecting just fine, and sometimes I cant even get through 3. The enemy is tagged, layers are all correctly set up, and despite all that, it still randomly doesn’t register. It doesn’t go through the enemy, and I’m not missing, and NONE of the debugs I set up are firing. please help, this is the section of the code that deals with shooting, I can post the full script if needed.
if (Input.GetButtonDown("Fire1"))
{
//Raycast 1, + debug (RayOne shoots forward to detect the first collision, RayTwo gets used for detecting enemies not through walls)
RaycastHit2D RayOne = Physics2D.Raycast(transform.position, transform.up, RayLength, ObstacleLayer);
Debug.DrawRay(transform.position, transform.up * RayLength, Color.red);
if (RayOne == true && Bullets[0])
{
//if ray 1 successfully collided with an obstacle, shoot another ray + debug to the position where it was struck. only preform if it was successful to save on performance
RaycastHit2D RayTwo = Physics2D.Raycast(transform.position, transform.up, RayOne.distance, ObstacleLayer);
Debug.DrawRay(transform.position, transform.up * RayOne.distance, Color.blue);
//muzzle smoke particle effect
Instantiate(MuzzleSmoke, MuzzleFlash.transform.position, transform.rotation);
//Set Timer for muzzleflash
FlashTimer = .05f;
if (RayTwo == true)
{
if (RayTwo.collider.tag == "Enemy")
{
//get enemy health on raycast, subtract 10 from health
var HealthComponent = RayTwo.collider.GetComponent<EnemyHealth>();
if (HealthComponent != null)
{
Debug.Log("HitEnemy");
//turn the 2D raycast normal into a 3D vector for the particle angle
Vector3 hitNormal3D = new Vector3(RayTwo.normal.x, RayTwo.normal.y, 0);
Quaternion RayTwoHitAngle = Quaternion.LookRotation(Vector3.forward, hitNormal3D);
HealthComponent.EnemyHealthValue -= 10;
//instantiate particles
Instantiate(BloodSquirt, RayTwo.point, RayTwoHitAngle);
}
else if (HealthComponent == null)
{
Debug.Log("failed to grab component");
}
}
else
{
//make the raycast normal into a quaternion by making it 3d and then using lookrotation idk man
Vector3 hitNormal3D = new Vector3(RayTwo.normal.x, RayTwo.normal.y, 0);
Quaternion RayTwoHitAngle = Quaternion.LookRotation(Vector3.forward, hitNormal3D);
Instantiate(SparksParticles, RayTwo.point, RayTwoHitAngle);
Debug.Log("miss");
}
}
}
//rotate the chamber in the revolver
RotateBullets();
}
Well fix that first because that means your code ain’t running… or your console buttons are turned off.
Make sure your log console selector buttons are enabled. See this graphic:
Sounds like you wrote a bug… and that means… time to start debugging!
By debugging you can find out exactly what your program is doing so you can fix it.
Use the above techniques to get the information you need in order to reason about what the problem is.
You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.
Once you understand what the problem is, you may begin to reason about a solution to the problem.
Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.
thanks for the reply, the code does run, and the debugs will fire, what I mean is that whenever one of the shots decides to not register properly, then none of the debugs will fire. If I miss a shot, or the shot registers properly then it will fire a debug, which confuses me even more because I’m pretty sure that at least one of my debugs should be firing when it doesn’t register. I’m just trying to figure out where the code is going when it doesn’t register the shot properly.
I kinda agree with @Kurt-Dekker on the debug side, try adding specific debugs, I tried replicating it but i couldn’t set it up properly. I can think of two things (IF layers and colliders are correct).
The bullet logic: I think this might be the issue, since you are running the raycast code IF both a hit is detected AND Bullets[0] is true. It might be that if you either shoot slow or fast, one logic works and the other dont, because if your “chamber” rotates or you’re “spending” bullets, can It be possible that sometimes no bullets is loaded (Bullets[0] is false) even tho you expect it to shoot. If this is true, none of the debug will also trigger.
I would add a debug before that if statement and see what it is happening when you try to shoot (fast, slow, etc).
Thats a good idea, I will be gone over the weekend but I will try that out once i’m back, and as for the double raycasts, I use one which shoots forward a set distance, and the second one only shoots up to the first collision of that raycast. The reason I did this was to prevent being able to shoot through walls, but that might be redundant if it only checks the first collision anyway. One thing I will also try now that im thinking about it is slightly extending the distance of the second raycast because it is maybe possible that on certain frames it just isnt colliding with the enemy since it just shoots to the exact distance where the collision was, but I dont think this is the case since it should set off the “miss” debug if it does that.
In addition to the above suggestions, it’s a red flag to me that your mask is called ObstacleLayer. Sometimes people mistakenly pass layers into physics queries instead of a mask. Make sure you’re using a LayerMask, or are creating a bitmask from the layer index.
It’s also noteworthy that you should use CompareTag instead of comparing tags via equality. CompareTag checks whether the tag exists, and also avoids an unnecessary allocation.
It’s also generally a good idea to draw the ray from start to hit.point to make sure it’s doing what you expect in the hit case.
One thing to be very careful of is to ensure you’re not passing in Vector3 where Vector2 is expected. 2D physics uses Vector2 in all case. Unity will just drop the Z which might seem helpful but it’s not helpul if you’re expecting “transform.up” to be the same as Vector2.up which it likely won’t be. If you rotate in anything other than the Z axis, you’ll get a 3D rotated vector and when you pass it into anything that wants a Vector2, the Z will be removed.
Unless you actually need “transform.up”, I’d suggest using “Vector2.up”. Of course, this may be intentionally and not a problem in your case but be aware of it.
I don’t understand why you perform a raycast to detect an obstacle then perform the exact same raycast again but only to where the first one hit. That’s completely redundant. Just draw to the point you hit:
The above looks like you should invest in learning how to attach the debugger, set a breakpoint and single step through the code to follow your logic and look at your results. Whilst instrumenting your code with lots of Debug.Log calls, ultimately they don’t provide enough information without adding lots of them and they don’t easily show the control flow.
I figured it out now, the double raycast was causing the issue, I thought it was required because the first raycast would go through obstacles, but for some reason I didn’t realize that it just uses the first collision anyway so it was completely redundant. thanks for your resonses