/// <summary> /// caculates the movement modifying the motion vector to take into account any collisions that will /// occur when moving /// </summary> /// <returns><c>true</c>, if movement was calculated, <c>false</c> otherwise.</returns> /// <param name="motion">Motion.</param> /// <param name="collisionResult">Collision result.</param> public bool CalculateMovement(ref System.Numerics.Vector2 motion, out CollisionResult collisionResult) { collisionResult = new CollisionResult(); // no collider? just move and forget about it if (Entity.GetComponent <Collider>() == null || _triggerHelper == null) { return(false); } // 1. move all non-trigger Colliders and get closest collision var colliders = Entity.GetComponents <Collider>(); for (var i = 0; i < colliders.Count; i++) { var collider = colliders[i]; // skip triggers for now. we will revisit them after we move. if (collider.IsTrigger) { continue; } // fetch anything that we might collide with at our new position var bounds = collider.Bounds; bounds.X += motion.X; bounds.Y += motion.Y; var neighbors = Physics.BoxcastBroadphaseExcludingSelf(collider, ref bounds, collider.CollidesWithLayers); foreach (var neighbor in neighbors) { // skip triggers for now. we will revisit them after we move. if (neighbor.IsTrigger) { continue; } if (collider.CollidesWith(neighbor, motion, out CollisionResult _InternalcollisionResult)) { // hit. back off our motion motion -= _InternalcollisionResult.MinimumTranslationVector; // If we hit multiple objects, only take on the first for simplicity sake. if (_InternalcollisionResult.Collider != null) { collisionResult = _InternalcollisionResult; } } } } ListPool <Collider> .Free(colliders); return(collisionResult.Collider != null); }
/// <summary> /// Calculates the movement modifying the motion vector to take into account any collisions that will /// occur when moving. This version is modified to output through a given collection to show every /// collision that occured. /// </summary> /// <returns>The amount of collisions that occured.</returns> /// <param name="motion">Motion.</param> /// <param name="collisionResult">Collision result.</param> public int AdvancedCalculateMovement(ref System.Numerics.Vector2 motion, ICollection <CollisionResult> collisionResults) { int Collisions = 0; // no collider? just move and forget about it if (Entity.GetComponent <Collider>() == null || _triggerHelper == null) { return(Collisions); } // 1. move all non-trigger Colliders and get closest collision var colliders = Entity.GetComponents <Collider>(); for (var i = 0; i < colliders.Count; i++) { var collider = colliders[i]; // skip triggers for now. we will revisit them after we move. if (collider.IsTrigger) { continue; } // fetch anything that we might collide with at our new position var bounds = collider.Bounds; bounds.X += motion.X; bounds.Y += motion.Y; var neighbors = Physics.BoxcastBroadphaseExcludingSelf(collider, ref bounds, collider.CollidesWithLayers); foreach (var neighbor in neighbors) { // skip triggers for now. we will revisit them after we move. if (neighbor.IsTrigger) { continue; } if (collider.CollidesWith(neighbor, motion, out CollisionResult _InternalcollisionResult)) { // hit. back off our motion motion -= _InternalcollisionResult.MinimumTranslationVector; collisionResults.Add(_InternalcollisionResult); Collisions++; } } } ListPool <Collider> .Free(colliders); return(Collisions); }
/// <summary> /// update should be called AFTER Entity is moved. It will take care of any ITriggerListeners that the Collider overlaps. /// </summary> public void Update() { // 3. do an overlap check of all entity.colliders that are triggers with all broadphase colliders, triggers or not. // Any overlaps result in trigger events. var colliders = _entity.GetComponents <Collider>(); for (var i = 0; i < colliders.Count; i++) { var collider = colliders[i]; // fetch anything that we might collide with us at our new position var neighbors = Physics.BoxcastBroadphase(collider.Bounds, collider.CollidesWithLayers); foreach (var neighbor in neighbors) { // we need at least one of the colliders to be a trigger if (!collider.IsTrigger && !neighbor.IsTrigger) { continue; } if (collider.Overlaps(neighbor)) { var pair = new Pair <Collider>(collider, neighbor); // if we already have this pair in one of our sets (the previous or current trigger intersections) dont call the enter event var shouldReportTriggerEvent = !_activeTriggerIntersections.Contains(pair) && !_previousTriggerIntersections.Contains(pair); if (shouldReportTriggerEvent) { NotifyTriggerListeners(pair, true); _previousColliders.Add(pair); } _activeTriggerIntersections.Add(pair); CheckForStayColliders(); } // overlaps } // end foreach } ListPool <Collider> .Free(colliders); CheckForExitedColliders(); }