Skip to main content

IRaycastBehaviorJobWrapper

Ray behaviors are implementations of IRaycastBehaviorJobWrapper. The BaseSteeringSystem schedules them after their corresponding ray query is done, passing in its results. There are three interfaces relevant in creating a ray behavior. The most important one is a custom job IRaycastBehaviorJob<C, A1, A2, R> which significantly simplifies creating the behaviors.

Implementing IRaycastBehaviorJobWrapper

Below is the implementation of the DebugRaysJobWrapper. It can be easily used as a template to create your own behavior. The Schedule method receives information about the entities as well as the result of its group's ray query inside RaycastBehaviorParams. It should create an object of the type specified in [OutData] and assign it to out results. The behavior should write one VelocityResult per entity into VelocityResults. Here the DebugRaysJob is resposible for that.

DebugRayJobWrapper.cs
[JobWrapper(typeof(DebugRayComponent))]
[OutData(typeof(VelocityResults))]
public class DebugRayJobWrapper : IRaycastBehaviorJobWrapper
{
public JobHandle Schedule(
SystemBase systemBase,
in RaycastBehaviorParams rayBehaviorParams,
out IDelayedDisposable results,
in JobHandle dependency)
{
results = new VelocityResults(rayBehaviorParams.MainBaseParams.EntityCount);
var outDependency = new DebugRayJob().Schedule<
DebugRayJob,
DebugRayComponent,
NoneAccumulator,
NoneAccumulator,
VelocityResult>(systemBase, rayBehaviorParams, (VelocityResults)results, 1, dependency);
return outDependency;
}
}

Attributes

This job wrapper uses two attributes. First declares what type of object the behavior returns. Second declares which components are expected on the entity. The types from the attributes are used in the editor of the SteeringSystemAsset.

The correct way to match the type arguments with generic parameters to IRaycastBehaviorJob<C, A1, A2, R> is the following:

  • [JobWrapper(typeof(C))]
  • [OutData(typeof(R))]

Implementing IRaycastBehaviorJob<C, A1, A2, R>

IRaycastBehaviorJob<C, A1, A2, R> simplifies creation of new ray behaviors. For each entity, OnHit is called for each ray of the query which hit and OnMiss for each ray missed. Information about the entity and the ray are passed in. Both functions also receive an accumulator. After influence of all rays is accumulated into the accumulators, they are passed with information about the entity into the Finalize method. That then returns a single result of type R per entity. Internally the result is then written into the results.

Generic Parameters

  • C - Type of component expected on the main entities - should match the argument of [JobWrapper].
  • A1 - Type of accumulator passed into the OnHit method, implements IAccumulator.
  • A2 - Type of accumulator passed into the OnMiss method, implements IAccumulator.
  • R - Type of result returned from the behavior - should match the argument of [OutData].
DebugRayJobWrapper.cs
[BurstCompile]
struct DebugRayJob : IRaycastBehaviorJob<DebugRayComponent, NoneAccumulator, NoneAccumulator, VelocityResult>
{
public void OnHit(
in EntityInformation<DebugRayComponent> entity,
in RayData rayData,
in RaycastHit hit,
ref NoneAccumulator hitA)
{
// Accumulate something from rays that hit the environment into accumulator
DebugDraw.DrawArrow(entity.Position, raycastHit.Position, Color.red);
}

public void OnMiss(
in EntityInformation<DebugRayComponent> entity,
in RayData rayData,
ref NoneAccumulator missA)
{
// Accumulate something from rays that missed the environment into accumulator
DebugDraw.DrawArrow(
entity.Position,
entity.Position + rayData.Direction * rayData.MaxDistance,
Color.green);
}

public VelocityResult Finalize(
in EntityInformation<DebugRayComponent> entity,
in NoneAccumulator hitA,
in NoneAccumulator missA)
{
// Based on the accumulators, return a VelocityResult which tells which way to go
return default;
}
}
tip

You can just copy and paste this, then change all occurences of DebugRay to MyBehaviorName to create a new behavior quickly. The only three things to implement are the OnHit, OnMiss and Finalize methods. See other default behaviors to understand more complex examples.