Comment créer un objet déplaçable qui s'accroche aux obstacles sur le chemin?


8

J'apporte encore une autre question de glisser avec la souris (j'utilise Unity avec C #), mais avec un détail particulier moins commun: l'existence d'obstacles au milieu du chemin à travers lequel le glissement se produit (espace 3D, pas 2D) .

Laisse-moi expliquer. Supposons que j'ai un plan sur lequel je veux faire glisser un cube appelé "obj". C'est facile. Voici ma mise en œuvre simple pour cela:

void Update () {
  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  RaycastHit hit;
  if(Physics.Raycast(ray, out hit, 1000000))
  obj.transform.position = new Vector3(hit.point.x,0.25F,hit.point.z);
}

Ça marche. Cependant, supposons que j'ai également quelques autres cubes au-dessus de l'avion, qui sont les obstacles. De toute évidence, lorsque le joueur se déplace "obj" au-dessus de l'avion, ce mouvement doit être bloqué par les obstacles. Et puis, en entrant en collision avec les obstacles, "obj" ne devrait se déplacer que sur les côtés de cet obstacle. Si la souris est déplacée et que "obj" cesse d'entrer en collision avec des obstacles, le mouvement de style glisser libre reprend à nouveau.

objet traîné vers un obstacle et s'arrêtant à son bord, puis reprenant lorsque la traînée passe l'obstacle

Pour rendre le défi plus difficile, j'essaie de le faire sans utiliser de composants RigidBody aux obstacles (l'objet traîné peut l'avoir). Avez-vous des idées sur la manière la plus efficace d'y parvenir? Merci beaucoup!

EDIT: Les commentateurs ont attiré mon attention sur le fait que je devrais mentionner que les objets peuvent pivoter lors de la capture.

EDIT 2: Compte tenu de la difficulté de la formulation d'origine, j'ai changé la question permettant l'utilisation de composants Rigidbody au niveau des objets glissés. La solution ne peut tout simplement pas utiliser des composants Rigidbody aux obstacles.


Déplacez-vous des formes convexes arbitraires - sont-elles toujours à quatre côtés? Sont-ils toujours en 2D?
Steven

Puis-je connaître la raison pour laquelle vous n'utiliserez pas de Rigidbodies? Ils sont le moyen le plus simple de faire ce que vous voulez sans avoir à réimplémenter le code déjà disponible dans Unity.
EvilTak

@EvilTak J'apprends plutôt à gérer la géométrie impliquée dans la tâche et pour des raisons de performances, je n'aime pas utiliser Rigidbodies sauf si c'est vraiment vraiment inévitable. Dans ce cas particulier, j'aurai plusieurs milliers d'objets se comportant comme des obstacles
MAnd

Btw, merci à @Anko (ou à qui l'a fait) d'avoir inclus cette image animée pour illustrer le problème! Je réfléchissais toujours à la meilleure façon de le faire.
2015

1
@Steven et EvilTak: l'objet peut être autorisé à tourner, les obstacles non. Les moyens habituels de détecter les collisions ne semblent pas suffisants: l'objet principal continue de pénétrer à l'intérieur des objets.
2015 à 15h04

Réponses:


2

Il est difficile de détecter une collision sans aucun corps rigide impliqué, mais puisque vous utilisez des cubes, vous pouvez peut-être utiliser des limites . Chaque mise à jour, vérifiez si les limites de l'objet glissé se croisent avec les limites des obstacles. Si c'est le cas, vous pouvez essayer ceci:

  1. Désactivez le rendu de maillage de l'objet glissé pour le rendre invisible (mais continuez à le faire glisser).
  2. Déposez un objet d'espace réservé visible identique à l'objet glissé à la dernière position avant l'intersection des limites (maintenant, il semble que l'objet s'est arrêté, mais vous faites toujours glisser l'original).
  3. À chaque mise à jour, vérifiez si les limites de l'objet que vous faites toujours glisser se croisent avec les limites d'un obstacle.
  4. Lorsque les limites de l'objet glissé ne coupent plus avec un obstacle, supprimez / désactivez l'objet d'espace réservé et réactivez le rendu de maillage de l'objet glissé pour le rendre à nouveau visible.

Vous n'arrêtez jamais de faire glisser le bloc; il apparaît simplement à l'utilisateur que le bloc a cessé de glisser alors qu'il se croiserait avec un obstacle.


Sur la base des commentaires précédents et de votre réponse, j'ai édité la question pour la rendre plus facile à réaliser: disons maintenant que Rigidbody pourrait être utilisé pour l'objet glissable ou ses espaces réservés. Rigidbody ne pouvait tout simplement pas être utilisé pour les obstacles.
2015

1

Sans l'avoir fait moi-même, voici ce que j'essaierais:

  1. Décidez de la hauteur d'un obstacle dans l'avion afin de bloquer votre objet déplacé (où «haut» signifie retiré le long de l'axe approprié - je suppose que celui qui pointe vers la caméra).
  2. À chaque mise à jour, enregistrez la position de votre hit raycast.
  3. Chaque mise à jour, avant d'enregistrer la position du hit raycast actuel, vérifiez la position du hit raycast actuel par rapport à la position du hit raycast précédent.
  4. Si la différence> = hauteur de blocage, arrêtez votre objet en mouvement à la position de coup de rayon précédente.

Il me semble que si vous souhaitez que votre objet traîne le long d'un plan incliné d'un obstacle, vous devriez simplement faire en sorte que sa transformation continue de suivre la position du dernier hit raycast.


Merci pour votre réponse, @Evan. Cependant, cette solution ne serait pas exacte. Supposons que le RayCast soit tiré depuis le centre du cadre de sélection de l'objet déplaçable. Que faire si l'obstacle sur le chemin ne bloque qu'une partie de l'objet déplaçable qui se trouve à gauche ou à droite du lancer de rayon? Même si nous augmentons le nombre de rayons projetés (ce qui peut devenir exponentiellement élevé si l'objet déplaçable peut être déplacé dans des directions à 360 ° dans les dimensions X, Z), en fonction de la petite taille de l'obstacle par rapport à l'objet déplaçable, il pourrait encore être entre les rayons
projetés

D'accord, je pense que je vois ce que tu veux dire.
Evan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.