public void Move(Vector3 input, out Vector3 movement) { Vector3 position = transform.position; Vector3 direction = input.normalized; float distance = input.magnitude; ContactFilter2D filter = new ContactFilter2D(); filter.layerMask = groundLayer; //Perform a sweep test to see if there are any objects in the way RaycastHit2D hit = Physics2D.CapsuleCast(transform.position + (Vector3)collider.offset, collider.size, collider.direction, transform.rotation.eulerAngles.z, direction, distance, groundLayer); if (hit && !hit.collider.CompareTag("Platform")) { float normalDistance = distance - hit.distance; position += input * hit.distance; position += (Vector3)hit.normal * normalOffset; //slide along the surface hit Vector3 slide = Vector3.ProjectOnPlane(direction * normalDistance * slideAmount, hit.normal); position += slide; } else { position += input; } movement = position - transform.position; transform.position = position; }
private bool IsGrounded() { var bounds = _capCollider.bounds; RaycastHit2D hit = Physics2D.CapsuleCast(bounds.center, bounds.size, CapsuleDirection2D.Vertical, 0, Vector2.down, bounds.extents.y + .01f, groundLayerMask); return(hit.collider != null || IsOnScrollable()); }
// Use this for initialization void Awake() { animator = GetComponent <Animator>(); rigidbody2D = GetComponent <Rigidbody2D>(); spriteRenderer = GetComponent <SpriteRenderer>(); capsuleCollider2D = GetComponent <CapsuleCollider2D>(); jumpCount = maxJumps; //should be safe??? int intMask = 0; intMask |= (1 << LayerMask.NameToLayer("Player")); layerMask = ~intMask; bool selfCast = Physics2D.CapsuleCast(capsuleCollider2D.offset + (Vector2)transform.position, capsuleCollider2D.size * 0.95f, CapsuleDirection2D.Vertical, transform.rotation.eulerAngles.z, -transform.up, 0, layerMask); bool DownCast = Physics2D.CircleCast(capsuleCollider2D.offset + (Vector2)(transform.position) - new Vector2(0, ((capsuleCollider2D.size.y - capsuleCollider2D.size.x) / 2f + capsuleCollider2D.size.x / 2f)), capsuleCollider2D.size.x * 0.49f, -transform.up, capsuleCollider2D.size.x * 0.05f, layerMask); Debug.Log(DownCast + " " + selfCast); if (DownCast == true && selfCast == false) { onGround = true; } else { onGround = false; } }
private bool IsGrounded() { RaycastHit2D raycastHit2d = Physics2D.CapsuleCast(capsuleCollider2d.bounds.center, capsuleCollider2d.bounds.size, capsuleCollider2d.direction, 0f, Vector2.down, .03f, platformsLayerMask); Debug.Log(raycastHit2d.collider); return(raycastHit2d.collider != null); }
private void DetectingEnemies() { if (!invulnerabity) { RaycastHit2D[] results = new RaycastHit2D[16]; List <Vector2> normals = new List <Vector2>(); int count = Physics2D.CapsuleCast(GetComponent <Transform>().position, GetComponent <CapsuleCollider2D>().size * 1.05f, CapsuleDirection2D.Vertical, 0, Vector2.zero, enemyContactFilter, results); if (count > 0) { GameObject firstEnemy = results[0].collider.gameObject; for (int i = 0; i < count; i++) { if (results[i].collider.gameObject.Equals(firstEnemy)) { normals.Add(results[i].normal); } } EnemyBehaviour enemy = firstEnemy.GetComponent <EnemyBehaviour>(); stats.ChangePatience(-enemy.GetDamage() / 100); enemy.CollideWithPlayer(); soundsmanager.PlaySound("Daño"); inputActivated = false; Invulnerable(true); KnockBack(normals); } } }
public void Move(Vector2 velocityBias, bool isDash = false) { // DebugExtension.DebugArrow( BodyPosition, velocityBias, Color.blue ); // DebugExtension.DebugArrow( BodyPosition, CurrentVelocity, Color.red ); if (Time.deltaTime <= 0) { return; } var amount = (CurrentVelocity + velocityBias) * Time.deltaTime; var length = amount.magnitude; var direction = amount.normalized; var hit = Physics2D.CapsuleCast(BodyPosition, 0.6f * BodySize, CapsuleDirection2D.Vertical, 0, direction, length, _moveBlockingLayerMask | (isDash ? 0 : _dashableObstacleLayerMask)); if (hit.collider != null && !transform.IsAncestorOf(hit.collider.transform)) { DebugExtension.DebugPoint(hit.point, Color.yellow, 0.1f, 1); BodyPosition = hit.centroid; CancelHorizontalMovement(); } else { transform.Translate(direction * length); } CheckWallCollisions(isDash); }
private void DetectingMotionPlatform() { RaycastHit2D[] results = new RaycastHit2D[16]; int count = Physics2D.CapsuleCast(GetComponent <Transform>().position, GetComponent <CapsuleCollider2D>().size * 1.05f, CapsuleDirection2D.Vertical, 0, Vector2.zero, motionPlatformContactFilter, results); if (count > 0) { bool existsOne = false; int j = -1; for (int i = 0; i < count; i++) { if (results[i].normal.y > 0.65f) { j = i; } } if (j != -1) { onMotionPlatform = results[j].collider.gameObject.GetComponent <Transform>(); GetComponent <Transform>().parent = onMotionPlatform; } } else { GetComponent <Transform>().parent = null; onMotionPlatform = null; } }
protected virtual void Attacks() { bool attack = false; if (grounded || canKick) { if (Input.GetButtonDown("AttackLeft") && !attacking) { side = LEFT; attack = true; canKick = false; } else if (Input.GetButtonDown("AttackRight") && !attacking) { side = RIGHT; attack = true; canKick = false; } } if (attack) { attacking = true; if (grounded) { } else { rigidbody.velocity = side == RIGHT ? Vector2.right * 20 : Vector2.left * 20; } Invoke("StopAttack", 0.25f); } if (attacking) { Vector3 dir; if (side == RIGHT) { dir = Vector3.right; } else { dir = Vector3.left; } RaycastHit2D hit = Physics2D.CapsuleCast(transform.position, new Vector2(0.2f, 0.8f), CapsuleDirection2D.Vertical, 0, dir, 1f, int.MaxValue); if (hit.collider) { Enemy enemy = hit.collider.GetComponent <Enemy>(); if (enemy) { enemy.Die(side); } } } }
private RaycastHit2D CapsuleCast(Vector2 sizeMultiplier, Vector2 direction, float distance) { Vector2 pos = _capsuleCollider.offset + Vector2.up * 0.1f; Vector2 size = _capsuleCollider.size; size.x *= sizeMultiplier.x; size.y *= sizeMultiplier.y; return(Physics2D.CapsuleCast(transform.TransformPoint(pos), size, _capsuleCollider.direction, 0, direction, distance, _movementRaycastMask)); }
public override RaycastHit2D Cast(Vector2 position, Vector2 scale, float rotation, Vector2 motion) { return(Physics2D.CapsuleCast(position + PositionOffset, Size * scale, Direction, rotation + AngleOffset, motion.normalized, motion.magnitude, CollisionMask.value, CollisionMinDepth, CollisionMaxDepth)); }
private bool IsGrounded() { float extraHeightText = 0.01f; var bounds = _capsuleCollider2D.bounds; Vector2 origin = new Vector2(bounds.center.x, bounds.center.y - 0.5f); Vector2 size = new Vector2(bounds.size.x * 0.8f, bounds.size.y); RaycastHit2D raycastHit = Physics2D.CapsuleCast(origin, size, CapsuleDirection2D.Vertical, 0f, Vector2.down, extraHeightText, platformLayerMask); _isGrounded = raycastHit.collider != null; return(_isGrounded); }
void FixedUpdate() { Vector2 v = rb.velocity; v.x = movement * movementSpeed; grounded = Physics2D.CapsuleCast(transform.position, new Vector2(1, 2), CapsuleDirection2D.Vertical, 0, Vector2.down, 0.1f, groundMask); if (input.axis.x != 0) { if (Physics2D.BoxCast(new Vector3(0, 0.5f, 0) + transform.position, new Vector2(0.5f, 0.5f), 0, new Vector2(movement, 0), 0.5f, groundMask)) { v.x = 0; if (input.axis.y > 0 && canJump) { movement = input.axis.x * -1f; movementCooldown = 0.3f; rb.AddForce(Vector2.up * jumpForce); canJump = false; wallSliding = false; } else { wallSliding = true; v.y = slideSpeed; } grounded = true; } else { wallSliding = false; } } if (!canJump && grounded && input.axis.y <= 0) { canJump = true; } if (input.axis.y > 0 && canJump) { rb.AddForce(Vector2.up * jumpForce); canJump = false; } input.axis.y = 0; rb.velocity = v; }
public bool DetectGap() { var ahead = enemy.Stats.Direction.x < 0 ? enemy.Components.Collider.bounds.min.x : enemy.Components.Collider.bounds.max.x; RaycastHit2D hit = Physics2D.CapsuleCast( new Vector2(ahead, enemy.Components.Collider.bounds.center.y), enemy.Components.Collider.bounds.size, CapsuleDirection2D.Vertical, 0, Vector2.down, 0.1f, enemy.Components.GroundLayer); return(hit.collider == null); }
public void LateUpdate() { Physics2D.queriesHitTriggers = false; //RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.up, 0.1f); RaycastHit2D hit = Physics2D.CapsuleCast(transform.position, new Vector3(0.3f, 0.3f, 0.3f), CapsuleDirection2D.Vertical, 360, transform.up, 0.2f); Physics2D.queriesHitTriggers = true; if (hit.collider != null && hit.collider.transform.root != transform.root) { HitSomething(hit.collider.gameObject, hit.point); } Debug.DrawRay(transform.position, transform.up); }
public Collider2D DetectCollider(LayerMask colliderLayer) { var capsuleSize = new Vector2(collider.bounds.size.x, collider.bounds.size.y); RaycastHit2D hit = Physics2D.CapsuleCast( collider.bounds.center, capsuleSize, CapsuleDirection2D.Vertical, 0, new Vector2(transform.localScale.x, 0), 0.1f, colliderLayer); return(hit.collider); }
bool Gap() { RaycastHit2D hit; if (side == RIGHT) { hit = Physics2D.CapsuleCast(transform.position + Vector3.right * 0.5f, new Vector2(0.5f, 1.0f), CapsuleDirection2D.Vertical, 0, Vector3.down, 1.0f, int.MaxValue); } else { hit = Physics2D.CapsuleCast(transform.position + Vector3.left * 0.5f, new Vector2(0.5f, 1.0f), CapsuleDirection2D.Vertical, 0, Vector3.down, 1.0f, int.MaxValue); } return(!hit.collider); }
public bool CheckCast(float reduceOfs, Vector2 dir, out RaycastHit2D hit, float dist, int mask) { if (mCapsuleColl) { Transform collT = transform; Vector2 collPos = collT.position + collT.localToWorldMatrix.MultiplyPoint3x4(mCapsuleColl.offset); Vector2 collSize = mCapsuleColl.size; collSize.y -= reduceOfs; hit = Physics2D.CapsuleCast(collPos, collSize, mCapsuleColl.direction, collT.eulerAngles.z, dir, dist, mask); return(hit.collider != null); } else { hit = Physics2D.CircleCast(transform.position, mRadius - reduceOfs, dir, dist, mask); return(hit.collider != null); } }
private void TryRaycast(Vector2 from, Vector2 to) { RaycastHit2D hit = Physics2D.CapsuleCast(from, size, CapsuleDirection2D.Vertical, _angle, to - from); if (hit) { Debug.Log("Raycast hit in: " + hit.transform.name); if (boxPosition != null) { boxPosition.position = hit.centroid; Quaternion rotation = boxPosition.rotation; rotation.eulerAngles = new Vector3(0f, 0f, _angle); boxPosition.rotation = rotation; } } }
public void Attack() { if (!dead && currentHitChest == null) { _animator.SetTrigger("attack"); Vector2 pos = _capsuleCollider.offset + Vector2.up * 0.1f; if (!FacingRight) { pos.x *= -1; } var result = Physics2D.CapsuleCast(transform.TransformPoint(pos), _capsuleCollider.size, _capsuleCollider.direction, 0, Vector2.right * (FacingRight ? 1 : -1), 1f, _enemyRaycastMask); if (result.collider != null) { result.collider.GetComponent <Hunter> ().Die(); } } }
private bool IsGrounded() { float extraHeightText = 0.04f; RaycastHit2D raycastHit = Physics2D.CapsuleCast(capsuleCollider.bounds.center, capsuleCollider.bounds.size, CapsuleDirection2D.Vertical, 0, Vector2.down, extraHeightText, platformLayerMask); //Color rayColor; //if (raycastHit.collider != null) //{ // rayColor = Color.green; //} else //{ // rayColor = Color.red; //} //Debug.DrawRay(collider.bounds.center + new Vector3(collider.bounds.extents.x, 0), Vector2.down * (collider.bounds.extents.y + extraHeightText), rayColor); //Debug.DrawRay(collider.bounds.center - new Vector3(collider.bounds.extents.x, 0), Vector2.down * (collider.bounds.extents.y + extraHeightText), rayColor); //Debug.DrawRay(collider.bounds.center - new Vector3(collider.bounds.extents.x, collider.bounds.extents.y), Vector2.right * (collider.bounds.extents.y + extraHeightText), rayColor); //Debug.Log(raycastHit.collider); return(raycastHit.collider != null); }
private bool CheckGrounded() { bool result = false; LayerMask layerMask = (1 << 8) | (1 << 9) | (1 << 11); ; //layerMask = ~layerMask; List <Collider2D> results = new List <Collider2D>(); ContactFilter2D contactFilter2D = new ContactFilter2D(); contactFilter2D.SetLayerMask(layerMask); RaycastHit2D raycastHit2D; raycastHit2D = Physics2D.CapsuleCast(transform.position, capsuleCollider2D.size, capsuleCollider2D.direction, 0, Vector2.down, 1, layerMask); if (raycastHit2D.collider != null && raycastHit2D.distance > 0 && raycastHit2D.distance < 0.035) { result = true; } return(result); }
public bool CheckFront() { if (forwardHits == null) { forwardHits = new RaycastHit2D[raycastBuffer]; } Vector2 faceVector = new Vector2(facing, 0f); ContactFilter2D filter = new ContactFilter2D(); filter.useTriggers = false; int hitCount = Physics2D.CapsuleCast(new Vector2(playerCollider.bounds.center.x + (facing * playerCollider.bounds.extents.x), playerCollider.bounds.center.y), new Vector2(.1f, playerCollider.bounds.size.y), CapsuleDirection2D.Vertical, 0f, faceVector, filter, forwardHits, .1f); for (int i = 0; i < hitCount; i++) { RaycastHit2D hit = forwardHits[i]; if (hit.collider != null && hit.collider != playerCollider) { return(true); } } return(false); }
void Update() { if (GameController.instance == null) { return; } if (GameController.instance.currentState == GameController.GameState.Play || GameController.instance.currentState == GameController.GameState.Cutscene) { float hNewVel; // Nova velocidade horizontal do player. float vNewVel; // Nova velocidade vertical do player. // Movimento horizontal, também garante que o player nunca ultrapasse a velocidade máxima. if (GameController.instance.currentState == GameController.GameState.Cutscene) { target.input.verticalAxis = 0f; } if (grounded) { hNewVel = target.input.horizontalAxis * velocity; } else { hNewVel = Mathf.Clamp(_rigidbody.velocity.x + Mathf.CeilToInt(target.input.horizontalAxis * velocity) * airAcelerationMultiplier, -velocity, velocity); } // Movimento vertical. vNewVel = _rigidbody.velocity.y; // Verifica que esta tocando no chão. grounded = Physics2D.CapsuleCast(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0), new Vector2(_collider.size.x, _collider.size.y), CapsuleDirection2D.Vertical, 0, -Vector2.up, 0.1f, rayMask); // DEBUG #if UNITY_EDITOR if (grounded) { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) - new Vector3(0, _collider.size.y / 2, 0), transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) - new Vector3(0, _collider.size.y / 2, 0) - new Vector3(0, _collider.size.y * 0.075f, 0), Color.red); } else { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) - new Vector3(0, _collider.size.y / 2, 0), transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) - new Vector3(0, _collider.size.y / 2, 0) - new Vector3(0, _collider.size.y * 0.075f, 0), Color.green); } #endif // Verifica se o player foi esmagado. if (grounded) { bool crushed = false; RaycastHit2D ray; if (ray = Physics2D.Raycast(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) + new Vector3(0, _collider.size.y / 2, 0), Vector2.up, _collider.size.y * 0.03f, rayMask)) { if (ray.collider.tag == "Plataform") { crushed = true; } } if (crushed) { Player.instance.Death(); } // DEBUG #if UNITY_EDITOR if (crushed) { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) + new Vector3(0, _collider.size.y / 2, 0), transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) + new Vector3(0, _collider.size.y / 2, 0) + new Vector3(0, _collider.size.y * 0.05f, 0), Color.red); } else { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) + new Vector3(0, _collider.size.y / 2, 0), transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0) + new Vector3(0, _collider.size.y / 2, 0) + new Vector3(0, _collider.size.y * 0.05f, 0), Color.green); } #endif } // Verifica se o Player está tentando andar contra uma parede, usado para evitar que ele possa "grudar em paredes" durante um pulo. bool blocked = Physics2D.CapsuleCast(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0), new Vector2(_collider.size.x, _collider.size.y * 0.95f), CapsuleDirection2D.Vertical, 0, Player.instance.facing * Vector2.right, 0.05f, rayMask); if (blocked) { hNewVel = 0; } // DEBUG #if UNITY_EDITOR if (blocked) { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0), transform.position + Player.instance.facing * (new Vector3(0.05f, 0, 0) + new Vector3(_collider.size.x / 2, 0, 0)), Color.red); } else { Debug.DrawLine(transform.position + new Vector3(_collider.offset.x, _collider.offset.y, 0), transform.position + Player.instance.facing * (new Vector3(0.05f, 0, 0) + new Vector3(_collider.size.x / 2, 0, 0)), Color.green); } #endif // Evita a soma de addForces no pulo. if (target.input.jumpButton && grounded && GameController.instance.currentState == GameController.GameState.Play) { vNewVel = 0; } if (GameController.instance.currentState == GameController.GameState.Cutscene) { hNewVel = velocity; } // Aplica a velocidade ao player. _rigidbody.velocity = new Vector2(hNewVel, vNewVel); // Realiza o pulo. if (target.input.jumpButton && grounded && GameController.instance.currentState == GameController.GameState.Play) { _rigidbody.AddForce(_rigidbody.mass * Mathf.Sqrt(2 * jumpHeight * 10) * Vector2.up, ForceMode2D.Impulse); } } }
//In here the speed is actually used, and collision is handled. private void HandleMovement() { //0. cache deltaTime. float deltaTime = Time.deltaTime; //0.5 check for ground. Vector2 origin = transform.position; Vector2 groundCheckPos = origin; groundCheckPos.y += verticalOriginToGroundOffset; Physics2D.queriesHitTriggers = false; //Collider2D groundCollider = Physics2D.OverlapCircle(groundCheckPos, groundCheckTolerance, groundMask); float halfHeight = verticalGroundCheckOffset * 0.5f; RaycastHit2D groundHit = Physics2D.CircleCast(origin + new Vector2(0, halfHeight), groundCheckTolerance, Vector2.down, -halfHeight, groundMask); if (!isGrounded && groundHit) { audioSource.PlayOneShot(landOnGroundSFX); } isGrounded = groundHit; //0.75 snap to the surface. if (isGrounded && velocity.y <= 0) { float groundY = groundHit.point.y - verticalOriginToGroundOffset; if (Mathf.Abs(groundY - origin.y) <= groundSnapDistance) { origin.y = groundY; //after snapping, also make sure that the desired downwards velocity is really low to avoid collision bugs. if (desiredVelocity.y <= 0) { desiredVelocity.y = 0; } } } //1. Do gravity stuff. if (!isGrounded) { desiredVelocity.y -= gravity * deltaTime; desiredVelocity.y = Mathf.Max(desiredVelocity.y, -maxVerticalVelocity); } MoveWithCollision(true); //Making this bit a local method because i shouldnt think about using this outside of this context //also because it needs to be able to call itself without f*****g things up lol. void MoveWithCollision(bool allowRecursion) { //2. use the desired velocity to check where to go Vector2 translation = desiredVelocity * deltaTime; Vector2 projectedPosition = origin + translation; //3. cast the collider, check for collision on the way there. //RaycastHit2D[] hits = new RaycastHit2D[5]; float distance = translation.magnitude; Vector2 direction = translation.normalized; //I HAVE to write this long line because for some stupid reason, unity wont allow CapsuleCollider2D.Cast without a rigidbody??? //ITS DOING THE EXACT SAME THING, WHY DOESNT ONE WORK WITHOUT A RIGIDBODY???? Physics2D.queriesHitTriggers = false; //just make this query ignore triggers real quick <.< RaycastHit2D hit = Physics2D.CapsuleCast(origin + collider.offset, collider.size, collider.direction, 0, direction, distance, groundMask); Physics2D.queriesHitTriggers = true; //4. update velocity based on travelled distance. if (hit) { //tiny distance away stops the player from getting stuck, but causes some stutter. Vector2 maxTravelDist = Mathf.Max(0, hit.distance - 0.05f) * direction; //if bumping into the ceiling, reset velocity to 0, the player should just fall down afterwards. if (hit.normal.y < -0.9f && desiredVelocity.y > 0.0f) { desiredVelocity.y = 0.0f; if (desiredVelocity.sqrMagnitude > 0.1f && allowRecursion) { MoveWithCollision(false); } return; } if ((hit.normal.x > 0.9f && desiredVelocity.x < 0.0f) || (hit.normal.x < -0.9f && desiredVelocity.x > 0f)) { desiredVelocity.x = 0.0f; if (desiredVelocity.sqrMagnitude > 0.1f && allowRecursion) { MoveWithCollision(false); } return; } transform.position = origin + maxTravelDist; //remove velocity based on hit.normal? velocity = maxTravelDist / deltaTime; } else { transform.position = projectedPosition; velocity = desiredVelocity; } } }
void Update() { inputVector.x = Input.GetAxis("Horizontal"); inputVector.y = Input.GetAxis("Vertical"); Vector3 lookAtTarget = Camera.main.ScreenToWorldPoint(Input.mousePosition); lookAtTarget.z = 0; // don't bother reorienting if we're right on top of our character Vector2 lookAtVector = lookAtTarget - transform.position; if (lookAtVector.magnitude > GetComponent <CapsuleCollider2D>().size.x) { // We might normally use the code below in a 3D game but... // transform.LookAt(LookAtTarget); makes z face the target, therefore doesn't work in 2D transform.right = lookAtTarget - transform.position; } Vector3 moveVector = inputVector * playerSpeed * Time.deltaTime; int directHitCount = GetComponent <CapsuleCollider2D>().Cast(inputVector, directHits); if (directHitCount > 0) { RaycastHit2D directHit = directHits[0]; if (moveVector.magnitude >= directHit.distance) { float diameter = GetComponent <CapsuleCollider2D>().size.x; float radius = diameter / 2.0f; Vector2 positionAtWall = directHit.point + directHit.normal * radius; float wallBounceDistance = 0.001f; positionAtWall += (directHit.normal * wallBounceDistance); Vector2 previousPosition = transform.position; float distanceSoFar = (positionAtWall - previousPosition).magnitude; DebugUtil.DrawCircle(transform.position + moveVector, radius, Color.red); Vector2 wallTangent = Vector3.Cross(Vector3.forward, directHit.normal); float remainingDistance = moveVector.magnitude - distanceSoFar; float dotForSign = Vector3.Dot(wallTangent, moveVector); Vector2 directionalWallTangent = (wallTangent * dotForSign).normalized; Vector2 finalTangentOffset = directionalWallTangent * remainingDistance; int tangentHitCount = Physics2D.CapsuleCast(positionAtWall, GetComponent <CapsuleCollider2D>().size, CapsuleDirection2D.Horizontal, 0, directionalWallTangent, obstructionsToPlayer, tangentHits); if (tangentHitCount > 0) { RaycastHit2D tangentHit = tangentHits[0]; if (remainingDistance >= tangentHit.distance) { DebugUtil.DrawCircle(positionAtWall + finalTangentOffset, radius, Color.magenta); transform.position = tangentHit.point + tangentHit.normal * radius; return; } } Debug.DrawLine(positionAtWall, positionAtWall + directionalWallTangent); transform.position = positionAtWall + finalTangentOffset; return; } } transform.position += moveVector; }
void FixedUpdate() { _cancelMove = false; var colliders = GetComponentsInChildren <Collider2D>(); var currentPos = (Vector2)gameObject.transform.position; var currentAngle = gameObject.transform.rotation.eulerAngles.z; var timedDirection = _direction * moveSpeed * Time.fixedDeltaTime; var nextPos = currentPos + timedDirection; var hitColliders = new List <Collider2D>(); bool _hitHorizontally = false; bool _hitVertically = false; RaycastHit2D closestHorizontalHit = new RaycastHit2D(); RaycastHit2D closestVerticalHit = new RaycastHit2D(); foreach (var col in colliders) { RaycastHit2D bestHit = new RaycastHit2D(); if (typeof(BoxCollider2D) == col.GetType()) { bestHit = Physics2D.BoxCast(currentPos, col.bounds.size, currentAngle, timedDirection.normalized, timedDirection.magnitude, collisionMask); Debug.DrawLine(currentPos, nextPos, Color.red); } else if (typeof(CircleCollider2D) == col.GetType()) { var circleCol = (CircleCollider2D)col; bestHit = Physics2D.CircleCast(currentPos, circleCol.radius, timedDirection.normalized, timedDirection.magnitude, collisionMask); Debug.DrawLine(currentPos, nextPos, Color.red); Debug.DrawLine(currentPos, bestHit.point, Color.green); } else if (typeof(CapsuleCollider2D) == col.GetType()) { var capsuleCol = (CapsuleCollider2D)col; bestHit = Physics2D.CapsuleCast(currentPos, capsuleCol.size, capsuleCol.direction, currentAngle, timedDirection.normalized, timedDirection.magnitude, collisionMask); Debug.DrawLine(currentPos, nextPos, Color.red); } else if (typeof(PolygonCollider2D) == col.GetType()) { var polygonCol = (PolygonCollider2D)col; var closest = Mathf.Infinity; RaycastHit2D hit = new RaycastHit2D(); foreach (var point in polygonCol.points) { hit = Physics2D.Raycast(point, timedDirection.normalized, timedDirection.magnitude, collisionMask); Debug.DrawLine(currentPos, nextPos, Color.red); if (hit.collider != null && hit.distance < closest) { bestHit = hit; closest = hit.distance; break; } } } if (bestHit.collider != null) { if (!Array.Exists(colliders, x => x == bestHit.collider)) { if (!hitColliders.Contains(bestHit.collider)) { hitColliders.Add(bestHit.collider); } SendMessageUpwards("OnPOCollisionEnter", new object[] { col, bestHit.collider, bestHit }, SendMessageOptions.DontRequireReceiver); bestHit.collider.gameObject.SendMessageUpwards("OnPOCollisionEnter", new object[] { bestHit.collider, col, bestHit }, SendMessageOptions.DontRequireReceiver); if (!bestHit.collider.isTrigger) { var vector = bestHit.point - currentPos; var angle = Vector2.Angle(vector, _direction); if (angle <= 120f) { _cancelMove = true; } var deltaX = Mathf.Abs(vector.x); var deltaY = Mathf.Abs(vector.y); if (deltaX > 0.01f) { if (closestHorizontalHit.collider == null || deltaX < Mathf.Abs((closestHorizontalHit.centroid - currentPos).x)) { closestHorizontalHit = bestHit; } _hitHorizontally = true; } if (deltaY > 0.01f) { if (closestVerticalHit.collider == null || deltaY < Mathf.Abs((closestVerticalHit.centroid - currentPos).y)) { closestVerticalHit = bestHit; } _hitVertically = true; } } } } } foreach (var t in _touching) { if (!hitColliders.Contains(t)) { SendMessage("OnPOCollisionLeave", new object[] { t }, SendMessageOptions.DontRequireReceiver); } } _touching = hitColliders; if (!_cancelMove) { gameObject.transform.position = nextPos; } else { Vector2 newPos = Vector2.zero; var hOrigin = closestHorizontalHit.point - timedDirection; var vOrigin = closestVerticalHit.point - timedDirection; var deltaX = hOrigin - currentPos; var deltaY = vOrigin - currentPos; //var newX = (closestHorizontalHit.point - deltaX).x - 0.01f * Mathf.Sign(timedDirection.x); //var newY = (closestVerticalHit.point - deltaY).y - 0.01f * Mathf.Sign(timedDirection.y); var newX = closestHorizontalHit.centroid.x; var newY = closestVerticalHit.centroid.y; if (_hitHorizontally && _hitVertically) { newPos = new Vector2(newX, newY); } else if (_hitHorizontally) { newPos = new Vector2(newX, nextPos.y); } else if (_hitVertically) { newPos = new Vector2(nextPos.x, newY); } else { // Hit to close, don't move newPos = currentPos; gameObject.transform.position = (Vector3)newPos; return; } gameObject.transform.position = (Vector3)newPos; } }