3 votes

Unity - Les objets instanciés se reproduisent à la même position dans la Coroutine, alors qu'en les instanciant directement, ils se reproduisent correctement.

Ce que je veux réaliser :

Je crée une ville générée de manière procédurale. J'ai réussi à faire fonctionner les routes, ainsi que la création des maisons, elles apparaissent le long de la route et ne sont pas créées si elles entrent en collision avec la route et/ou un autre bâtiment. Maintenant, comme je veux parfois charger une grande ville, cela coûte beaucoup de temps de calcul, alors je voulais mettre une Coroutine pour charger lentement toutes les maisons. (S'il vous plaît dites-moi s'il y a une meilleure façon, ou une façon "correcte", c'est la seule chose que je savais qui pourrait fonctionner).

Ce que j'ai fait / Problème :

Donc ce que j'ai fait, c'est que tous les segments que j'utilise pour créer une maison, je les mets dans une liste, et une fois que toutes les maisons sont pré-générées (pas encore spawned/instantiated) je veux utiliser la coroutine pour les spawn individuellement. Mais lorsque j'utilise la coroutine pour les faire apparaître, elles apparaissent les unes dans les autres. Alors que si je les fais naître directement à partir de leur script (en utilisant toujours la liste), ils naissent correctement, je n'ai aucune idée de ce que je fais mal et de la façon de résoudre ce problème.

public void Spawner(Vector3 buildingPosition, Quaternion buildingRotation, int buildingHeight, GameObject buildingParent, LayerMask m_LayerMask, BuildingGenerator buildGenerator)
    {
        GameObject baseBuilding = buildingBase[Random.Range(0, buildingBase.Count)];
        baseBuilding.transform.position = buildingPosition;
        baseBuilding.transform.rotation = buildingRotation;

        Debug.Log(baseBuilding.transform.position);

        Collider[] hitColliders = Physics.OverlapBox(baseBuilding.transform.position, baseBuilding.GetComponentInChildren<Renderer>().bounds.extents /2, Quaternion.identity, m_LayerMask);
        if (hitColliders.Count() > 1)
        {
            return;
        }
        buildGenerator.Segments.Add(baseBuilding);
        buildingPosition.y += baseBuilding.GetComponentInChildren<Renderer>().bounds.max.y - buildingPosition.y;

        for (int i = 0; i <= buildingHeight; i++)
        {
            buildingRotation *= Quaternion.Euler(0, 0, 0);
            GameObject middleBuilding = buildingMiddle[Random.Range(0, buildingMiddle.Count)];
            middleBuilding.transform.position = buildingPosition;
            middleBuilding.transform.rotation = buildingRotation;
            //buildGenerator.Segments.Add(middleBuilding);

            buildingPosition.y += middleBuilding.GetComponentInChildren<Renderer>().bounds.max.y - buildingPosition.y;

        }
        if (buildingRoof.Count != 0)
        {
            GameObject roofBuilding = buildingRoof[Random.Range(0, buildingRoof.Count)];
            roofBuilding.transform.position = buildingPosition;
            roofBuilding.transform.rotation = buildingRotation;
            buildGenerator.Segments.Add(roofBuilding);
        }
        Instantiate(buildGenerator.Segments[1]);                //If i use this, they spawn on the correct place.
        Debug.Log(buildGenerator.Segments.Count);

    }

    {
        StartCoroutine(LoadSegments(buildingParent));
    }
    public IEnumerator LoadSegments(GameObject buildingParent)
    {
        for (int i = 0; i < Segments.Count; i++)
        {
            GameObject SpawnedSegment = Instantiate(Segments[i]);
            //SpawnedSegment.transform.parent = buildingParent.transform;
            yield return new WaitForEndOfFrame();
        }
    }

Informations supplémentaires :

Je fais usage de 3 scripts pour spawn la ville entière, le roadGenerator, qui va spawn les routes, ces points de route sont stockés dans une liste. Une fois les routes générées, le roadgenerator appelle le building Generator. Le générateur de bâtiment va parcourir toute la liste de toutes les routes, et créer des bâtiments à côté d'elles, les bâtiments sont créés via un 3ème scripts (non instancié). Le scripts de construction, ce scripts contient les segments de construction, et va les assembler et aussi vérifier les collisions (Premier bloc de code). Une fois que ces bâtiments sont tous créés et mis dans une liste, le buildingGenerator va lancer la coroutine et instancier tous ces bâtiments (donc sur la mauvaise position)(Second bloc de code).

J'espère avoir fourni suffisamment d'informations, sinon je serais heureux d'en fournir davantage.

1voto

Lilly Points 51

Ok, j'ai finalement réussi à le faire fonctionner. Le problème ne venait pas de la coroutine, mais de la liste. Mon code surchargeait constamment les objets de ma liste. Donc j'ai créé un nouveau script, avec des attributs de base comme l'objet, la position et la rotation. Ensuite, j'ajoute ces nouveaux script à la liste, et je les génère dans la coroutine. (Dans mon commentaire, j'ai dit que j'ai eu d'autres problèmes après avoir corrigé cela, c'est parce que j'ai utilisé .bounds.max.y, alors que j'aurais dû utiliser .bounds.size.y. C'est donc aussi la correction pour cela).

J'espère que quelqu'un dans le futur pourra trouver cela utile !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X