Quel type de comportement ou de logique de pilotage puis-je utiliser pour que les mobiles en entourent un autre?

10

J'utilise la recherche de chemin dans mon jeu pour diriger une foule vers un autre joueur (pour les poursuivre). Cela fonctionne pour les faire dépasser le joueur, mais je veux qu'ils s'arrêtent légèrement avant leur destination (donc choisir l'avant-dernier nœud fonctionne très bien).

Cependant, lorsque plusieurs mobs poursuivent le mobile, ils "s'empilent parfois les uns sur les autres". Quelle est la meilleure façon d'éviter cela? Je ne veux pas traiter les foules comme opaques et bloquées (parce qu'elles ne le sont pas, vous pouvez les traverser) mais je veux que les foules aient un certain sens de la structure.

Exemple:

Imaginez que chaque serpent se guide vers moi et devrait entourer "Setsuna". Remarquez comment les deux serpents ont choisi de me tailler? Ce n'est pas une exigence stricte; même être légèrement décalé est correct. Mais ils devraient «entourer» Setsuna.

entrez la description de l'image ici

Vaughan Hilts
la source
1
L'empilement est-il uniquement une préoccupation à destination ou également pendant le transport? Je devine ce dernier.
SpartanDonut du
C'est ce dernier, @SpartanDonut
Vaughan Hilts
@KromStern J'ai ajouté une photo, j'espère que cela vous aidera.
Vaughan Hilts

Réponses:

15

Donnez à vos agents une faible "charge électrostatique" pour les faire se repousser, selon la loi de Coulomb .

En supposant pour simplifier que les mobs devraient se repousser avec une force équivalente, il devrait suffire d'appliquer une force entre chaque paire de mobs avec une magnitude some_constant / distance^2, où se some_constanttrouve une force de répulsion configurable et distancela distance qui les sépare.

Les forces de répulsion tombent alors au carré de la distance.

Nature of Code en a un excellent exemple (avec une démonstration en direct) ici . Cela ressemble à ceci:

comportements combinés de suivi et séparés

Faire correspondre chaque élément les uns aux autres est une opération quadratique ( O(n^2)). Si vous avez vraiment beaucoup d' agents, vous souhaiterez peut-être optimiser les calculs de force avec une approximation de Barnes-Hut , ce qui le ramène à log-linear ( O(n log n)) mais nécessite un quadtree .

Anko
la source
Excellent lien, Anko. Très appréciée! Je vais certainement devoir lire ce site en entier.
Vaughan Hilts
Starcraft (1, au moins) fait quelque chose de similaire avec ses unités volantes. Mais il ne le fait que lorsqu'ils cessent de bouger, c'est-à-dire lorsqu'ils se déplacent, ils s'agglutinent les uns sur les autres (s'ignorent complètement comme des obstacles), mais lorsqu'ils s'arrêtent, ils commencent tous à s'étendre de ce qui semble être le centre local d'une zone régulière (carré / cercle, probablement) qui les englobe. Cela ne semble pas aussi joli que l'exemple dans la réponse, mais il utilise probablement moins de ressources CPU, et il est peut-être plus facile de coder aussi ...
Shivan Dragon
@ShivanDragon SC2 présente le même comportement, ils convergent tous vers la destination dans une foule, puis s'espacent pour des looks réalistes et esthétiques (de sorte que leurs pièces ne se coupent pas).
Kroltan
2
Une sorte de force de répulsion peut être une bonne idée, mais les détails sont délicats. J'ai expérimenté ces derniers dans un RTS sur le thème de l'espace et je recommande de ne pas suivre la physique de trop près et plutôt de la modéliser pour qu'elle se comporte bien. Quelques observations: 1) Comme il ne s'agit pas d'une simulation physique, je n'appliquerais la force que sur de courtes distances. 2) Cela ne peut pas empêcher les corps finis de se chevaucher 3) Le potentiel dur provoque facilement des erreurs numériques, telles que des particules réfractées à des vitesses élevées. 4) Une fois que vous avez un nombre important de particules et que la pression augmente au milieu, les choses ont tendance à devenir laides.
CodesInChaos
1

Mon approche est similaire à celle de @ Anko, mais basée sur le travail de Millington et Funge de Artificial Intelligence for Games .

Voici à quoi ressemblerait un comportement de séparation, mais vous devez tenir compte du fait que cette vitesse doit être calculée avec la vitesse de l'agent dans sa fonction de mise à jour.

public Vector3 GetSeparationVel (float threshold, float decayCoefficient)
{
    threshold = threshold * threshold;
    Vector3 separationVelocity = Vector3.Zero;
    for (int i = 0; i < enemies.Length; i++) {
        if (enemies[i] == this) {
            continue;
        }
        Vector3 direction = this.position - enemies[i].position;
        float distance = direction.LengthSquared();
        float strenght = 0.0f;
        if (distance < (threshold)) {
            strenght = Math.Min(decayCoefficient / distance, this.maxAccel);
            direction.Normalize();
            separationVelocity += strenght * direction;
        }
    }
}
reefaktor
la source