using Unity.Entities; using Unity.Mathematics; namespace TinyPhysics.Systems { /// /// Detect when an object is tapped and update its Tappable component /// A tap is defined as a Down/Up gesture within a certain time and distance /// public class PointerTapSystem : PointerSystemBase { const float tapSqrDistanceThreshold = 100f; const float tapTimeThreshold = 0.5f; protected override void OnInputDown(int pointerId, float2 inputPos) { // Get entity under pointer var pointerRaycastHit = GetPointerRaycastHit(inputPos, m_CollisionFilter); var pointerEntity = pointerRaycastHit.Entity; // Only target entities with Tappable component if (pointerEntity != Entity.Null && HasComponent(pointerEntity)) { // Set tap data on entity that was pressed var tappable = new Tappable { PointerId = pointerId, TimePressed = Time.ElapsedTime, IsPressed = true }; SetComponent(pointerEntity, tappable); } } protected override void OnInputMove(int pointerId, float2 inputPos, float2 inputDelta) { Entities.ForEach((ref Tappable tappable) => { if (tappable.PointerId == pointerId && tappable.IsPressed) { // Update total distance that pointer moved tappable.PointerMoveSqrDistance += math.dot(inputDelta, inputDelta); } }).Run(); } protected override void OnInputUp(int pointerId, float2 inputPos) { Entities.ForEach((ref Tappable tappable) => { if (tappable.PointerId == pointerId && tappable.IsPressed) { // Consider a tap only if pointer didn't move much and duration was short var isWithinTimeThreshold = Time.ElapsedTime - tappable.TimePressed < tapTimeThreshold; var isWithinDistanceThreshold = tappable.PointerMoveSqrDistance < tapSqrDistanceThreshold; tappable.IsTapped = isWithinTimeThreshold && isWithinDistanceThreshold; tappable.IsPressed = false; } }).WithoutBurst().Run(); } protected override void OnInputCanceled(int pointerId) { Entities.ForEach((ref Tappable tappable) => { if (tappable.PointerId == pointerId) { tappable.IsPressed = false; tappable.IsTapped = false; } }).Run(); } } }