- Home /
Problem is not reproducible or outdated
How do I get Raycasts to cast symmetrically?
I have an even distribution of points on the surface of a sphere and a list of Vectors for raycasting from the center, however when I try doing all of the casts the directions seem to be in a 270 degree cone in the direction the original (now stationary) object was moving that I am performing the casts from. Does anyone know why this warp is happening and how to avoid it?
Vector3 explosionPosition = transform.position;
List<Vector3> points = new List<Vector3>(BlockIndex.SphereSurfacePoints(radius + 2));
float rayDamage = damage * 0.0027777777777778f;
float thisRay = rayDamage;
RaycastHit[] hits;
float fade = 1 / radius * rayDamage;
float forcefade = 1 / radius * explosionForce;
SortHits sorter = new SortHits();
rigidbody.isKinematic = true;
collider.enabled = false;
int i = 0;
for (int x = 0; x < points.Count; x++)
{
// reset vars befor raycast
thisRay = rayDamage;
i = 0;
//cast a ray for the current point
hits = Physics.RaycastAll(explosionPosition, points[x], radius);
if (hits != null && hits.Length > 0)
{
foreach (RaycastHit hit in hits)
{
if (thisRay > 0)
{
DestructableObject dObject = hit.collider.GetComponent<DestructableObject>();
if (dObject != null)
{
float currdamage = dObject._currentHP;
dObject.ApplyRayDamage(thisRay);
thisRay -= currdamage;
}
if (hit.collider.rigidbody)
hit.collider.rigidbody.AddExplosionForce(
forcefade,
explosionPosition,
radius,
0);
}
if (thisRay > 0)
thisRay -= fade;
else
i = hits.Length;
}
}
}
return;
SphereSurfacePoints is the precomputed list of Vector3 coordinates. To debug I tried instantiating cube primitives at each of the points and it makes a perfect sphere.
This is the function that returns the array:
public static Vector3[] UniformPointsOnSphere(float numberOfPoints)
{
List<Vector3> points = new List<Vector3>();
float i = Mathf.PI * (3 - Mathf.Sqrt(5));
float offset = 2 / numberOfPoints;
float halfOffset = 0.5f * offset;
float y = 0;
float r = 0;
float phi = 0;
int currPoint = 0;
for (; currPoint < numberOfPoints; currPoint++)
{
y = currPoint * offset - 1 + halfOffset;
r = Mathf.Sqrt(1 - y * y);
phi = currPoint * i;
Vector3 point = new Vector3(Mathf.Cos(phi) * r, y, Mathf.Sin(phi) * r);
if (!points.Contains(point)) points.Add(point);
}
return points.ToArray();
}
Posting your code might help solve this problem. $$anonymous$$y first guess is that you are not reconstructing the rays at each frame, so that the origin of the rays are remaining fixed.
Edited and added the code. It still needs to have a little more optimizing done to speed it up of course but it's as legible as I can get it. Ignore variable "i" it was used for edited out debugging messages.
In case it matters this is being used to calculate explosive force passing through several destructable objects and dissipating with distance traveled and damage absorbed. The world is voxel based and the explosion radius is never greater than 32. Collider boxes are generated for each voxel in range so there is something for the rays to hit. There are about 4000 rays and it executes in about 2 frames inside a coroutine.
Answer by robertbu · Mar 05, 2013 at 09:29 PM
I don't see enough of your code to be sure, but the most likely issue is how you are passing your 'points[x]' to the RaycastAll(). The second Vector3 parameter is a direction and is relative to the start point. You write, "SphereSurfacePoints is the precomputed list of Vector3 coordinates," which leads me to believe they are world space coordinates.
If so you may want this instead:
hits = Physics.RaycastAll(explosionPosition, points[x] - explosionPosition, radius);
They are a collection of of normalized points centred at 0,0,0 The only thing omitted was the name of the void method, which was a euphemism for ejaculate. Some of the na$$anonymous$$g in my code includes some coarse humour since I'm a solo programmer and generally nobody else sees the code. ;)
I don't see anything obvious. I know you said you checked the points by creating game objects, but did you check it right here at the Raycast? If you haven't, just before the RaycastAll() create primitives at explosionPosition+points[x]*radius just to be sure.
And how are seeing that there is a "270 degree cone in the direction the original?" A Debug.DrawRay() statement or something else.
I see nothing wrong in the code. Here is a test to figure out if the Raycasting is a problem at all. Box the explosion point in six planes. $$anonymous$$ake sure the normals face inward. If you have access and the knowledge, creating a sphere with in-facing normals ins$$anonymous$$d of six planes will give a somewhat better result. Then run the raycasting code and place an object at the hit point of each raycast. This will tell definitively whether the issue is with the raycast or with something else. And if it is a problem, it will give a visual to think about. Oh, I'd do the test on a position away from the origin.
I was curious, so I took your UniformPointsOnSphere() and grabbed the guts of your raycasting code. I had a sphere with a flat bottom with inward facing normals from another project. I did the experiment I mention above and here is the result:
It has been so long since I working on this question that I don't remember all the specifics. But I used all the guts from your code, and the results looked fine. Your collection being relative to vector3.zero is what you want, since each will define a direction relative the position you specify. I had a hard time co$$anonymous$$g up with a solution since I could not reproduce the issue.