Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Created July 16, 2019 07:18
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save jeffvella/fa5b7e4eaf3fa4b42e0b77ad26ed3535 to your computer and use it in GitHub Desktop.
Save jeffvella/fa5b7e4eaf3fa4b42e0b77ad26ed3535 to your computer and use it in GitHub Desktop.
Unity Physics in ECS Raycasting
using BovineLabs.Entities.Systems;
using Unity.Burst;
using Unity.Entities;
using Unity.Jobs;
using Unity.Collections;
using Unity.Physics;
using Unity.Physics.Systems;
using UnityEngine;
[UpdateAfter(typeof(BuildPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
public class RaycastUnderPointerSystem : JobComponentSystem
{
private BuildPhysicsWorld _buildPhysicsWorldSystem;
private EndFramePhysicsSystem _endFramePhysicsSystem;
private NativeQueue<UnderPointerEvent> _eventQueue;
protected override void OnStartRunning()
{
_buildPhysicsWorldSystem = World.GetExistingSystem<BuildPhysicsWorld>();
_endFramePhysicsSystem = World.GetOrCreateSystem<EndFramePhysicsSystem>();
_eventQueue = World.GetExistingSystem<EntityEventSystem>().GetOrCreateEventQueue<UnderPointerEvent>();
}
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
if (Input.GetMouseButton(0))
{
inputDeps = JobHandle.CombineDependencies(inputDeps, _buildPhysicsWorldSystem.FinalJobHandle);
var screenRay = Camera.main.ScreenPointToRay(Input.mousePosition);
var selectionSettings = GetSingleton<SelectionSettings>();
var handle = new FindClosestInteractable
{
Input = new RaycastInput
{
Start = screenRay.origin,
End = screenRay.GetPoint(100),
Filter = new CollisionFilter
{
BelongsTo = selectionSettings.SelectionCategory,
CollidesWith = ~0u,
GroupIndex = 0
}
},
EventQueue = _eventQueue.ToConcurrent(),
World = _buildPhysicsWorldSystem.PhysicsWorld
}.Schedule(inputDeps);
_endFramePhysicsSystem.HandlesToWaitFor.Add(handle);
return handle;
}
return inputDeps;
}
[BurstCompile]
public struct FindClosestInteractable : IJob
{
[ReadOnly] public PhysicsWorld World;
[ReadOnly] public RaycastInput Input;
public NativeQueue<UnderPointerEvent>.Concurrent EventQueue;
public unsafe void Execute()
{
if (World.CollisionWorld.CastRay(Input, out var hit))
{
Entity entity = World.Bodies[hit.RigidBodyIndex].Entity;
EventQueue.Enqueue(new UnderPointerEvent
{
Entity = entity,
Hit = hit,
});
}
}
}
}
@Thefolle
Copy link

Thefolle commented Jul 29, 2021

Actually you need to add this tag at class level:

[UpdateInGroup(typeof(FixedStepSimulationSystemGroup))]

Otherwise the other tags (UpdateBefore and UpdateAfter) are ignored. In other words, order between systems make sense only if the interested systems belong to the same group. You can check the pertinent group through the entity debugger. 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment