protected override void OnUpdate() { if (!UpdateState()) { return; } RaycastInput rayInput = RaycastUtils.RaycastInputFromRay( _mainCamera.ScreenPointToRay(Input.mousePosition), _filter ); var raycastJob = new RaycastUtils.SingleRaycastJob { raycastInput = rayInput, physicsWorld = _physicsWorld }; raycastJob.Execute(); if (!raycastJob.hasHit) { return; } NativeEventStream.ThreadWriter writer = _eventSystem.CreateEventWriter <TEvent>(); writer.Write(EventFromRaycastHit(raycastJob.hit, _state)); _eventSystem.AddJobHandleForProducer <TEvent>(Dependency); }
public SuperspectiveRaycast GetRaycastHits() { Vector2 screenPos = PixelPositionOfReticle(); Ray ray = cam.ScreenPointToRay(screenPos); return(RaycastUtils.Raycast(ray.origin, ray.direction, interactionDistance, layerMask)); }
public SuperspectiveRaycast GetAnyDistanceRaycastHits() { Vector2 reticlePos = Reticle.instance.thisTransformPos; Vector2 screenPos = Vector2.Scale( reticlePos, new Vector2(SuperspectiveScreen.currentWidth, SuperspectiveScreen.currentHeight) ); Ray ray = cam.ScreenPointToRay(screenPos); return(RaycastUtils.Raycast(ray.origin, ray.direction, float.MaxValue, layerMask)); }
private void Update() { if (Input.GetMouseButtonDown(0)) { onTap(RaycastUtils.raycastObject(Camera.main)); } if (Input.GetMouseButton(0)) { currentSwipe?.onSwipeContinue(); } if (Input.GetMouseButtonUp(0)) { currentSwipe = null; } }
private Unity.Physics.RaycastHit SingleRaycast() { UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastInput raycastInput = new RaycastInput { Start = ray.origin, End = ray.GetPoint(2000f), Filter = new CollisionFilter() { BelongsTo = ~0u, CollidesWith = ~0u, // all 1s, so all layers, collide with everything GroupIndex = 0 } }; Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit(); RaycastUtils.SingleRayCast(_world, raycastInput, ref hit, this.Dependency); return(hit); }
void HandlePointer() { isPointerUp["currentState"] = RaycastUtils.IsCameraLookingAtObject(this.gameObject, layersToConsider); // If state remains unchanged, don't invoke events if (isPointerUp["currentState"] == isPointerUp["previousState"]) { return; } isPointerUp["previousState"] = isPointerUp["currentState"]; if (isPointerUp["currentState"]) { OnPointerEnter.Invoke(); } else { OnPointerExit.Invoke(); } }
private void Update() { if (Input.GetMouseButtonDown(0)) { startPosition = RaycastUtils.raycastPositionWith(cam, y: 1); } if (Input.GetMouseButton(0)) { Vector3?position = RaycastUtils.raycastPositionWith(cam, y: 1); if (position.HasValue) { onJoystickMove.Invoke(position.Value); } } if (Input.GetMouseButtonUp(0)) { startPosition = null; onFingerReleased.Invoke(); } }
public void Update(Vector2 dimensions, Direction facingDir) { const float EPSILON = 0.1f; //the extra amount to cast -> higher values make snapping more noticeable but provide more reliability and better adhesion to moving platforms. var position = transform.position.ToV2(); float heightOffset = dimensions.y / 3; //gives our cast more room to detect the ground (guards cases where we overshoot cuz we are falling quickly) float castLength = dimensions.x * Mathf.Tan(MAX_SLOPE_RADIANS) + heightOffset + EPSILON; //detect slopes of up to the maxDetectionAngle var xOffset = dimensions.x / 2f; var centerPoint = position; var leftPoint = new Vector2(position.x - xOffset, position.y); var rightPoint = new Vector2(position.x + xOffset, position.y); var centerRay = new Ray2D(position + Vector2.up * heightOffset, Vector2.down); var leftRay = new Ray2D(leftPoint + Vector2.up * heightOffset, Vector2.down); var rightRay = new Ray2D(rightPoint + Vector2.up * heightOffset, Vector2.down); CastInfo centerCast = RaycastUtils.Raycast(centerRay, castLength, GameUtils.Layers.GroundMask); CastInfo leftCast = RaycastUtils.Raycast(leftRay, castLength, GameUtils.Layers.GroundMask); CastInfo rightCast = RaycastUtils.Raycast(rightRay, castLength, GameUtils.Layers.GroundMask); CastInfo castInfo = centerCast.didHit ? centerCast : (leftCast.didHit ? leftCast : rightCast); SetGroundedInfo(castInfo, heightOffset + EPSILON, facingDir); CheckForStateChange(); if (followMovingObjects) { ///Cover the case of moving platforms! if (IsGrounded && castInfo.didHit) { position.y = castInfo.hitInfo.point.y; transform.position = position.ToV3(); } ///TODO -> still need handling for horizontal movement of platforms; that is a bit more /// involved though so ill leave it for now until some level design decisions are sorted } #if DEBUG_MODE ///bottom positions on collider DebugUtils.DrawSquare(centerPoint, 0.035f, Color.yellow); DebugUtils.DrawSquare(leftPoint, 0.035f, Color.yellow); DebugUtils.DrawSquare(rightPoint, 0.035f, Color.yellow); if (centerCast.didHit) { DebugUtils.DrawSquare(centerCast.hitInfo.point, 0.05f, Color.blue); } if (leftCast.didHit && rightCast.didHit) { DebugUtils.DrawConnection(leftCast.hitInfo.point, rightCast.hitInfo.point, Color.blue, Color.blue, 0.05f); } else if (leftCast.didHit) { DebugUtils.DrawSquare(leftCast.hitInfo.point, 0.05f, Color.blue); } else if (rightCast.didHit) { DebugUtils.DrawSquare(rightCast.hitInfo.point, 0.05f, Color.blue); } DebugUtils.DrawArrow(centerRay.origin, centerRay.GetPoint(castLength), Color.red, 0.1f); DebugUtils.DrawArrow(leftRay.origin, leftRay.GetPoint(castLength), Color.red, 0.1f); DebugUtils.DrawArrow(rightRay.origin, rightRay.GetPoint(castLength), Color.red, 0.1f); DebugUtils.DrawArrow(position, position + GroundSlope * xOffset * 1.5f, Color.green, 0.1f); if (castInfo.didHit) { DebugUtils.DrawSquare(castInfo.hitInfo.point, 0.1f, Color.magenta); } #endif }
protected override void OnUpdate() { _physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem <BuildPhysicsWorld>(); _world = _physicsWorldSystem.PhysicsWorld.CollisionWorld; if (Input.GetMouseButtonDown(1) && !_isDragging) { Unity.Physics.RaycastHit hit = SingleRaycast(); if (hit.Entity != Entity.Null) { // TODO this single raycast needs to hit a VALID terrain piece ShowAllDragIndicators(); _dragStartPos = hit.Position; _isDragging = true; } else { HideAllDragIndicators(); _isDragging = false; } } else if (_isDragging && Input.GetMouseButton(1)) { Unity.Physics.RaycastHit hit = SingleRaycast(); float3 dragEndPos = hit.Position; // Ignore dragging if some distance threshold is not met // Or if there are no selected formations if (hit.Entity == Entity.Null || math.distancesq(_dragStartPos, dragEndPos) < 5f) { isValidDrag = false; return; } // Check if its a valid drag for the # of selected formations var selectedFormations = GetSelectedFormations(); if (!selectedFormations.IsCreated || selectedFormations.Length == 0) { Debug.Log("No formations selected"); return; } var numSelectedFormations = selectedFormations.Length; float dragDist = math.distance(_dragStartPos, dragEndPos); // TODO formation width may NOT be evenly split float formationWidth = dragDist / numSelectedFormations; // Width for each formation (evenly split) if (formationWidth < MIN_FORMATION_WIDTH) { return; } // Red line to show the width of drag //Debug.DrawLine(dragStartPos, dragEndPos, Color.red, 0f, true); // Preparing batch raycasts in between the two drag positions to get curvature of the terrain // TODO this can be jobified, right? float3 dragDir = math.normalize(dragEndPos - _dragStartPos); quaternion rotateFor = quaternion.AxisAngle(new float3(0f, 1f, 0f), math.radians(-90f)); float3 dragFor = math.mul(rotateFor, dragDir); _dragForward = dragFor; var numSelectedUnits = _selectedFormationUnitQuery.CalculateEntityCount(); if (!TEMP_SLOT_ASSIGNMENTS.IsCreated) { TEMP_SLOT_ASSIGNMENTS = new NativeArray <float3>(numSelectedUnits, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); } else if (TEMP_SLOT_ASSIGNMENTS.Length != numSelectedUnits) { // Very common case to have to resize TEMP_SLOT_ASSIGNMENTS.Dispose(); TEMP_SLOT_ASSIGNMENTS = new NativeArray <float3>(numSelectedUnits, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); } var raycastInputs = new NativeArray <RaycastInput>(numSelectedUnits, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); var formationUnitIndices = new NativeArray <int>(numSelectedFormations, Allocator.Temp, NativeArrayOptions.UninitializedMemory); // TODO Calculate centroid of each formation. Assign formations accordingly. var currUnitIndex = 0; for (int i = 0; i < selectedFormations.Length; i++) { var currFormation = selectedFormations[i]; // Filters to an existing query to calculate unit count for one formation _selectedUnitQuery.SetSharedComponentFilter(currFormation); int numUnits = _selectedUnitQuery.CalculateEntityCount(); var raycastInputsSlice = raycastInputs.Slice(currUnitIndex, numUnits); numUnitsPerRow = math.clamp((int)(formationWidth / _distanceApart), MIN_FORMATION_WIDTH, MAX_FORMATION_WIDTH); // Draws the forward direction of the formation in white //Debug.DrawRay(math.lerp(dragStartPos, dragEndPos, 0.5f), dragFor); float3 startPoint = math.lerp(_dragStartPos, dragEndPos, (float)i / selectedFormations.Length); // TODO not working CollisionFilter raycastFilter = new CollisionFilter() { BelongsTo = _walkableLayer, CollidesWith = _walkableLayer, GroupIndex = 0 }; #region Creating raycast inputs int levels = numUnits / numUnitsPerRow; float3 forwardOffset; for (int currLevel = 0; currLevel < levels; currLevel++) { forwardOffset = dragFor * currLevel * _distanceApart; for (int j = 0; j < numUnitsPerRow; j++) { float3 sideOffset = dragDir * _distanceApart * j; float3 currUnitPos = startPoint + sideOffset - forwardOffset; raycastInputsSlice[j + (numUnitsPerRow * currLevel)] = new RaycastInput { Start = currUnitPos + new float3(0f, 20f, 0f), End = currUnitPos - new float3(0f, 20f, 0f), Filter = raycastFilter }; // DEBUG //Debug.DrawLine(currUnitPos, currUnitPos + new float3(0f, 1f, 0f), Color.blue); } } // For the remainder units in the back int calculatedUnits = numUnitsPerRow * levels; // The number of units we have finished calculating int remainderUnits = numUnits % numUnitsPerRow; float3 middlePos = (startPoint + (dragDir * numUnitsPerRow / 2 * _distanceApart)) - (dragDir * _distanceApart * remainderUnits / 2); forwardOffset = dragFor * levels * _distanceApart; for (int j = 0; j < remainderUnits; j++) { float3 sideOffset = dragDir * _distanceApart * j; float3 currUnitPos = middlePos + sideOffset - forwardOffset; raycastInputsSlice[calculatedUnits + j] = new RaycastInput { Start = currUnitPos + new float3(0f, 5f, 0f), End = currUnitPos - new float3(0f, 5f, 0f), Filter = raycastFilter }; // DEBUG //Debug.DrawLine(currUnitPos, currUnitPos + new float3(0f, 1f, 0f), Color.green); } formationUnitIndices[i] = currUnitIndex; currUnitIndex += numUnits; #endregion } NativeArray <float3> raycastResults = new NativeArray <float3>(numSelectedUnits, Allocator.TempJob, NativeArrayOptions.UninitializedMemory); // Runs the batch of raycasts // TODO schedule these raycasts all at once. This is very slow var handle = RaycastUtils.ScheduleBatchRayCastPosition(_world, raycastInputs, raycastResults, Dependency, out var hasFailed); handle.Complete(); raycastInputs.Dispose(); if (hasFailed) { Debug.Log("Dragging failed, disposing raycast results"); raycastResults.Dispose(); return; } ShowSelectedDragIndicators(); var handles = new NativeArray <JobHandle>(selectedFormations.Length, Allocator.TempJob); var translations = GetComponentDataFromEntity <Translation>(false); var rotations = GetComponentDataFromEntity <Rotation>(false); for (int i = 0; i < selectedFormations.Length; i++) { var currFormation = selectedFormations[i]; var unitPositionsSlice = raycastResults.Slice(formationUnitIndices[i]); handles[i] = Entities .WithName("AlignUnitDragIndicators") .WithReadOnly(unitPositionsSlice) .WithAll <DragIndicatorTag, Translation, Rotation>() .WithSharedComponentFilter(currFormation) .WithNativeDisableContainerSafetyRestriction(translations) .WithNativeDisableContainerSafetyRestriction(rotations) .ForEach((Entity entity, int entityInQueryIndex) => { translations[entity] = new Translation { Value = unitPositionsSlice[entityInQueryIndex] + new float3(0f, 0.1f, 0f) }; rotations[entity] = new Rotation { Value = quaternion.LookRotation(dragFor, math.up()) }; }).ScheduleParallel(Dependency); } new CopyFloat3Job { Output = TEMP_SLOT_ASSIGNMENTS, Input = raycastResults }.Schedule(raycastResults.Length, 128, JobHandle.CombineDependencies(handles)).Complete(); isValidDrag = true; handles.Dispose(); formationUnitIndices.Dispose(); } else if (isValidDrag && Input.GetMouseButtonUp(1)) { isValidDrag = false; EaseOfAssignmentUnitAssignment(); //SpatialUnitAssignmnet(); } else { _isDragging = false; if (Input.GetKey(KeyCode.Space)) { ShowAllDragIndicators(); } else { HideAllDragIndicators(); } } _endSimulationEcbSystem.AddJobHandleForProducer(this.Dependency); }
private void OnWideSelection(float3 startPos, float3 endPos) { var upperBound = new float3( math.max(startPos.x, endPos.x), 0f, math.min(startPos.z, endPos.z) ); var lowerBound = new float3( math.min(startPos.x, endPos.x), 0f, math.max(startPos.z, endPos.z) ); BlobAssetReference <Collider> collider = RaycastUtils.GetBoxCollider( upperBound, lowerBound, new CollisionFilter { BelongsTo = ~0u, CollidesWith = (uint)CollisionLayer.Grid, GroupIndex = 0 } ); var maxNewElements = _selectionList.Length * 2 + 1; var hits = new NativeList <ColliderCastHit>(Allocator.TempJob); var hitEntities = new NativeList <Entity>(Allocator.TempJob); var entitiesToAdd = new NativeList <Entity>(maxNewElements, Allocator.TempJob) { Length = maxNewElements }; var entitiesToRemove = new NativeList <Entity>(maxNewElements, Allocator.TempJob) { Length = maxNewElements }; var totalEntities = new NativeList <Entity>(Allocator.TempJob); JobHandle boxCastJob = new RaycastUtils.ColliderCastJob { physicsWorld = _physicsWorld, hits = hits, origin = upperBound / 2f + lowerBound / 2f, collider = collider }.Schedule(_physicsSystem.GetOutputDependency()); var boxCastDep = JobHandle.CombineDependencies( Dependency, _physicsSystem.GetOutputDependency(), boxCastJob ); JobHandle convertJob = new ConvertHitsToEntitiesJob { hits = hits, hitEntities = hitEntities, selectionList = _selectionList, totalEntities = totalEntities }.Schedule(boxCastDep); var convertDep = JobHandle.CombineDependencies(boxCastDep, convertJob); hits.Dispose(convertDep); JobHandle getSelectionDiffJob = new GetSelectionDiffJob { totalEntities = totalEntities, selectionList = _selectionList, hitEntities = hitEntities, entitiesToAdd = entitiesToAdd, entitiesToRemove = entitiesToRemove }.Schedule(totalEntities, 1, convertDep); var getSelectionDiffDep = JobHandle.CombineDependencies( convertDep, getSelectionDiffJob ); hitEntities.Dispose(getSelectionDiffDep); totalEntities.Dispose(getSelectionDiffDep); JobHandle selectJob = new SetSelectionJob { selectionList = entitiesToAdd, select = true, parallelWriter = _ecbSystem.CreateCommandBuffer() .AsParallelWriter() }.Schedule(entitiesToAdd, 1, getSelectionDiffDep); JobHandle unselectJob = new SetSelectionJob { selectionList = entitiesToRemove, select = false, parallelWriter = _ecbSystem.CreateCommandBuffer() .AsParallelWriter() }.Schedule(entitiesToRemove, 1, getSelectionDiffDep); var selectionJobDep = JobHandle.CombineDependencies( getSelectionDiffDep, selectJob, unselectJob ); JobHandle updateSelectionJob = new UpdateSelectionJob { selectionList = _selectionList, entitiesToAdd = entitiesToAdd, entitiesToRemove = entitiesToRemove }.Schedule(selectionJobDep); var updateSelectionDep = JobHandle.CombineDependencies( selectionJobDep, updateSelectionJob ); entitiesToAdd.Dispose(updateSelectionDep); entitiesToRemove.Dispose(updateSelectionDep); _selectionJobHandle = updateSelectionDep; }
public void Update() { var hit = RaycastUtils.CastClickRay(settings.TargetLayers); var mousePos = Input.mousePosition; //Do we allow draggin? And Is The target the same from the click start? And has the mouse not moved much? bool isDrag = settings.AllowDragging && (hit.collider == null || hit.collider != mouseDownTarget) && Vector2.Distance(mousePos, mouseDownPosition) > settings.dragStartDistance; //Click Start if (Input.GetMouseButtonDown(settings.Button)) { //mouseDownTime = Time.time; mouseDownPosition = Input.mousePosition; mouseDownRealWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition); mouseDownTarget = hit.collider; } //Dragging else if (Input.GetMouseButton(settings.Button)) { if (!isDrag) { if (OnClickHold != null) { OnClickHold(new TargetingArguments(hit.collider, hit.point)); } } else { RaycastHit[] allHits = RaycastUtils.BoxSelect(settings.TargetLayers, mouseDownPosition); if (OnMultiSelectHover != null) { OnMultiSelectHover(allHits.Select(h => new TargetingArguments(h.collider, h.point)).ToArray()); } } } //Released else if (Input.GetMouseButtonUp(settings.Button)) { if (!isDrag) { if (OnClicked != null) { OnClicked(new TargetingArguments(hit.collider, hit.point)); } } else { RaycastHit[] allHits = RaycastUtils.BoxSelect(settings.TargetLayers, mouseDownPosition); if (OnMultiSelect != null) { OnMultiSelect(allHits.Select(h => new TargetingArguments(h.collider, h.point)).ToArray()); } } } else //Just Hovering { if (OnHover != null) { OnHover(new TargetingArguments(hit.collider, hit.point)); } } }