Ignorer les collisions avec certains objets dans certains contextes

14

Je fais un jeu de course avec des voitures dans Unity. La voiture a un boost boost / nitro. Pendant le boost, je ne voudrais pas être dévié lors d'une collision avec des zombies, mais je veux être dévié lors d'une collision avec des murs.

D'un autre côté, je ne veux pas ignorer la collision avec des zombies, car je veux toujours les frapper à l'impact.

Comment dois-je gérer cela? Fondamentalement, ce que je veux, c'est que la voiture ne tourne pas lorsqu'elle entre en collision avec certains objets.

Paul Manta
la source

Réponses:

7

Pensez à manipuler vos couches lors de l'exécution.

Activation / désactivation des collisions pour certains objets avec des calques entiers

Physics.IgnoreCollision et Physics.IgnoreLayerCollision vous permettent de désactiver les collisions entre deux collisionneurs et entre deux couches, respectivement.

Si vous souhaitez exclure un collisionneur spécifique des collisions, il n'y a aucun moyen intégré de le faire. Si vous utilisez des corps rigides non cinématiques avec des collisionneurs non déclencheurs, il y aura toujours une réponse même si vous essayez de filtrer les réponses par balise.

La façon dont nous avons accompli cela sur notre projet était de créer une couche nommée "Void". Le néant n'entre en collision avec rien du tout.

Vous pouvez maintenant désactiver temporairement la collision d'un collisionneur en définissant son calque sur "Void" et le réactiver en restaurant son ancien calque.

Voici l'essentiel:

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;
}

Nous l'avons fait spécifiquement parce que l'activation et la désactivation des collisionneurs qui étaient des enfants de corps rigides peuvent vraiment gâcher les choses dans certaines circonstances. Vous ne pouvez donc pas désactiver de manière fiable une partie d'un collisionneur à corps rigide composé, mais vous pouvez échanger de manière fiable autour de la couche de l'une des parties du collisionneur composé.

Maintenant votre situation spécifique

Pour réduire l'impact de la collision de zombies sur votre voiture, envisagez de faire des déclencheurs cinématiques rigides de vos zombies, ou de rendre leur masse très très petite (comme float.Epsilon), de sorte que l'impact n'a aucun effet sur l'élan de la voiture. À l'impact, vous pouvez également effectuer ce changement de couche, de sorte que les collisions ultérieures ne soient pas déclenchées, même si la première applique une force négligeable à la carrosserie.

Vous pouvez même les passer à une couche qui n'entre pas en collision avec la voiture.

Vous pouvez également mettre un autre collisionneur sur des zombies qui s'activent lors d'un survol. De cette façon, vous pouvez simuler les forces d'impact OnTriggerEnter. Vous ne pouvez pas être aussi précis avec cela, mais vous pouvez approximer où les normales de contact ont été assez bien pour jeter le zombie dans un endroit amusant.

Vous devez vous demander:

  • Est-ce que je veux pouvoir renverser les zombies renversés avec ma voiture, ou devraient-ils simplement jouer une animation de mort?

  • Est-ce que je me soucie si la vitesse et la vitesse angulaire de la voiture sont affectées de manière plus petite en frappant des zombies?

michael.bartnett
la source
1

Appelez Physics.IgnoreCollision sur tous les zombies, en passant la fonction objet joueur aussi, lorsque la voiture commence à booster. Cela empêchera Unity de réagir aux collisions entre le joueur et les zombies. Lorsque la voiture a fini de booster, appelez à Physics.IgnoreCollisionnouveau pour chaque zombie, en lui passant l'objet joueur et falsepour que la réponse à la collision recommence.

Wackidev
la source
Mais cela signifierait qu'ils ne se heurteront à rien d'autre non plus.
Paul Manta
Je ferai d'autres recherches. La seule chose à laquelle je peux penser est: peut-être pouvez-vous ignorer la collision en renvoyant false depuis OnCollisionEnter?
Wackidev
@Wackidev Ce n'est pas le cas.
Rhys van der Waerden
@Paul J'ai édité ma réponse.
Wackidev
0

Je suppose que vous pouvez vérifier les noms des objets, ou ajouter une valeur de nom aux classes d'objets, puis vérifier cela?

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");                
        }
    }
}

Ensuite, ayez simplement une autre variable que vous pouvez utiliser pour vérifier le renforcement et l'ajouter aux contrôles.

EDIT: a ajouté cette variable dans.

Lewis
la source
Il sait comment être averti des collisions; il ne veut tout simplement pas que des mesures soient prises en conséquence. Il souhaite désactiver la réponse de collision intégrée dans certains cas.
Wackidev
Sûrement, que se passe-t-il lorsque la collision se déclenche entre les crochets? Je n'ai jamais utilisé l'unité auparavant, donc je ne sais pas, mais dans cocos2d, et XNA c'est fait comme ça.
Lewis
En fait, Unity gère les collisions lui-même via PhysX. OnCollisionEnter n'est qu'une méthode de notification; il n'est pas conçu pour gérer la réponse de collision réelle.
Wackidev
0

Je suppose que vous utilisez le moteur physique pour faire la «déviation» automatiquement en fonction de la forme / masse lorsque les choses entrent en collision? si tel est le cas, changez la masse de vos zombies à une valeur très minimale et ils n'affecteront pas la voiture.

ADB
la source
0

Il existe deux classes de réponses ici:

  1. Ignorer ou désactiver les collisions
    • Ces solutions ne résoudront pas le problème, il veut que les zombies volent lorsqu'ils sont touchés.
  2. Modification de la masse:
    • C'est une bonne approche. N'oubliez pas de modifier également l'inertie en conséquence.
      • Vous pouvez également modifier la masse et l'inertie des voitures lors de la suralimentation (nous le faisons pour réduire l'impact de tous les objets non cinématiques sur une voiture lors de la suralimentation)
      • Cela ne devrait pas affecter la route ou les murs en supposant qu'ils sont cinématiques.

J'espère que cela t'aides!

dwuLive
la source
Deux des réponses existantes d'il y a six ans recommandent déjà l'approche de masse que vous proposez ici. Y a-t-il une nouvelle stratégie que vous souhaitez ajouter?
DMGregory
Je m'excuse, je ne suis pas encore en mesure de voter et je voulais m'assurer que Paul Manta n'était pas égaré.
dwuLive