Рекомендуемый подход к нескольким коллайдерам
У меня есть некоторые трудности с тем, что, вероятно, очень глупо. У меня есть вражеский игровой объект, который в зависимости от того, где он попал (столкновение) - либо он, либо игра умирает. Я думаю, что самый простой способ описать это, используя классическую игру Super Mario Bros. в качестве примера.
Как вы все знаете, если игрок столкнется с врагом - игрок проиграет - ЕСЛИ он не прыгнет на голову врага, в этом случае враг должен умереть.
Моя первоначальная идея заключалась в создании двух коллайдеров на игровом объекте:
- Синяя рамка представляет BoxCollider2D - который при столкновении с ним приведет к проигрышу игрока (обратите внимание, что он немного ниже сверху)
- Зеленая граница представляет BoxCollider2D на дочернем игровом объекте - который при столкновении с ним приведет к смерти игрового объекта.
Ниже приведена упрощенная версия кода, который я использовал:
// Collider #1
public void OnCollisionEnter2D(Collision2D collision)
{
// Trigger 'Game-Over' logic
}
// Collider #2
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
Destroy(this.gameObject);
}
}
Этот вид работ, однако на мгновение после столкновения с Коллайдером № 1, Коллайдер № 2 также срабатывает - и пока враг уничтожен, игрок также проигрывает.
Я играл со значениями RigidBody2D, чтобы не дать игроку войти во 2-й коллайдер при ударе врага сверху - но, очевидно, с такой силой / скоростью, коллайдеры могут быть немного неточными (или, может быть, я просто делаю это неправильно?).
Я изучил RayCasts, но это кажется слишком сложным для чего-то, что мне кажется довольно тривиальным (наложение лучей на все четыре стороны и четыре вершины игрока - при условии, что у игрока есть коллайдер коробки).
На данный момент я прибег к "единому коллайдеру с простым фрагментом кода, который мне не нравится, и не всегда работает:
public void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
float yVelocity = collision.gameObject.transform.rigidbody2D.velocity.y;
if (yVelocity < 0)
{
Debug.Log("Enemy will lose..." + yVelocity);
Destroy(this.gameObject);
}
else
{
// Trigger 'Game-Over' logic
}
}
}
В настоящее время я работаю в режиме 2D, но решения для режима 3D (хотя, возможно, и более сложные, чем необходимо для моего вопроса) также будут рассмотрены.
Спасибо, парни.
3 ответа
Как разработчик игры, у вас всегда есть много способов решить проблему или создать игровой процесс. Прежде всего, я должен сказать, что вы должны сделать полигональный коллайдер 2d для ваших объектов и персонажей. просто столкновение картинок не очень хорошо, так как я вижу, что вы использовали коробчатые цилиндры в своей игре.
хорошим выбором может быть то, что вы присоединяете и опорожняете объект от своего игрока и устанавливаете его положение под ногами своего игрока и проверяете, вражеский удар, враг умирает, если враг ударит основного персонажа, игрок умирает.
другой выбор может быть, когда o объекты сталкиваются, проверяют положение 2 объектов. игрока выше, он убивает, иначе враг убивает игрока.
если вы думаете больше, вы найдете больше ответов. Вы должны исследовать различные пути и найти наиболее эффективные.
Я думаю, что будет легко отключить другой коллайдер, когда он сработает. Вы можете легко включить / отключить коллайдеры с collider.enabled = true;
или же collider.enabled = false;
// Collider #1
public void OnCollisionEnter2D(Collision2D collision)
{
// Trigger 'Game-Over' logic
// collider2.enabled = false;
}
// Collider #2
public void OnCollisionEnter2D(Collision2D collision)
{
// collider1.enabled = false;
if (collision.gameObject.tag == "Player")
{
Destroy(this.gameObject);
}
}
Таким образом, он будет довольно легким и простым в реализации.
Один из способов реализовать то, что вы хотите, - поместить каждый коллайдер в свой дочерний игровой объект и использовать метод IsTouching().
void OnTriggerEnter2D(Collider2D other){
if(GameObject.Find("Top Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
Destroy(transform.gameObject)
}
if(GameObject.Find("Bottom Trigger").GetComponent<BoxCollider2D>().IsTouching(other)){
Destroy(other.gameObject)
}
}