/// <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); }
void IUpdatable.Update() { if (IsImmovable || _collider == null) { Velocity = Vector2.Zero; return; } if (ShouldUseGravity) { Velocity += Physics.Gravity * Time.DeltaTime; } Entity.Transform.Position += Velocity * Time.DeltaTime; CollisionResult collisionResult; // fetch anything that we might collide with at our new position var neighbors = Physics.BoxcastBroadphaseExcludingSelf(_collider, _collider.CollidesWithLayers); foreach (var neighbor in neighbors) { // if the neighbor collider is of the same entity, ignore it if (neighbor.Entity == Entity) { continue; } if (_collider.CollidesWith(neighbor, out collisionResult)) { // if the neighbor has an ArcadeRigidbody we handle full collision response. If not, we calculate things based on the // neighbor being immovable. var neighborRigidbody = neighbor.Entity.GetComponent <ArcadeRigidbody>(); if (neighborRigidbody != null) { ProcessOverlap(neighborRigidbody, ref collisionResult.MinimumTranslationVector); ProcessCollision(neighborRigidbody, ref collisionResult.MinimumTranslationVector); } else { // neighbor has no ArcadeRigidbody so we assume its immovable and only move ourself Entity.Transform.Position -= collisionResult.MinimumTranslationVector; var relativeVelocity = Velocity; CalculateResponseVelocity(ref relativeVelocity, ref collisionResult.MinimumTranslationVector, out relativeVelocity); Velocity += relativeVelocity; } } } }
public void Update() { if (_collider == null) { return; } //fetch anything that we might collide with us var neighbors = Physics.BoxcastBroadphaseExcludingSelf(_collider, _collider.CollidesWithLayers); foreach (var neighbor in neighbors) { if (_collider.Overlaps(neighbor)) { NotifyListeners(_collider, neighbor); } } }
/// <summary> /// checks to see if this Collider with motion applied (delta movement vector) collides with any collider. If it does, true will be /// returned and result will be populated with collision data. Motion will be set to the maximum distance the Collider can travel /// before colliding. /// </summary> /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns> /// <param name="motion">Motion.</param> /// <param name="result">Result.</param> public bool CollidesWithAny(ref Vector2 motion, out CollisionResult result) { result = new CollisionResult(); // fetch anything that we might collide with at our new position var colliderBounds = Bounds; colliderBounds.X += motion.X; colliderBounds.Y += motion.Y; var neighbors = Physics.BoxcastBroadphaseExcludingSelf(this, ref colliderBounds, CollidesWithLayers); // alter the shapes position so that it is in the place it would be after movement so we can check for overlaps var oldPosition = Shape.position; Shape.position += motion; var didCollide = false; foreach (var neighbor in neighbors) { // skip triggers if (neighbor.IsTrigger) { continue; } if (CollidesWith(neighbor, out result)) { // hit. back off our motion and our Shape.position motion -= result.MinimumTranslationVector; Shape.position -= result.MinimumTranslationVector; didCollide = true; } } // return the shapes position to where it was before the check Shape.position = oldPosition; return(didCollide); }
/// <summary> /// checks to see if this Collider collides with any other Colliders in the Scene. The first Collider it intersects will have its collision /// data returned in the CollisionResult. /// </summary> /// <returns><c>true</c>, if with was collidesed, <c>false</c> otherwise.</returns> /// <param name="result">Result.</param> public bool CollidesWithAny(out CollisionResult result) { result = new CollisionResult(); // fetch anything that we might collide with at our new position var neighbors = Physics.BoxcastBroadphaseExcludingSelf(this, CollidesWithLayers); foreach (var neighbor in neighbors) { // skip triggers if (neighbor.IsTrigger) { continue; } if (CollidesWith(neighbor, out result)) { return(true); } } return(false); }