Comment detecter si un objet est crée sur un autre

Questions techniques liées à l’utilisation d'Unity (et n'entrant pas dans le cadre d'une des sections suivantes)
MattOPI
Messages : 5
Inscription : 14 Sep 2021 16:00

Comment detecter si un objet est crée sur un autre

Message par MattOPI » 14 Sep 2021 16:45

Bonjour,
je suis débutant avec unity et je connais donc assez peu de fonctionnalité possible, donc surtout n'hesitez pas à me proposer des trucs qui peuvent vous parraitre évident xD

Voici mon problème, je suis actuellement en train de faire un jeu où il y a beaucup de nouveaux objets généré pendant le jeux, je les créer tous avec 'instantiate' et ensuite je modifie 'transorm.position' pour les placer à l'endroit que je veux.
Bon déja rien que pour ca, pensez-vous à d'autre moyen pour créer les objets ou les positionners?

Et sinon, ce que j'aimerais pouvoir faire c'est ajouter une sécurité, j'aimerais que si je modifie la position d'un objet et que cela le fait arriver sur un autre objet déja existant, je puisse détruire l'objet qui vient d'arriver. Typiquement, je pourrais vouloir placer un pot de fleur à un endroit, mais il y a en a peut-etre déja un et ca posera des problemes si il est crée à cet endroit, donc je veux pouvoir le détruire avant de le placer, ou immédiatement après.

La solution que j'ai essayer de mettre en place pour contourner le probleme, est de mettre un box collider 'triggerable' :) à l'intérieur de mon objet, de cette manière il detecte avec 'OnTriggerEnter' si un objet est placé par dessus, et pour éviter qu'il ne se détecte lui même avec le box colider de l'objet dans lequel il est, je remonte un peu pour différencier les 'gameObject', j'ai également ajouté une distinction avec les tags pour éviter les problèmes avec le décors.
Cela reste problématique, parceque comme tout les pots de fleur en posséderont un, les deux s'activeront si les deux pots de fleurs sont superposé, et c'est plutot embetant. Et je ne peux donc pas faire une action spécifique sinon elle se fera en double, et je suis incapable de différencier les deux évenements.
Par exemple, j'aimerais pouvoir détruire l'objet qui est sensé etre crée sur l'objet existant, mais en mettant un destroy il se détruirons mutuellement. Bref, je sais pas faire xD

De mon point de vue, il y a trois manière de resoudre mon problème, admettons qu'il y a un objet A à un endroit et que je veuille créer un objet B à ce même endroit :
- arriver à detecter si il y a déja un objet à l'endroit où je veux placer B et ensuite décider si je crée B ou pas
- ou créer B et le placer, ensuite faire ensorte que B detecte si il est placé sur quelqu'un et si oui le faire s'autodétruire
- ou créer B et le placer, ensuite faire en sorte que A detecte si on lui à crée un objet dessus, et si oui détruire l'objet en question.

Avez-vous des idées pour en réaliser une des trois? Ou sinon, connaissez-vous des moyens diférents de faire ce que je veux, sans utiliser 'instantiate' par exemple?

Merci d'avance pour l'aide que vous pourrez m'apporter ^^

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5623
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: Comment detecter si un objet est crée sur un autre

Message par boubouk50 » 14 Sep 2021 17:38

Salut,

la manière la plus simple et efficace, je pense, est de déterminer en amont si tu peux poser un objet ou non.
Pour cela, si tu veux utiliser la physique Unity, tu peux utiliser (entre autres) un SphereCast () pour déterminer si dans le rayon d'action de la sphère il y a un objet ou non.
Ensuite, l'Instantiate ne te convient pas?
Si tu as bcp d'objets à instancier, le meilleur système reste le Pooling.
Il s'agit de préparer en amont des objets qui seront simplement affichés plutôt que d'être créés puis détruits, ce qui évite pas mal de temps de calcul et de déchets à envoyer au GarbageCollector.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
jmhoubre
Messages : 500
Inscription : 05 Oct 2019 22:05

Re: Comment detecter si un objet est crée sur un autre

Message par jmhoubre » 14 Sep 2021 18:39

Bonjour,

une autre solution, peut être plus simple pour un débutant : une grille. Tu crées une grille recouvrant ta zone de jeu (un array de GameObject). Il faut déterminer la surface de tes cases : trop grande tes objets seront loin les uns des autres, trop petite, il y aura beaucoup de cases inutilisées, ce qui n'est pas vraiment une bonne pratique.
Quand tu crées un objet :
1) choisir une case où le placer ;
2) la case est vide : instancier l'objet et le stocker dans la case.
3) la case est pleine : choisir une autre case.

Si tes objets n'ont pas la même surface de base, on peut les stocker dans plusieurs cases. Cela complique un peu, surtout s'il faut pouvoir détruire un objet placé.

