is there a way in the current Unity Version 2018.1 or in any further version to process raycasthit-Information in a job? I am particularly interested in an approach to handle the colors of the objects, which where hit by a raycast. In the main thread I would do something like this:
Color color = hit.collider.GetComponent<Renderer>().material.color;
Is there an approach to get the same information in a job?
You can try raycast command buffer. It does have some limitations currently, you can’t check layerMask on a job thread right now since some of the results still access GameObject, and those properties are not thread safe.
Thanks a lot for your reply. I already use the raycast command buffer. In a first step I use the RaycastCommand and do many Raycasts in parallel. In the next step I want to use an IJobParallelFor job to do some calculations (in parallel) with the obtained result buffer. For these calculations I need information about the color of the objects.
The raycast command buffer is very performant even though you’ll need to loop over the hits outside of the job. Raycasting a terrain of 512 x 512 (260,000 raycasts) took less than 200ms.
In my case the raycast command is extremely fast and not the problem. The following calculations are the bottleneck. In this step I have to process over 1.000.000 raycast-hits. Becaus of this large amount I want to use a job and do this in parallel.
Any part of the RaycastHit that interacts with the .collider will cause an error. So you can pretty much only check hit.point, hit.normal, and such things. You can look at the source to get a clear overview of what will and will not work.
The only way (as far as I can tell) to even check if the raycast hit anything is to check if .point != default(Vector3), which seems… hacky. I’m assuming that there will be some solution for batched raycasting that is more useful at one point in the future.
Anyway, what I think you want to do is to make a collider-to-color cache beforehand. Then your main thread lookups will be fast-ish.
If that’s not good enough, you could make a NativeDictionary from int to Color, where the int is the instanceID of all the colliders. Then you have a job that grabs the m_Collider from the raycasthits through reflection, and looks that up in the dictionary. I have no idea if that’ll be fast or even work - but it’d be worth looking into.
reflection uses reference types. therefore it cannot be used in a job.
you can use the NativeSlice API to convert the results to a struct with the same field layout and expose the instance id that way:
// NativeArray<RaycastHit> hits = ...;
var yourHits = hits.Slice().SliceConvert<YourRaycastHit>(); // YourRaycastHit must have the exact same fields as RaycastHit, but m_collider can be public (or you can add a property .IsValid => m_collider != 0)
What I do for this is create a grid using a 1d array. use it as a granular spatial map of types. Then I can fairly cheaply take the hit position map it to a cell.
public static int GetCellIndex(int x, int y)
{
return MapWidth * x + y;
}
Now stuff that can be hit I map to a NativeMultiHashMap using the above every few frames. Whatever it takes depends on how fast stuff moves in your world. Keys map to cell indexes. Looping over entries to find the one with the closest position is fairly cheap.
However I am already starting with a design of separating logical entities from monobehaviours. So I have an existing layer mapping things like GameObject instance id’s to my own unique entity (not ECS entity) id’s.
It’s more work then I’d like to be doing, but don’t really have much choice then to create some type of extra layer given the api limitations.
You could also use a more traditional spatial hashing approach, those are just inherently less granular, plus in my case the areas are small enough to work with the grid approach. Large spaces it becomes memory prohibitive and a sparse spatial map works better.