Partie 1
Bonjour à tous,
aujourd'hui, j'inspecte l'instanciation dans Unity afin de reproduire un projet que j'ai conçu manuellement sur 3DSMax. Souhaitant reproduire dans Unity, il s'agira de produire une ville procédurale qui sera façonnée automatiquement. Ceci permettra ainsi de se concentrer sur des effets de lumière. Je souhaite, au moment de la conception, avoir un environnement qui fait du sensé.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1NhETCLblph__JG9CAR1WIka0zCpHchGk9iAAVhwII-ZAvfQYs7GMLQc9QAQ3ArgBZ-st3zvPpRg4TRk7KKj3XAHZbLWDqZRFLQ0tjso8GSDcs8rW6AiJg-DRnjWaVCdQZInugOY-Jm1k/s320/tentative.jpg)
Mon plan pour la première partie :
Pour se repérer au départ j'ai installé un script dans mon Objet de GameConfig.
Il est nommé Building Spawn:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-JFU1BMv3myS-gPzL92EhTzCradlDdoJaQgcyUZkM9hYXq_8AresRVJH195K9KbsCaTQ6KeTa-y6lR8_IytCWQ1qz05RMNlb2lJLI1J6Pu8jtUgG5-snBf4U52ve-6EAtkDpH2OFFj6dm/s200/buildSpawn.jpg)
-Maison : placer l'objet avec collision qui sera Instancié.
Dans ce cas-ci j'ai mis l'objet ci-haut.
- Surface : Terrain sur lequel les objets se trouveront.
Pour le moment, j'ai placé un Plane sur le monde et je l'ai mis dans ce paramètre.
-
Maison Pos, Nbre Batiments, Nbre Batiments Actuel : Pourraient être
privés, mais je les ai mis publics pour que vous ayez une idée de ce qui
est analysé. Ces chiffres changeront à chaque update.
- Nbre
Batiments Min, Nbre BatimentsMax : Comme les noms indiquent, ce sont
les variations du nombres d'instances de l'objet dans Maison qui se
retrouveront dans la scène.
- Collision :
Automatiquement, à l'ouverture du jeu, le Box Collider* de l'objet dans le paramètre Maison sera attaché.
*Pas
besoin d'un Mesh Collider puisque ce sont des objets très cubiques et
l'analyse que Unity fait peut devenir un peu trop compliquée sur des
collisions à géométrie complexe.
1- Générer 1 objet ...
J'ai rapidement mis en place des bâtiments à la forme allongée qui doit avoir une boîte de collision (Box Collision) pour la suite.
C'est une étape qui se termine avec deux lignes de script :
// Paramètre avec l'objet - Variable
public GameObject _maison;
Pour l'instant, on peut mettre cette ligne dans la fonction On Start :
//L'instanciation - FixedUpdate
Instantiate(_maison);
2 et 3- ...sur la surface ET au hasard ...
Le produire SUR la surface s'avérera un étape supplémentaire qui n'a pas encore été abordée dans ce projet. Bien s'assurerque le centre de l'objet s'appuie au sol dans le logiciel de modélisation (au bas du BoxCollider). Pour tout le reste, il me faudra un article complet sur le sujet.
Autrement; nous passons à l'étape 3 : je désire générer l'objet au hasard, ailleurs qu'au centre du monde.
Vient l'utilité de Maison Pos :
// créer les coordonnées - Variable
public Vector3 _maisonPos;
// dire que ce sont les mêmes coordonnées que l'objet dans Maison - On Start
_maison.transform.position = _maisonPos;
Pour l'instant, on peut mettre cette ligne dans la fonction On Start :
// changer la position de l'objet maitre - Update
_maisonPos.x = Random.Range(-5.0f, 5.0f);
_maisonPos.z = Random.Range(-5.0f, 5.0f);
_maison.transform.position = _maisonPos;
4- ... et le multiplier...
Cette fois, nous auront toutes nos Variables - je les ai toutes mises publiques mais elle peuvent être privées (private) :
public GameObject _maison;
public GameObject _surface;
public Vector3 _maisonPos;
public int _nbreBatiments;
public int _nbreBatimentsActuel = 0;
public int _nbreBatimentsMin = 1;
public int _nbreBatimentsMax = 10;
public BoxCollider _collision;
void Start()
{
//ajustés
_nbreBatiments = Random.Range(_nbreBatimentsMin, _nbreBatimentsMax);
_maison.transform.position = _maisonPos;
_collision = _maison.GetComponent<BoxCollider> ();
//créés
var _maisonRot = _maison.transform.localRotation.eulerAngles;
}
void Update()
{
// Layer 10 et layer 9 ne se voient pas (collisions)
_maison.layer = 10;
_surface.layer = 10;
}
void FixedUpdate()
{
//Pour suivre le nombre de bâtiments (PEUT ÊTRE REMPLACÉ PAR UNE FOR LOOP)
if ( _nbreBatimentsActuel < _nbreBatiments )
{
//isole et isole les collisions - layer 10 ne voit pas layer 9 - avant l'instanciation
_maison.layer = 9;
//L'instanciation
Instantiate(_maison);
//remet la layer - layer 9 voit la layer 9 - après l'instanciation
_maison.layer = 10;
//Ajout d'un token - Nombre de bâtiment (peut se faire en for loop)
_nbreBatimentsActuel += 1;
//changer la position de l'objet maitre
_maisonPos.x = Random.Range(-5.0f, 5.0f);
_maisonPos.z = Random.Range(-5.0f, 5.0f);
_maison.transform.position = _maisonPos;
//changer la rotation du même objet
var _maisonRot = _maison.transform.rotation;
_maison.transform.rotation = Quaternion.Euler(-90.0f, Random.Range(-90.0f, 90.0f), 0.0f);
}
else
{
print("Il y a " + _nbreBatiments + " bâtiments dont " + _nbreBatimentsActuel + " sont apparus.");
}
//Éviter de laisser la maison à (0, 0, 0)
if (_maison.transform.position.x == 0.0f & _maison.transform.position.z == 0.0f )
{
_maison.transform.position = _maisonPos;
}
}
J'ai déjà mis la variable de "_collision" ici pour préparer l'étape suivante. Ce qui est le plus important ici c'est l'ordre dans lequel nous procédons.
Nous verrons ici des problème de "groupes de maison interpénétrant" l'une dans l'autre.
Également, nous aurons un problème de rotation. En faisant un troubleshoot, j'ai remarqué que le système n'avait gardé que les rotation entre 0.3 et 0.7 dans la traduction en Quaternion, alors je vais rechercher pour une solution plus appropriée. Certains confirment la complexité des Quaternions dans leur réponse comme l'une des pistes ici envoyée par "rutter" :
https://answers.unity.com/questions/790877/random-rotation-in-z-axis.html
5- ... sans qu'ils ne se touchent.
Ici, nous répondons au problème des groupes de maisons avec un système utilisant les physiques "Physics.OverlapBox". Étant donné que la physique procède par moment de façon erratique avec la fonction d'Update, je me vois suggéré d'utiliser la fonction de FixedUpdate, environnement contrôlé pour la physique.
Bref, voici ce dont nous avons besoin de nouveau (et ou le placer entre les commentaires) :
// [...]créés
var _enableMeshCollider = _surface.GetComponent<MeshCollider>().enabled ;
//var _maisonRot = _maison.transform.localRotation.eulerAngles; [...]
//[...]if ( _nbreBatimentsActuel < _nbreBatiments )
//{
//mise à jour de la position de la COLLISION BOX
_collision = _maison.GetComponent<BoxCollider> ();
//création de la boite de collision (nécessite une COLLISION BOX)
//Démarrer en confirmant les collisions
var _verifCollision = Physics.OverlapBox ( (_collision.center + _maisonPos), (_collision.size), (_maison.transform.rotation));
//Continuer en vérifiant les contacts des collisions
if (_verifCollision.Length == 1 || _verifCollision.Length == 0)
{
print ("ce qui est écrit " + _verifCollision.Length + "- ne touche rien");
//troubleshooting coordonnées de la hitbox
print ("non-hit ET le centre X : " + (_collision.center.x + _maisonPos.x) + " ET la taille X : " + _collision.size.x + " ET le centre Z : " + (_collision.center.z + _maisonPos.z) + " ET la taille Z : " + _collision.size.z + " ET la rotation : " + _maison.transform.rotation);
//isole et ferme les collisions - layer 10 par rapport à la layer 9 - avant l'instanciation
//_maison.layer = 9; [...]
// [...]Ajout d'un token
//_nbreBatimentsActuel += 1;
}
else
{
print ("ce qui est écrit " + _verifCollision.Length );
//troubleshooting coordonnées de la hitbox
print("hit build"ET le centre X : " + (_collision.center.x + _maisonPos.x) + " ET la
taille X : " + _collision.size.x + " ET le centre Z : " +
(_collision.center.z + _maisonPos.z) + " ET la taille Z : " +
_collision.size.z + " ET la rotation : " + _maison.transform.rotation);
}
//changer la position de l'objet maître
_maisonPos.x = Random.Range(-5.0f, 5.0f); [...]
//[...]_maison.transform.rotation = Quaternion.Euler(-90.0f, Random.Range(-90.0f, 90.0f), 0.0f);
//repositionner la collision
_collision = _maison.GetComponent<BoxCollider> ();
//}
//else[...]
Ce sont des étapes cruciales ou l'objet "Maison", qui sera instancié, parcourt l'environnement à la recherche d'un endroit ou rien n'est placé (collision).
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy0Aw5C1wqVM9Vu25CgW5IkbYuqTwWiEfhTsAVtWVnPyp-WR42jAHnpregormJskfCMnAmWNAM2OwILgwU21Hp3EwhIoeIojmvae6zXT-nAIrtoZaIbu4FwFPkCecQ7kF9myfClBCUmU-P/s640/via-camera.jpg) |
Les maisons se tiennent plus à distance mais semblent garder relativement le même angle |
---
Retour
Utilisation de la loop avec "for" : Je crois que je dois transférer à la "for loop" plutôt que de continuer directement sur l'Update. Cela va me permettre d'isoler mes problèmes suivants.Imprécision de la vérification des Collisions : Notez que j'ai mis " if (_verifCollision.Length == 1 || _verifCollision.Length == 0)" comme condition pour créer une instance, ce qui signifie qu'il peut y avoir 1 collision. _verifCollision est la OverlapBox (Zone qui détecte des superpositions de Collisions). Si je mets uniquement "_verifCollision.Length == 0", ce qui signifie que l'Array des Collisions serait vide, je me retrouve avec une boucle infinie ou la recherche d'un endroit sans collision ne se termine jamais. Je suppose que le layer mask ne s'active pas au bon moment ou pas du tout. Je crois qu'il me faut mentionner à la OverlapBox quelle layer elle doit analyser. Elle semble mettre l'objet maître dans les collisions.
Rotations d'objet et d'OverlapBox différentes : À quelques endroits, les objets s'interpénètrent . Selon mes recherches, il s'agirait encore d'un problème lié aux rotations Quaternion vs Euler. Il est certain que je vais regarder cela de près pour la suite.
Partie 2 à venir...
Je vous souhaite la meilleure journée,
À bientôt.