Sinon, pour instancier et détruire à foison, le pooling est la bonne méthode, comme précisé par Boubouk :
- voici ce qu'en dit la doc d'Unity ;
- un tuto officiel sur le site learn Unity (10 minutes) ;
- un tuto de Brackeys (17 minutes) ;
Il y a des tas de façons de réaliser un pool, et ce n'est pas une technique réservée aux experts... Le principe est de préparer une quantité d'objets en les Instantiant et en les désactivant. Quand on a besoin d'un objet, on l'active. Quand ce n'est plus le cas, on le désactive. Une structure, souvent une List, est utilisée pour stocker les objets :
- Instantiate est remplacé par { ChercherUnObjetInactif; Activer; ModifierObjet (le transform en particulier)}
- Destroy est remplacé par { Désactiver; }
On peut mettre une sécurité : quand il n'y a plus d'objets disponibles dans le pool, on en ajoute un (Instantiate puis Désactiver puis mettre dans la structure du pool).

MattOPI
Messages : 5
Inscription : 14 Sep 2021 16:00

Re: Comment detecter si un objet est crée sur un autre

Message par MattOPI » 14 Sep 2021 19:00

Dacodac, j'essaie ca.
Merci beaucoup pour l'aide en tout cas.

Du coup, je rencontre un problème en l'utilisant :))

Code : Tout sélectionner

public virtual void Place(Vector3 newPosition)
    {
        RaycastHit hit;

        boxHeight = this.gameObject.GetComponent<BoxCollider2D>().size.y;
        boxLenght = this.gameObject.GetComponent<Collider2D>().size.x;
        radius = min(boxHeight, boxLenght)/2;
        startPoint = newPosition;
        direction = transform.forward;

        if (Physics.SphereCast(startPoint, radius, direction, out hit, 1) && hit.CompareTag("Object"))
        {
            this.Destroy();
        }else
        {
            this.transform.position = newPosition;
            // this.gameObject.SetActive(true);
        }
    }
Donc, j'essaie ca, pour boxHeight et boxLenght j'essaie deux ecriture différentes qui ne marche pas l'une comme l'autre, en fait j'aimerais récupérer les dimensions du BoxCollider, mais je ne sais pas vraiment commen faire.
Ensuite, je n'ai pas vérifier que la fonction min marchais mais ca je pense que je peux trouver.
Ensuite, pour le sphereCast, est-ce que si toutes les variables sont défini correctement, il est sensé marcher? Les arguments sont bon?
Et pour finir, le hit.compareTag ne marche pas, ce qui semble plutot coherent, il faudrait que je récupère l'objet qu'il a touché plutot, comment je peux faire ca?

ps : le this.Destroy() est normal, c'est juste une méthode 'virtual' que j'ai fait et qui porte le même nom que la fonction habituel
ps2 : Dac, je ne connaissais pas du tout le Pool et je pense que je l'utiliserais pour certain cas, si mon jeux est vraiment trop lent, je pense que j'essairais d'utiliser ca, mais à première vu ca me semble peu adapté pour les objets que j'ai crée là. En fait tout depend de coment start et awake fonctionne, mais malheureusement, je suppose qu'il s'excute quand même, même si l'objet n'est pas activé? Parceque, actuellement, des la création d'un objet, je le place dans une hierarchy, qui à globalement une structure d'arbre où tout les fils sont relié en liste chainé, ce qui reste assez efficasse pour les supprimer de la hierachy puisqu'il n'y a globalement aucun parcours de liste à faire. Du coup, des que je créer un objet, je le place dans la hierarchy et cela se fait dans le awake, je suppose que ce doit pouvoir etre adaptable en prenant un objet existant et au moment de l'activer de l'ajouter à la hierarchy mais bon...

Pleins de questions en plus ^^
Merci beaucoup pour l'aide en tout cas
Dernière édition par MattOPI le 14 Sep 2021 19:15, édité 4 fois.

Avatar de l’utilisateur
Max
Messages : 8375
Inscription : 30 Juil 2011 13:57
Contact :

Re: Comment detecter si un objet est crée sur un autre

Message par Max » 14 Sep 2021 19:11

Bonsoir,

Je ne pense pas que passer par un Cast soit la bonne méthode,
mais plutôt Physics.OverlapSphere par exemple, qui va retourner tous les colliders détectés au sein d'une sphère à partir d'une position précise.
Mais lève nous d'un doute: tu fais de la 3D ou de la 2D, parce que c'est pas la même ?
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

MattOPI
Messages : 5
Inscription : 14 Sep 2021 16:00

Re: Comment detecter si un objet est crée sur un autre

Message par MattOPI » 14 Sep 2021 19:17

Bonsoir,

2D, 2D :hehe:
C'est mon premier jeux, c'est encore un peu trop dur pour moi la 3D xDD

Et du coup, dac je regarde ca ^^
D'après ce que je vois, Physics.OverlapSphere à en effet plus l'air de faire ce que je veux ^^
Dernière édition par MattOPI le 14 Sep 2021 19:21, édité 1 fois.

