Ignorar colisões com alguns objetos em determinados contextos

14

Estou fazendo um jogo de corrida com carros no Unity. O carro tem um impulso / nitro. Ao aumentar, eu não gostaria de ser desviado ao colidir com zumbis, mas quero ser desviado ao colidir com paredes.

Por outro lado, não quero ignorar a colisão com zumbis, porque ainda quero atingi-los no impacto.

Como devo lidar com isso? Basicamente, o que eu quero é que o carro não gire ao colidir com certos objetos.

Paul Manta
fonte

Respostas:

7

Considere manipular suas camadas em tempo de execução.

Ativando / desativando colisões para determinados objetos com camadas inteiras

Physics.IgnoreCollision e Physics.IgnoreLayerCollision permitem desativar colisões entre dois colididores e entre duas camadas, respectivamente.

Se você deseja excluir um colisor específico das colisões, não há como criar isso. Se você estiver usando corpos rígidos não cinemáticos com coletores sem gatilho, sempre haverá uma resposta, mesmo se você tentar filtrar as respostas por tag.

A maneira como realizamos isso em nosso projeto foi criar uma camada chamada "Vazio". O vácuo não colide com nada.

Agora você pode desativar temporariamente a colisão de um colisor, definindo sua camada como "Vazio" e reativá-lo restaurando sua camada antiga.

Aqui está a essência:

int oldLayer = -1;
int voidLayer;

void Start()
{
    voidLayer = LayerMask.NameToLayer("Void");
}

void DisableCollider(Collider col)
{
    oldLayer = col.gameObject.layer;
    col.gameObject.layer = voidLayer;
}

void EnableCollider(Collider col)
{
    col.gameObject.layer = oldLayer;
}

Fizemos isso especificamente porque habilitar e desabilitar colisores filhos de corpos rígidos pode realmente estragar tudo em algumas circunstâncias. Portanto, você não pode desativar com segurança parte de um colisor de corpo rígido composto, mas é possível alternar com segurança a camada de uma das partes do colisor composto.

Agora sua situação específica

Para reduzir o impacto que a colisão de zumbis causa no seu carro, considere fazer com que os corpos rígidos cinemáticos dos zumbis sejam acionados ou diminua sua massa muito, muito pequena (como o float.Epsilon), para que o impacto tenha efeito nulo no momento do carro. No impacto, você também pode fazer essa troca de camada, para que as colisões subsequentes não sejam acionadas, mesmo que a primeira aplique uma força desprezível à carroceria do carro.

Você pode até trocá-los para uma camada que simplesmente não colide com o carro.

Você também pode colocar outro colisor nos zumbis que são ativados no atropelamento. Dessa forma, você pode fingir que o OnTriggerEnter é forçado a impactar. Você não pode ser tão preciso com isso, mas pode aproximar-se de onde os normais de contato podem ter sido bons o suficiente para jogar o zumbi em algum lugar divertido.

Você deve se perguntar:

  • Eu quero ser capaz de nocautear os zumbis atropelados com o meu carro, ou eles devem apenas tocar uma animação da morte?

  • Eu me importo se a velocidade do carro e a velocidade angular são afetadas de maneiras menores ao atingir zumbis?

michael.bartnett
fonte
1

Chame Physics.IgnoreCollision em todos os zumbis, passando a função que o objeto do jogador também, quando o carro começar a acelerar. Isso fará com que o Unity não reaja a colisões entre o jogador e os zumbis. Quando o carro terminar de acelerar, chame Physics.IgnoreCollisionnovamente cada zumbi, passando o objeto do jogador e falsefazendo com que a resposta à colisão comece novamente.

Wackidev
fonte
Mas isso significaria que eles também não colidirão com mais nada.
Paul Manta
Vou fazer mais algumas pesquisas. A única coisa em que consigo pensar é: talvez você possa ignorar a colisão retornando false de OnCollisionEnter?
Wackidev 02/07
@Wackidev Este não é o caso.
Rhys van der Waerden
@ Paul Eu editei minha resposta.
Wackidev 03/07/2012
0

Suponho que você possa verificar os nomes dos objetos ou adicionar um valor de nome às classes de objetos e verificar isso?

bool boosting = false; //need a trigger in the game to set this to true.

function OnCollisionEnter(theCollision : Collision)
{   
    if (boosting == true)
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit during boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit during boost");            
        }
    }
    else 
    {
        if(theCollision.gameObject.name == "Zombie")
        {
              Debug.Log("Zombie hit not in boost");              
        }
        else if(theCollision.gameObject.name == "Wall")
        {
              Debug.Log("Wall hit not in boost");                
        }
    }
}

Depois, basta ter outra variável que você pode usar para verificar o aumento e adicionar isso às verificações.

EDIT: adicionada esta variável em.

Lewis
fonte
Ele sabe como ser notificado de colisões; ele simplesmente não quer que nenhuma ação seja tomada como resultado. Ele deseja desativar a resposta de colisão interna em certos casos.
Wackidev 02/07
Certamente, o que acontece quando a colisão é acionada vai entre os colchetes? Eu não usei a unidade antes, então não sei, mas no cocos2d, e o XNA é feito assim.
Lewis
Na verdade, o Unity lida com as colisões por meio do PhysX. OnCollisionEnter é apenas um método de notificação; não foi projetado para lidar com a resposta de colisão real.
Wackidev 03/07/2012
0

Suponho que você esteja usando o mecanismo de física para fazer o 'desvio' automaticamente com base na forma / massa quando as coisas colidem. se for esse o caso, altere a massa de seus zumbis para um valor muito mínimo e eles não afetarão o carro.

ADB
fonte
0

Existem duas classes de respostas aqui:

  1. Ignorando ou desativando colisões
    • Essas soluções não resolverão o problema, ele quer que os zumbis voem quando atingidos.
  2. Mudança de massa:
    • Essa é uma boa abordagem. Não se esqueça de alterar também a inércia de acordo.
      • Como alternativa, você pode alterar a massa e a inércia dos carros ao impulsionar (fazemos isso para reduzir o impacto de todos os objetos não cinemáticos em um carro ao impulsionar)
      • Isso não deve afetar a estrada ou paredes, supondo que sejam cinemáticas.

Espero que isto ajude!

dwuLive
fonte
Duas das respostas existentes de seis anos atrás já recomendam a abordagem baseada em massa que você está sugerindo aqui. Há alguma nova estratégia que você deseja adicionar?
DMGregory
Peço desculpas, ainda não sou capaz de votar e queria garantir que Paul Manta não se desviasse.
precisa saber é o seguinte