Как определить сторону столкновения с коллайдером?
Всем привет! Делаю бесконечный "раннер", где игрок стоит на месте, а карта уже двигается на игрока, игрок может лишь двигаться влево и вправо. Хочу избегая триггеров заставить определять сторону столкновения с коллайдером. Например при попытке сдвинуться в сторону, то отскочить назад и, допустим, потерять здоровье, а если лобовое столкновение, то GameOver.
Пытался сделать через рейкаст, но он срабатывает как-то через раз, то есть то возвращает правильно, то возвращает Direction.None
public static class UnityGameUtils
{
public static Direction GetColliderHitDirection(GameObject gameObject, GameObject hitGameObject)
{
RaycastHit raycastHit;
Vector3 direction = (gameObject.transform.position - hitGameObject.transform.position).normalized;
Ray ray = new Ray(gameObject.transform.position, direction);
Debug.DrawRay(gameObject.transform.position, direction);
if(Physics.Raycast(ray, out raycastHit))
{
if(raycastHit.collider != null)
{
Vector3 raycastNormal = raycastHit.normal;
raycastNormal = raycastHit.transform.TransformDirection(raycastNormal);
if(raycastNormal == raycastHit.transform.up)
{
return Direction.Top;
}
if (raycastNormal == -raycastHit.transform.up)
{
return Direction.Bottom;
}
if (raycastNormal == raycastHit.transform.forward)
{
return Direction.Forward;
}
if (raycastNormal == -raycastHit.transform.forward)
{
return Direction.Back;
}
if (raycastNormal == raycastHit.transform.right)
{
return Direction.Right;
}
if (raycastNormal == -raycastHit.transform.right)
{
return Direction.Left;
}
}
}
return Direction.None;
}
}
PlayerMovementController:
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Barrier")
{
Direction hitDirection = UnityGameUtils.GetColliderHitDirection(this.gameObject, collision.gameObject);
if (hitDirection == Direction.Forward)
{
this.CanMove = false;
PlayerMovement.OnBarrierHit?.Invoke(this);
}
}
if (collision.gameObject.tag == "HighGround" || collision.gameObject.tag == "Barrier")
{
Direction hitDirection = UnityGameUtils.GetColliderHitDirection(this.gameObject, collision.gameObject);
if (hitDirection == Direction.Right || hitDirection == Direction.Left)
{
this.pointFinish = this.pointStart;
}
}
}
Ответы (1 шт):
Допустим ось x - это ось перемещения влево/вправо. Мы узнаём размеры нашего объекта по оси x и делим на 2 и делаем чуть меньше(необязательно). Теперь узнаём координаты нашего игрока с помощью transfowm.position.x и делаем две переменные: начало игрока и коней игрока по оси x , от первой отнимает ко второй прибавляем, ну теперь просто при столкновении сравниваем координаты объекта с которым столкнулись и эти две переменные. Как то так
public PlayerSizeX;
if(collision.gameObject.tag == "Barrier")
{
private float PSX = transform.position.x - PlPlayerSizeX/2 + 1f; //можно изменять 1f
private float PFX = transform.position.x + PlPlayerSizeX/2 - 1f; //можно изменять 1f
Direction hitDirection = UnityGameUtils.GetColliderHitDirection(this.gameObject, collision.gameObject);
if (transform.position.x > PSX && PFX > transform.position.x)
{
this.CanMove = false;
PlayerMovement.OnBarrierHit?.Invoke(this);
}
else
{
if(collision.gameObject.transform.position.x > transform.position.x)
{
// Толкаемся влево можно через addForce()
}
else
{
// Толкаемся вправо можно через addForce()
}
}
}
Я думаю это будет работать, Но это подойдет только, если ваш персонаж не вращается(направлен перпендикулярно оси x) и объекты двигаются к нему спереди или сзади