Skip to content

Instantly share code, notes, and snippets.

@gamemachine
Last active August 22, 2018 22:00
Show Gist options
  • Select an option

  • Save gamemachine/76618453d84202cecf2ed7f2ef0c3bf8 to your computer and use it in GitHub Desktop.

Select an option

Save gamemachine/76618453d84202cecf2ed7f2ef0c3bf8 to your computer and use it in GitHub Desktop.
using Unity.Burst;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using UnityEngine;
namespace AiGame.Ecs.Systems
{
public class LosDirectSystem : JobComponentSystem
{
public struct LosRequestData
{
public ComponentDataArray<LosRequest> Requests;
public EntityArray Entities;
public readonly int Length;
}
public static LosDirectSystem Instance { get; private set; }
[Inject]
private LosRequestData Data;
[Inject]
private EndFrameBarrier EndFrameBarrier;
private NativeArray<RaycastHit> Hits;
private NativeArray<RaycastCommand> Commands;
private NativeHashMap<int, LosRequest> Responses;
private JobHandle JobHandle;
public LosRequest GetResponse(int id)
{
LosRequest response;
if (Responses.TryGetValue(id, out response))
{
Responses.Remove(id);
}
return response;
}
public void Request(LosRequest request)
{
var commandBuffer = EndFrameBarrier.CreateCommandBuffer();
commandBuffer.CreateEntity(EcsGlobals.LosRequestArchetype);
commandBuffer.SetComponent(request);
}
protected override void OnCreateManager(int capacity)
{
base.OnCreateManager(capacity);
Instance = this;
Responses = new NativeHashMap<int, LosRequest>(2048, Allocator.Persistent);
}
protected override void OnDestroyManager()
{
base.OnDestroyManager();
if (Responses.IsCreated) Responses.Dispose();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
EntityCommandBuffer buffer = EndFrameBarrier.CreateCommandBuffer();
for (int i = 0; i < Data.Length; i++)
{
LosRequest request = Data.Requests[i];
if (request.Completed == 1)
{
Responses.Remove(request.Id);
Responses.TryAdd(request.Id, request);
buffer.DestroyEntity(Data.Entities[i]);
}
}
Commands = new NativeArray<RaycastCommand>(Data.Length, Allocator.TempJob);
Hits = new NativeArray<RaycastHit>(Data.Length, Allocator.TempJob);
var startJob = new LosStartJob
{
Requests = Data.Requests,
Commands = Commands
};
var finishJob = new LosFinishJob
{
Requests = Data.Requests,
Commands = Commands,
Hits = Hits
};
var startHandle = startJob.Schedule(inputDeps);
var raycastHandle = RaycastCommand.ScheduleBatch(Commands, Hits, 1, startHandle);
var finishHandle = finishJob.Schedule(raycastHandle);
return finishHandle;
}
[BurstCompile]
struct LosStartJob : IJob
{
public NativeArray<RaycastCommand> Commands;
[ReadOnly]
public ComponentDataArray<LosRequest> Requests;
public void Execute()
{
int raycastIndex = 0;
for (int i = 0; i < Requests.Length; i++)
{
LosRequest request = Requests[i];
Vector3 start = request.Start;
Vector3 end = request.End;
float3 dir = request.End - request.Start;
float distance = Vector3.Distance(request.Start, request.End);
Commands[raycastIndex] = new RaycastCommand(request.Start, math.normalize(dir), distance, request.LayerMask, 1);
raycastIndex++;
}
}
}
[BurstCompile]
struct LosFinishJob : IJob
{
[DeallocateOnJobCompletion]
public NativeArray<RaycastCommand> Commands;
[DeallocateOnJobCompletion]
public NativeArray<RaycastHit> Hits;
public ComponentDataArray<LosRequest> Requests;
public void Execute()
{
for (int i = 0; i < Requests.Length; i++)
{
LosRequest request = Requests[i];
RaycastHit hit = Hits[i];
if (hit.point == Vector3.zero)
{
request.Result = 1;
}
else
{
request.Result = 0;
}
request.Completed = 1;
Requests[i] = request;
}
}
}
}
}
using Unity.Entities;
using Unity.Mathematics;
namespace AiGame.Ecs.Systems
{
public struct LosRequest : IComponentData
{
public int Id;
public float3 Start;
public float3 End;
public int Result;
public int LayerMask;
public int Completed;
public static LosRequest Create(int requestId, float3 start, float3 end, int layerMask)
{
LosRequest request = new LosRequest();
request.LayerMask = layerMask;
request.Id = requestId;
request.Start = start;
request.End = end;
return request;
}
}
}
// snippet of how to init archetypes
public static EntityArchetype LosRequestArchetype;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
public static void Init()
{
EntityManager entityManager = World.Active.GetOrCreateManager<EntityManager>();
LosRequestArchetype = entityManager.CreateArchetype(typeof(LosRequest));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment