- Home /
Raycast ricochet only works for a couple of Rays
I'm working on an AI script that can sense the player and shoot them using ricocheting bullets. To achieve this, I use a script that casts rays in all directions that collide with walls. Raycasting to the walls works great and I get some nice ricocheted rays, but most of them don't ricochet at all and I can't figure out why.
using UnityEngine;
public class TargetFollowing : MonoBehaviour
{
[SerializeField] private LayerMask _layerMask;
[SerializeField] private int _numberOfRays;
[SerializeField] private float _raycastDistance;
private Transform _transform;
private void Awake() {
_transform = GetComponent<Transform>();
}
private void Update() {
for (var i = -_numberOfRays / 2; i < _numberOfRays / 2; i++) {
var direction = GetRelativeDirection(new Vector3(Mathf.Sin(i), Mathf.Cos(i), 0f));
CastRay(_transform.position, direction, 3);
}
}
private Vector3 GetRelativeDirection(Vector3 originalDirection) {
return _transform.TransformDirection(originalDirection);
}
private void CastRay(Vector3 currentPosition, Vector3 rayDirection, int numberOfRicochets) {
var raycastHit = Physics2D.Raycast(currentPosition, rayDirection, _raycastDistance, _layerMask.value);
if (raycastHit.collider == null) {
Debug.DrawRay(currentPosition, rayDirection * _raycastDistance, Color.red);
return;
}
var targetPosition = rayDirection * raycastHit.distance;
Debug.DrawRay(currentPosition, targetPosition, GetRaycastColor(numberOfRicochets));
if (numberOfRicochets <= 0) {
return;
}
var ricochetDirection = Vector2.Reflect(rayDirection, raycastHit.normal);
CastRay(raycastHit.point, ricochetDirection, numberOfRicochets - 1);
}
private static Color GetRaycastColor(int ricochetNumber) {
switch (ricochetNumber) {
case 0: return Color.cyan;
case 1: return Color.green;
case 2: return Color.yellow;
case 3: return Color.magenta;
default: return Color.black;
}
}
}
The values of the serialized properties I used in the screenshots at the bottom are:
Layer Mask: only Walls
Number Of Rays: 45
Raycast Distance: 100
Playing around with the raycast distance didn't really help either.
Nothing jumps out at me on first read. My suggestion would be to go down to just 1 ray and find a case where it doesn't bounce, then step through your code and find out where it is breaking down
Answer by G_hi3 · Jun 24, 2021 at 09:24 PM
I figured out the problem in my script by displaying the normals of each raycast collision. First, every collision that didn't ricochet had two normal directions. This indicated to me, that there was a raycast from and to that exact point. Then I used ~Physics2D.RaycastAll` to find all collisions and proceeded to print out the distance of each hit for every raycast with multiple collisions. The Console was filled with exponentially more "0" than other distances. I updated my code with this at the top of my CastRay
method:
var allRaycastHits = Physics2D.RaycastAll(currentPosition, rayDirection, Mathf.Infinity, _layerMask.value);
var raycastHit = allRaycastHits.FirstOrDefault(h => h.distance > float.Epsilon);
if (raycastHit == default) {
Debug.DrawRay(currentPosition, rayDirection * Mathf.Infinity, Color.red);
return;
}
So basically, give me the first collision that isn't the point of origin and use that to display the ricochet.
Your answer
Follow this Question
Related Questions
Physics2D Raycast not detecting wall colliders 1 Answer
2D Raycast Layer Mask not working 1 Answer
Is it possible to raycast during edit mode? 1 Answer
Can't find the null reference 1 Answer