Просто начните с Unity, так что наберитесь терпения :) Мы создаем игру, похожую на Zelda - сверху вниз, без физики / гравитации, тайловых карт для карты.Мы не хотим использовать динамические твердые тела из-за всей физики, стоящей за ним.
Карта тайлов имеет «Стены» с CompositeCollider2D и статическим жестким телом, наш игрок имеет CircleCollider2D и кинематическое твердое тело.И у игрока, и у стен есть физический материал с нулевым трением.
Каков наилучший способ обнаружения столкновений с кинематической рибибоди?У нас есть несколько концепций, таких как Physics2D.CircleCastAll, но в итоге наш игрок застрял в стенах или застрял в углах (игрок должен плавно двигаться за углом) или застрял в двух перекрывающихся коллайдерах.
ЛучшийРешение, которое мы придумали, заключается в следующем (и игрок все еще сталкивается с коллайдерами, но, по крайней мере, больше не застревает).
// MoveDirection is the movement input
movement = MoveDirection * Speed * Time.deltaTime;
List<RaycastHit2D> results = new List<RaycastHit2D>();
List<RaycastHit2D> resultsX = new List<RaycastHit2D>();
List<RaycastHit2D> resultsY = new List<RaycastHit2D>();
if (movement.x != 0)
{
actorCollider.Cast(new Vector2(movement.x, 0), filter, resultsX, movement.magnitude);
results.AddRange(resultsX);
}
if (movement.y != 0)
{
actorCollider.Cast(new Vector2(0, movement.y), filter, resultsY, movement.magnitude);
results.AddRange(resultsY);
}
foreach (RaycastHit2D hit in results)
{
Vector2 normal = hit.normal;
float projection = Vector2.Dot(movement, normal);
if (projection < 0)
{
if (hit.distance > 0)
{
projection += Mathf.Max(hit.distance - 0.01f, 0);
}
movement -= projection * normal;
}
}
// move player
newPosition = body.position + movement;
// make sure the player is positioned at pixel perfect positions
newPosition.x = (Mathf.Round(newPosition.x * 16) / 16);
newPosition.y = (Mathf.Round(newPosition.y * 16) / 16);
body.MovePosition(newPosition);
// this part moves the player back in case it is in a collider.
List<Collider2D> colliderList = new List<Collider2D>();
if (actorCollider.OverlapCollider(filter, colliderList) > 0)
{
foreach (Collider2D hit in colliderList)
{
var distance = hit.Distance(actorCollider);
body.MovePosition(body.position + (distance.normal * Mathf.Abs(distance.distance)));
}
}
Настройка игрока:
Настройка стен:
Почему-то это все еще кажется слишком сложным.Это лучший подход для обнаружения столкновений, или мы делаем это совершенно неправильно, и есть лучшие / более простые способы?Имейте в виду, что мы хотим как-то ходить по прямым углам и не застрять на них.И рядом друг с другом есть перекрывающиеся коллайдеры или коллайдеры.
Спасибо за ваше время!