- Home /
Question by
Ovicior · May 10, 2016 at 06:00 AM ·
c#raycast2d game2d-platformerraycasthit2d
One 2D Raycast Being Weird While Others Work
I've been making a raycast system for a 2D platformer, since it'll feel better than a rigidbody. It has been working fine so far, with vertical collision, except for one issue. A single ray seems to insist on ignoring the colliders and pushing through. The others do not do this. Can anyone help?
Image of problem: https://i.gyazo.com/3348630296886ffc4781eceeb97ffbd2.gif
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(BoxCollider2D))]
public class Controller2D : MonoBehaviour
{
public LayerMask collisionMask;
const float skinWidth = .015f;
public int horizontalRayCount = 4;
public int verticalRayCount = 4;
float horizontalRaySpacing;
float verticalRaySpacing;
BoxCollider2D collider;
RaycastOrigins raycastOrigins;
void Start()
{
collider = GetComponent<BoxCollider2D>();
CalculateRaySpacing();
}
public void Move(Vector3 velocity)
{
UpdateRaycastOrigins();
if (velocity.x != 0)
{
HorizontalCollisions(ref velocity);
}
if (velocity.y != 0)
{
VerticalCollisions(ref velocity);
}
transform.Translate(velocity);
}
void HorizontalCollisions(ref Vector3 velocity)
{
float directionX = Mathf.Sign(velocity.x);
float rayLength = Mathf.Abs(velocity.x) + skinWidth;
for (int i = 0; i < horizontalRayCount; i++)
{
Vector2 rayOrigin = (directionX == -1) ? raycastOrigins.bottomLeft : raycastOrigins.bottomRight;
rayOrigin += Vector2.up * (horizontalRaySpacing * i);
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);
Debug.DrawRay(rayOrigin, Vector2.right * directionX * rayLength, Color.red);
if (hit)
{
velocity.x = (hit.distance - skinWidth) * directionX;
rayLength = hit.distance;
}
}
}
void VerticalCollisions(ref Vector3 velocity)
{
float directionY = Mathf.Sign(velocity.y);
float rayLength = Mathf.Abs(velocity.y) + skinWidth;
for (int i = 0; i < verticalRayCount; i++)
{
Vector2 rayOrigin = (directionY == -1) ? raycastOrigins.bottomLeft : raycastOrigins.topLeft;
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength, Color.red);
if (hit)
{
velocity.y = (hit.distance - skinWidth) * directionY;
rayLength = hit.distance;
}
}
}
void UpdateRaycastOrigins()
{
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
raycastOrigins.bottomLeft = new Vector2(bounds.min.x, bounds.min.y);
raycastOrigins.bottomRight = new Vector2(bounds.max.x, bounds.min.y);
raycastOrigins.topLeft = new Vector2(bounds.min.x, bounds.max.y);
raycastOrigins.topRight = new Vector2(bounds.max.x, bounds.max.y);
}
void CalculateRaySpacing()
{
Bounds bounds = collider.bounds;
bounds.Expand(skinWidth * -2);
horizontalRayCount = Mathf.Clamp(horizontalRayCount, 2, int.MaxValue);
verticalRayCount = Mathf.Clamp(verticalRayCount, 2, int.MaxValue);
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
}
struct RaycastOrigins
{
public Vector2 topLeft, topRight;
public Vector2 bottomLeft, bottomRight;
}
}
Comment
Your answer
Follow this Question
Related Questions
Flip Player, Not the Player's Child. 3 Answers
Use 2D Effectors with Raycast Collision Method 0 Answers
How can I find gameObject child. 0 Answers
Raycasting in 2D is not working 0 Answers