Skip to main content

INeighborBehaviorJobWrapper

Neighbor behaviors are implementations of INeighborBehaviorJobWrapper. The BaseSteeringSystem schedules them after their corresponding neighbor query is done, passing in its results. There are three interfaces relevant in creating a neighbor behavior. The most important one is a custom job INeighborBehaviorJob<C1, C2, A, R>, which significantly simplifies creating the behaviors.

Implementing INeighborBehaviorJobWrapper

Below is the implementation of the DebugNeighborsJobWrapper. It can be easily used as a template to create your own behavior. The Schedule method receives information about the entities as well as it's neighbors inside NeighborBehaviorParams. It should allocate 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 DebugNeighborsJob is resposible for that.

DebugNeighborsJobWrapper.cs
[JobWrapper(typeof(DebugableComponent), typeof(SteeringEntityTagComponent))]
[OutData(typeof(VelocityResults))]
class DebugNeighborsJobWrapper : INeighborBehaviorJobWrapper
{
public JobHandle Schedule(
SystemBase systemBase,
in NeighborBehaviorParams neighborBehaviorParams,
out IDelayedDisposable results,
in JobHandle dependency)
{
results = new VelocityResults(neighborBehaviorParams.NeighborQueryParams.MainBaseParams.EntityCount);
return new DebugNeighborsJob().Schedule<DebugNeighborsJob, DebugableComponent, SteeringEntityTagComponent, NoneAccumulator, VelocityResult>(
systemBase,
neighborBehaviorParams,
(VelocityResults)results,
1,
dependency);
}
}

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 and its neighbor. 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 INeighborBehaviorJob<C1, C2, A, R> is the following:

  • [JobWrapper(typeof(C1), typeof(C2))]
  • [OutData(typeof(R))]

Implementing INeighborBehaviorJob<C1, C2, A, R>

INeighborBehaviorJob<C1, C2, A, R> simplifies creation of new neighbor behaviors. For each entity, the Execute is called up to MaxNumNeighbors times, once for each neighbor. Information about the entity and it's neighbor are passed in the behaviorData parameter. It has one component from both of the entities, depending on the generics. The Execute method also receives reference to an accumulator. After influence of all neighbors is accumulated into the accumulator, it is 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

  • C1 - Type of component on the main entities implements INeighborBaseBehavior.
  • C2 - Type of component on the neighbors.
  • A - Type of accumulator passed into the Exectute method.
  • R - Type of result returned from the behavior.
DebugNeighborsJobWrapper.cs
[BurstCompile]
struct DebugNeighborsJob : INeighborBehaviorJob<
DebugNeighborsComponent,
SteeringEntityTagComponent,
NoneAccumulator,
VelocityResult>
{
public void Execute(
in NeighborBehaviorData<DebugNeighborsComponent, SteeringEntityTagComponent> pair,
ref NoneAccumulator accumulator)
{
// Accumulate something about the neighbors into the accumulator
Debug.DrawLine(pair.Entity.Position, pair.OtherEntity.Position);
}

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

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