protected bool PerformMovement(Vector2 _movement) { // Create variables bool _isGrounded = false; bool _isOverlappingWarp = false; int _count = 0; int _closestHitIndex = -1; float _distance = _movement.magnitude; RaycastHit2D[] _hitResults = new RaycastHit2D[16]; // Return if not enough movement if (_distance < MinMovementDistance) { return(false); } // Cast collider and collide on obstacles contactFilter.useTriggers = true; _count = collider.Cast(_movement, contactFilter, _hitResults, _distance + Physics2D.defaultContactOffset); contactFilter.useTriggers = false; for (int _i = 0; _i < _count; _i++) { // Check warp if (_hitResults[_i].collider.isTrigger) { if (_hitResults[_i].collider.gameObject.HasTag("Warp") && collider.Distance(_hitResults[_i].collider).isOverlapped) { _isOverlappingWarp = true; if (currentWarp == null) { currentWarp = _hitResults[_i].collider.GetComponent <Warp>(); } } continue; } if (!CheckColliderTag(_hitResults[_i], _movement)) { continue; } // Cache normal hit Vector2 _normal = _hitResults[_i].normal; // Y movement related calculs if (Mathf.Approximately(_normal.y, 1)) { _isGrounded = true; velocity.y = 0; } else if (Mathf.Approximately(_normal.y, -1)) { velocity.y = 0; } // Get minimum distance float _newDistance = _hitResults[_i].distance - Physics2D.defaultContactOffset; if (_newDistance < _distance) { _distance = _newDistance; _closestHitIndex = _i; } } // Teleport if needed if (!_isOverlappingWarp && (currentWarp != null)) { currentWarp.TryToTeleport(this); currentWarp = null; } // Return if not enough movement if (_distance < MinMovementDistance) { OnHitSomething?.Invoke(_hitResults[_closestHitIndex]); return(true); } // Set isGrounded if ((_isGrounded != isGrounded) && (_movement.y != 0)) { IsGrounded = _isGrounded; } // Flip if needed if ((_movement.x != 0) && (Mathf.Sign(_movement.x) != (isFacingRight ? 1 : -1))) { Flip(); } // Move the object _movement = _movement.normalized * _distance; transform.position = (Vector2)transform.position + _movement; rigidbody.position += _movement; // Return if hit something or not if (_closestHitIndex > -1) { OnHitSomething?.Invoke(_hitResults[_closestHitIndex]); return(true); } return(false); }