J'essaie de créer un effet similaire à celui de Mario Galaxy ou de Geometry Wars 3 où lorsque le joueur contourne la "planète", la gravité semble s'ajuster et ils ne tombent pas du bord de l'objet comme ils le feraient si la gravité a été fixé dans une seule direction.
(source: gameskinny.com )
J'ai réussi à implémenter quelque chose de proche de ce que je recherche en utilisant une approche où l'objet qui devrait avoir la gravité attire d'autres corps rigides vers lui, mais en utilisant le moteur physique intégré pour Unity, en appliquant le mouvement avec AddForce et autres, Je n'arrivais pas à faire en sorte que le mouvement se sente bien. Je ne pouvais pas faire bouger le joueur assez rapidement sans que le joueur ne commence à voler de la surface de l'objet et je ne pouvais pas trouver un bon équilibre de force et de gravité appliquées pour s'adapter à cela. Mon implémentation actuelle est une adaptation de ce qui a été trouvé ici
J'ai l'impression que la solution utiliserait probablement encore la physique pour mettre le joueur à la terre sur l'objet s'il devait quitter la surface, mais une fois que le joueur a été mis à la terre, il y aurait un moyen de mettre le joueur à la surface et de désactiver la physique et contrôler le joueur par d'autres moyens mais je ne suis vraiment pas sûr.
Quel type d'approche dois-je adopter pour accrocher le lecteur à la surface d'objets? Notez que la solution devrait fonctionner dans l'espace 3D (par opposition à 2D) et devrait pouvoir être implémentée à l'aide de la version gratuite d'Unity.
Réponses:
J'ai réussi à accomplir ce dont j'avais besoin, principalement avec l'aide de ce billet de blog pour la pièce du puzzle en surface et j'ai trouvé mes propres idées pour le mouvement des joueurs et la caméra.
Accrochage du lecteur à la surface d'un objet
La configuration de base se compose d'une grande sphère (le monde) et d'une sphère plus petite (le joueur), toutes deux avec des collisionneurs de sphères qui leur sont attachés.
La majeure partie du travail effectué se faisait selon les deux méthodes suivantes:
le
Vector3 movementDirection
paramètre est juste tel qu'il semble, la direction dans laquelle nous allons déplacer notre lecteur dans cette image, et le calcul de ce vecteur, bien que relativement simple dans cet exemple, était un peu difficile à comprendre au début. Plus à ce sujet plus tard, mais gardez à l'esprit qu'il s'agit d'un vecteur normalisé dans la direction dans laquelle le joueur déplace cette image.En progressant, la première chose que nous faisons est de vérifier si un rayon, provenant de la position future hypothétique dirigée vers le vecteur des joueurs vers le bas (-transform.up), frappe le monde en utilisant WorldLayerMask qui est une propriété LayerMask publique du script. Si vous souhaitez des collisions plus complexes ou plusieurs calques, vous devrez créer votre propre masque de calque. Si le raycast frappe avec succès quelque chose, hitInfo est utilisé pour récupérer le point normal et le point de coup pour calculer la nouvelle position et rotation du joueur qui devrait se trouver juste sur l'objet. Un décalage de la position du joueur peut être nécessaire en fonction de la taille et de l'origine de l'objet joueur en question.
Enfin, cela n'a vraiment été testé et ne fonctionne probablement bien que sur des objets simples tels que des sphères. Comme le suggère le billet de blog sur lequel j'ai basé ma solution, vous souhaiterez probablement effectuer plusieurs diffusions et les faire une moyenne pour votre position et votre rotation afin d'obtenir une transition beaucoup plus agréable lorsque vous vous déplacez sur un terrain plus complexe. Il peut également y avoir d'autres pièges auxquels je n'ai pas pensé à ce stade.
Caméra et mouvement
Une fois que le joueur collait à la surface de l'objet, la prochaine tâche à accomplir était le mouvement. J'avais à l'origine commencé par le mouvement par rapport au joueur, mais j'ai commencé à rencontrer des problèmes aux pôles de la sphère où les directions ont soudainement changé, ce qui a fait que mon joueur changeait rapidement de direction encore et encore ne me permettant jamais de passer les pôles. J'ai fini par faire bouger mes joueurs par rapport à la caméra.
Ce qui fonctionnait bien pour mes besoins était d'avoir une caméra qui suivait strictement le joueur uniquement en fonction de la position des joueurs. En conséquence, même si la caméra était techniquement en rotation, une pression vers le haut déplaçait toujours le lecteur vers le haut de l'écran, vers le bas vers le bas, etc. avec la gauche et la droite.
Pour ce faire, ce qui suit a été exécuté sur la caméra où l'objet cible était le joueur:
Enfin, pour déplacer le joueur, nous avons exploité la transformation de la caméra principale de sorte que nos commandes montent, descendent, etc. Et c'est ici que nous appelons UpdatePlayerTransform qui obtiendra notre position accrochée à l'objet monde.
Pour implémenter une caméra plus intéressante mais les commandes étant à peu près les mêmes que celles que nous avons ici, vous pouvez facilement implémenter une caméra qui n'est pas rendue ou juste un autre objet factice pour baser le mouvement, puis utiliser la caméra la plus intéressante pour rendre ce vous voulez que le jeu ressemble. Cela permettra de belles transitions de caméra lorsque vous contournerez des objets sans casser les commandes.
la source
Je pense que cette idée fonctionnera:
Conservez une copie côté CPU du maillage de la planète. Avoir des sommets maillés signifie également que vous avez des vecteurs normaux pour chaque point de la planète. Désactivez ensuite complètement la gravité pour toutes les entités, appliquant plutôt une force dans la direction exactement opposée d'un vecteur normal.
Maintenant, sur la base de quel point ce vecteur normal de la planète devrait-il être calculé?
La réponse la plus simple (qui, j'en suis sûr, fonctionnera bien) est de se rapprocher de la méthode de Newton : lorsque les objets apparaissent pour la première fois, vous connaissez toutes leurs positions initiales sur la planète. Utilisez cette position initiale pour déterminer le
up
vecteur de chaque objet . De toute évidence, la gravité sera dans la direction opposée (versdown
). Dans l'image suivante, avant d'appliquer la gravité, lancez un rayon de la nouvelle position de l'objet vers son anciendown
vecteur. Utilisez l'intersection de ce rayon avec la planète comme nouvelle référence pour déterminer leup
vecteur. Le rare cas où le rayon ne frappe rien signifie que quelque chose s'est horriblement mal passé et vous devriez ramener votre objet à l'endroit où il était dans l'image précédente.Notez également qu'en utilisant cette méthode, plus le joueur est originaire de la planète, plus l'approximation est mauvaise. Il est donc préférable d'utiliser quelque part autour des pieds de chaque joueur comme origine. Je suppose, mais je pense que l'utilisation des pieds comme origine entraînera également une manipulation et une navigation plus faciles du joueur.
Une dernière note: pour de meilleurs résultats, vous pouvez même faire ce qui suit: suivre le mouvement du joueur dans chaque image (par exemple en utilisant
current_position - last_position
). Ensuite, fixez-le demovement_vector
sorte que sa longueur vers l'objetup
soit nulle. Appelons ce nouveau vecteurreference_movement
. Déplacez le précédentreference_point
parreference_movement
et utilisez ce nouveau point comme origine du lancer de rayons. Après (et si) le rayon frappe la planète, déplacez-vousreference_point
vers ce point d' impact . Enfin, calculez le nouveauup
vecteur, à partir de ce nouveaureference_point
.Un pseudo code pour le résumer:
la source
Ce post pourrait être utile. Son essence est que vous n'utilisez pas les contrôleurs de personnage, mais créez le vôtre en utilisant le moteur physique. Ensuite, vous utilisez les normales détectées sous le lecteur pour les orienter vers la surface du maillage.
Voici un bon aperçu de la technique. Il y a beaucoup plus de ressources avec des termes de recherche Web comme "promenade d'unité sur des objets 3d mario galaxy".
Il y a aussi un projet de démonstration de l'unité 3.x qui avait un moteur qui marche, avec un soldat et un chien et dans l'une des scènes. Il a montré la marche sur des objets 3D de style Galaxy . C'est ce qu'on appelle le système de locomotion par runevision.
la source
Rotation
Consultez la réponse à cette question sur answers.unity3d.com (effectivement posée par moi-même). Citation:
Voici le code qu'il m'a proposé:
Appelez cela à chaque mise à jour, et vous devriez le faire fonctionner. (notez que le code est en UnityScript ).
Le même code en C # :
La gravité
Pour la gravité, vous pouvez utiliser ma "technique de physique des planètes", que j'ai décrite dans ma question, mais elle n'est pas vraiment optimisée. C'était juste quelque chose que j'avais en tête.
Je vous suggère de créer votre propre système pour la gravité.
Voici un tutoriel Youtube de Sebastian Lague . C'est une solution très efficace.
EDIT: À l'unité, allez dans Edition > Paramètres du projet > Physique et définissez toutes les valeurs de Gravity sur 0 (ou supprimez le Rigidbody de tous les objets), pour éviter que la gravité intégrée (qui tire simplement le joueur vers le bas) entre en conflit avec la solution personnalisée. (éteignez-le)
la source