|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
// MoveController controls movement for 2D characters
|
|
|
|
|
[RequireComponent(typeof(BoxCollider2D))]
|
|
|
|
|
public class MoveController : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
const float skinWidth = 0.015f;
|
|
|
|
|
|
|
|
|
|
public int horizontalRayCount = 4;
|
|
|
|
|
public int verticalRayCount = 4;
|
|
|
|
|
public LayerMask collisionMask;
|
|
|
|
|
public CollisionInfo collisions;
|
|
|
|
|
|
|
|
|
|
private float horizontalRaySpacing;
|
|
|
|
|
private float verticalRaySpacing;
|
|
|
|
|
|
|
|
|
|
new BoxCollider2D collider;
|
|
|
|
|
RaycastOrigins raycastOrigins;
|
|
|
|
|
|
|
|
|
|
public bool isGrounded {
|
|
|
|
|
get => collisions.below;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Start() {
|
|
|
|
|
collider = GetComponent<BoxCollider2D>();
|
|
|
|
|
CalculateRaySpacing();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Move(Vector3 velocity) {
|
|
|
|
|
UpdateRaycastOrigins();
|
|
|
|
|
collisions.Reset();
|
|
|
|
|
|
|
|
|
|
if (velocity.x != 0) {
|
|
|
|
|
HorizontalCollisions(ref velocity);
|
|
|
|
|
}
|
|
|
|
|
if (velocity.y != 0) {
|
|
|
|
|
VerticalCollisions(ref velocity);
|
|
|
|
|
}
|
|
|
|
|
transform.Translate(velocity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void VerticalCollisions(ref Vector3 velocity) {
|
|
|
|
|
float directionY = Mathf.Sign(velocity.y); // -1 for down, 1 for up
|
|
|
|
|
float rayLength = Mathf.Abs(velocity.y) + skinWidth;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < verticalRayCount; i++) {
|
|
|
|
|
Vector2 rayOrigin = (directionY > 0) ? raycastOrigins.topLeft : raycastOrigins.bottomLeft;
|
|
|
|
|
rayOrigin += Vector2.right * (verticalRaySpacing * i + velocity.x);
|
|
|
|
|
|
|
|
|
|
Debug.DrawRay(rayOrigin, Vector2.up * directionY * rayLength, Color.red);
|
|
|
|
|
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.up * directionY, rayLength, collisionMask);
|
|
|
|
|
if (hit) {
|
|
|
|
|
if (directionY > 0) {
|
|
|
|
|
collisions.above = hit.collider;
|
|
|
|
|
} else {
|
|
|
|
|
collisions.below = hit.collider;
|
|
|
|
|
}
|
|
|
|
|
velocity.y = (hit.distance - skinWidth) * directionY;
|
|
|
|
|
rayLength = hit.distance;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void HorizontalCollisions(ref Vector3 velocity) {
|
|
|
|
|
float directionX = Mathf.Sign(velocity.x); // -1 for left, 1 for right
|
|
|
|
|
float rayLength = Mathf.Abs(velocity.x) + skinWidth;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < horizontalRayCount; i++) {
|
|
|
|
|
Vector2 rayOrigin = (directionX > 0) ? raycastOrigins.bottomRight : raycastOrigins.bottomLeft;
|
|
|
|
|
rayOrigin += Vector2.up * (horizontalRaySpacing * i);
|
|
|
|
|
|
|
|
|
|
Debug.DrawRay(rayOrigin, Vector2.right * directionX * rayLength, Color.red);
|
|
|
|
|
RaycastHit2D hit = Physics2D.Raycast(rayOrigin, Vector2.right * directionX, rayLength, collisionMask);
|
|
|
|
|
if (hit) {
|
|
|
|
|
if (directionX > 0) {
|
|
|
|
|
collisions.right = hit.collider;
|
|
|
|
|
} else {
|
|
|
|
|
collisions.left = hit.collider;
|
|
|
|
|
}
|
|
|
|
|
velocity.x = (hit.distance - skinWidth) * directionX;
|
|
|
|
|
rayLength = hit.distance;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UpdateRaycastOrigins() {
|
|
|
|
|
Bounds bounds = collider.bounds;
|
|
|
|
|
bounds.Expand(skinWidth * -2f);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
if (horizontalRayCount < 2) {
|
|
|
|
|
horizontalRayCount = 2;
|
|
|
|
|
}
|
|
|
|
|
if (verticalRayCount < 2) {
|
|
|
|
|
verticalRayCount = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
horizontalRaySpacing = bounds.size.y / (horizontalRayCount - 1);
|
|
|
|
|
verticalRaySpacing = bounds.size.x / (verticalRayCount - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct RaycastOrigins {
|
|
|
|
|
public Vector2 topLeft;
|
|
|
|
|
public Vector2 topRight;
|
|
|
|
|
public Vector2 bottomLeft;
|
|
|
|
|
public Vector2 bottomRight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct CollisionInfo {
|
|
|
|
|
public Collider2D above;
|
|
|
|
|
public Collider2D below;
|
|
|
|
|
public Collider2D left;
|
|
|
|
|
public Collider2D right;
|
|
|
|
|
|
|
|
|
|
public void Reset() {
|
|
|
|
|
above = null;
|
|
|
|
|
below = null;
|
|
|
|
|
left = null;
|
|
|
|
|
right = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|