Avatar de l’utilisateur
Max
Messages : 8375
Inscription : 30 Juil 2011 13:57
Contact :

Re: Comment detecter si un objet est crée sur un autre

Message par Max » 14 Sep 2021 19:20

dans ce cas regardes tu coté des Physics2D.Overlap, tu trouveras ton bonheur. Attention, il ne faut pas mélanger les componant 2D/3D :mrgreen:
Image
Pas d'aide par MP, le forum est là pour ça.
En cas de doute sur les bonnes pratiques à adopter sur le forum, consulter la Charte et sa FAQ

Avatar de l’utilisateur
boubouk50
ModoGenereux
ModoGenereux
Messages : 5623
Inscription : 28 Avr 2014 11:57
Localisation : Toulouse

Re: Comment detecter si un objet est crée sur un autre

Message par boubouk50 » 15 Sep 2021 08:40

Max a écrit :
14 Sep 2021 19:11
mais plutôt Physics.OverlapSphere
Ma faute, je pensais à ça plutôt que le cast. J'ai mal aiguillé du coup.
"Ce n'est pas en améliorant la bougie, que l'on a inventé l'ampoule, c'est en marchant longtemps."
Nétiquette du forum
Savoir faire une recherche
Apprendre la programmation

Avatar de l’utilisateur
jmhoubre
Messages : 500
Inscription : 05 Oct 2019 22:05

Re: Comment detecter si un objet est crée sur un autre

Message par jmhoubre » 15 Sep 2021 12:22

MattOPI a écrit :
14 Sep 2021 19:00
Donc, j'essaie ca, pour boxHeight et boxLenght j'essaie deux ecriture différentes qui ne marche pas l'une comme l'autre, en fait j'aimerais récupérer les dimensions du BoxCollider, mais je ne sais pas vraiment commen faire.
Pour cela, tu peux utiliser Collider.bounds.
MattOPI a écrit :
14 Sep 2021 19:00
Ensuite, je n'ai pas vérifier que la fonction min marchais mais ca je pense que je peux trouver.
La librairie Mathf possède cette fonction : Mathf.Min(a, b) qui fonctionne pour les float ou les int.

Avatar de l’utilisateur
jmhoubre
Messages : 500
Inscription : 05 Oct 2019 22:05

Re: Comment detecter si un objet est crée sur un autre

Message par jmhoubre » 15 Sep 2021 17:37

MattOPI a écrit :
14 Sep 2021 19:00
ps2 : Dac, je ne connaissais pas du tout le Pool et je pense que je l'utiliserais pour certain cas, si mon jeux est vraiment trop lent, je pense que j'essairais d'utiliser ca, mais à première vu ca me semble peu adapté pour les objets que j'ai crée là. En fait tout depend de coment start et awake fonctionne, mais malheureusement, je suppose qu'il s'excute quand même, même si l'objet n'est pas activé? Parceque, actuellement, des la création d'un objet, je le place dans une hierarchy, qui à globalement une structure d'arbre où tout les fils sont relié en liste chainé, ce qui reste assez efficasse pour les supprimer de la hierachy puisqu'il n'y a globalement aucun parcours de liste à faire. Du coup, des que je créer un objet, je le place dans la hierarchy et cela se fait dans le awake, je suppose que ce doit pouvoir etre adaptable en prenant un objet existant et au moment de l'activer de l'ajouter à la hierarchy mais bon...
Déjà, il faut bien voir qu'il n'y a pas un pool, mais des pools. Ou du moins plusieurs manières de faire.

Par exemple, dans le tuto de Brackeys, tout objet utilisé est remis dans le pool, avec pour conséquence qu'un objet dans la scène put être déplacé ailleurs si le pool n'est pas suffisamment grand. C'est adapté pour des effets ou des décals, éventuellement pour des éléments de décor, mais pas vraiment pour des projectiles. Le tuto d'Unity utilise une technique plus classique : un objet n'est pas détruit mais remis dans le pool. Si le pool n'a plus d'objet disponible il renvoie null. Je préfère en général ajouter un objet dans le pool, qui règle sa taille seul comme un grand.

Autre exemple, Brackeys implémente un dictionnaire de pools, il peut donc avoir un pool de pots de fleurs :) un pool de projectile et un pool d'effet.

Alors oui, le pool s'exécute à son start, et instancie autant d'objets que demandés (la taille initiale du pool). Mais c'est au lancement du jeu, pas pendant le jeu, d'où l'intérêt. Quand le joueur prend la main sur le jeu, tu as donc un pool avec disons 50 objets pré-instanciés, mais désactivés. Ils n'occupent que de la mémoire, et ne consomme pas de temps CPU.

Ils sont enfants de ce que tu veux. Généralement, le script du pool est attaché à un empty type GameManager ou PoolManager. les objets peuvent alors être enfants du GameManager. En général aussi, le script utilise un singleton afin de faciliter l'accès aux fonctions ObtenirUnObjet et RendreUnObjet.

Répondre

Revenir vers « Unity le logiciel »