You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
3.9 KiB
C#
94 lines
3.9 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(BoxCollider))]
|
|
public class MoveController : MonoBehaviour
|
|
{
|
|
public LayerMask collisionMask;
|
|
public const float skinWidth = 0.015f;
|
|
public int horizontalRayCount = 4;
|
|
public int verticalRayCount = 4;
|
|
|
|
new private BoxCollider collider;
|
|
private RaycastOrigins raycastOrigins;
|
|
private float horizontalRaySpacing;
|
|
private float verticalRaySpacing;
|
|
|
|
void Start() {
|
|
collider = GetComponent<BoxCollider>();
|
|
CalculateRaySpacing();
|
|
}
|
|
|
|
public void Move(Vector3 velocity) {
|
|
UpdateRaycastOrigins();
|
|
VerticalCollisions(ref velocity);
|
|
transform.Translate(velocity);
|
|
}
|
|
|
|
private void VerticalCollisions(ref Vector3 velocity) {
|
|
float directionY = Mathf.Sign(velocity.y);
|
|
float rayLength = Mathf.Abs(velocity.y) + skinWidth;
|
|
|
|
// bottom face
|
|
for (int i = 0; i < verticalRayCount; i++) {
|
|
for (int j = 0; j < verticalRayCount; j++) {
|
|
Vector3 rayOrigin = (directionY == -1) ? raycastOrigins.bottomFrontLeft : raycastOrigins.topFrontLeft;
|
|
rayOrigin += Vector3.right * (verticalRaySpacing * i + velocity.x);
|
|
RaycastHit[] hits = Physics.RaycastAll(rayOrigin, Vector3.up * directionY, rayLength, collisionMask);
|
|
|
|
if (hits.Length > 0) {
|
|
float minHitDist = 0f;
|
|
foreach(RaycastHit hit in hits) {
|
|
if (hit.distance > minHitDist) {
|
|
minHitDist = hit.distance;
|
|
}
|
|
}
|
|
velocity.y = (minHitDist - skinWidth) * directionY;
|
|
rayLength = minHitDist;
|
|
Debug.DrawRay(raycastOrigins.bottomFrontLeft + Vector3.right * verticalRaySpacing * i - Vector3.back * verticalRaySpacing * j, Vector3.down * 0.25f, Color.red);
|
|
} else {
|
|
Debug.DrawRay(raycastOrigins.bottomFrontLeft + Vector3.right * verticalRaySpacing * i - Vector3.back * verticalRaySpacing * j, Vector3.down * 0.25f, Color.green);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateRaycastOrigins() {
|
|
Bounds bounds = collider.bounds;
|
|
bounds.Expand(skinWidth * -2);
|
|
|
|
raycastOrigins.bottomFrontLeft = new Vector3(bounds.min.x, bounds.min.y, bounds.min.z); // 0 0 0
|
|
raycastOrigins.bottomBackLeft = new Vector3(bounds.min.x, bounds.min.y, bounds.max.z); // 0 0 1
|
|
raycastOrigins.topFrontLeft = new Vector3(bounds.min.x, bounds.max.y, bounds.min.z); // 0 1 0
|
|
raycastOrigins.topBackLeft = new Vector3(bounds.min.x, bounds.max.y, bounds.max.z); // 0 1 1
|
|
|
|
raycastOrigins.bottomFrontRight = new Vector3(bounds.max.x, bounds.min.y, bounds.min.z); // 1 0 0
|
|
raycastOrigins.bottomBackRight = new Vector3(bounds.max.x, bounds.min.y, bounds.max.z); // 1 0 1
|
|
raycastOrigins.topFrontRight = new Vector3(bounds.max.x, bounds.max.y, bounds.min.z); // 1 1 0
|
|
raycastOrigins.topBackRight = new Vector3(bounds.max.x, bounds.max.y, bounds.max.z); // 1 1 1
|
|
}
|
|
|
|
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 Vector3 topBackLeft;
|
|
public Vector3 topBackRight;
|
|
public Vector3 topFrontLeft;
|
|
public Vector3 topFrontRight;
|
|
public Vector3 bottomBackLeft;
|
|
public Vector3 bottomBackRight;
|
|
public Vector3 bottomFrontLeft;
|
|
public Vector3 bottomFrontRight;
|
|
}
|
|
}
|