Search Unity

Attaching Prefabs

Discussion in 'Scripting' started by tcotiago, Dec 1, 2016.

  1. tcotiago

    tcotiago

    Joined:
    Jan 24, 2016
    Posts:
    4
    Hello,
    I'm creating a 3D platformer game.
    Currently creating a system where it has a list of given prefabs, and generates the path ahead with those prefabs (think stepping stones).
    I'm currently having difficulty "snapping" the prefabs between them in a line, I want to use empty gameobjects as anchors but I'm not sure how.

    Attached is the code worked on
    I've also read how you can use transform to put it in the pivot position of the parent... not sure how aswell

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class gen : MonoBehaviour {
    6.  
    7.     public GameObject prefab;
    8.     public GameObject prefab2;
    9.     public GameObject prefab3;
    10.     public float gridX = 5f;
    11.     public float gridY = 5f;
    12.     public float spacing = 2f;
    13.  
    14.     void Start() {
    15.         for (int y = 0; y < gridY; y++) {
    16.             for (int x = 0; x < gridX; x++) {
    17.                 Vector3 pos = new Vector3(x, 0, y) * spacing;
    18.                 Instantiate(prefab, pos, Quaternion.identity);
    19. //                Instantiate(prefab2, pos, Quaternion.identity);
    20. //                Instantiate(prefab3, pos, Quaternion.identity);
    21.  
    22.  
    23.  
    24.             }
    25.         }
    26.     }
    27.  
    28.     void other() {
    29.  
    30.         for (int y = 0; y < gridY; y++) {
    31.             for (int x = 0; x < gridX; x++) {
    32.                 Vector3 pos = new Vector3(x, 0, y) * spacing;
    33.                 Instantiate(prefab2, pos, Quaternion.identity);
    34.             }
    35.         }
    36.     }
    37. }
    38.  
     
  2. romatallinn

    romatallinn

    Joined:
    Dec 26, 2015
    Posts:
    161
    Anchors for what? You mean that an empty object will be at place of the first object in a line?

    Do you want to instantiate objects in a line (as you mentioned at the very beginning) Or you want to make a grid of objects, according to the code?

    For first case:

    Code (CSharp):
    1. public int gridX = 5; // Make gridX var be integer
    2. private float y = some prescribed Y value;
    3.  
    4. for (int x = 0; x < gridX; x++) {
    5.      Vector3 pos = new Vector3(x * spacing, 0, y);
    6.      Instantiate(prefab, pos, Quaternion.identity);
    7. }
     
  3. tcotiago

    tcotiago

    Joined:
    Jan 24, 2016
    Posts:
    4
    Your code is correct for what I want to do, however, they may not overlap and I want to spawn 10 different prefabs without overlap in that line, that's where I'm having trouble.

    I'm not sure how I can spawn different prefabs (random generation every time I click play) and make them not overlap with eachother, because they are all different.
     
  4. romatallinn

    romatallinn

    Joined:
    Dec 26, 2015
    Posts:
    161
    Okay, then you should create an array of prefabs instead of creating new variable for each prefab.
    Code (CSharp):
    1. public GameObject[] prefs = new GameObject[3]; // Or instead of 3 how many prefs you have
    Then, just choose random index every time and instantiate a prefab with this index.
    Code (CSharp):
    1. public int gridX = 5; // Make gridX var be integer
    2. private float y = some prescribed Y value;
    3.  
    4. for (int x = 0; x < gridX; x++) {
    5.      Vector3 pos = new Vector3(x * spacing, 0, y);
    6.      int rndId = Random.Range(0, prefs.Length); // Random int value from 0 to 2
    7.      Instantiate(prefs[rndId], pos, Quaternion.identity);
    8. }
    PROFIT!
     
    Last edited: Dec 1, 2016
    tcotiago likes this.
  5. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Random.Range with ints is max exclusive so Length - 1 will always exclude the last item in the array. You'd want just Length
     
    romatallinn and tcotiago like this.
  6. romatallinn

    romatallinn

    Joined:
    Dec 26, 2015
    Posts:
    161
    Oops... Yeah, you are right. I always mix them up... :confused:
     
    KelsoMRK likes this.
  7. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    You can either pre-determine the size of the whole prefab, storing the value perhaps in a component on the parent and look that up when spawning a new one.

    Or you can determine it at runtime by finding the bounding box of the whole prefab and the spawned prefab to get the dimensions you need to add to the existing prefab's position.

    You can iterate on the children and find the greatest X position, or you can use some convenient Bounds functions to get the bounding box.

    Something like this perhaps, you can substitute collider bounds for renderer bounds if necessary.
    Code (CSharp):
    1. Renderer parentRenderer = GetComponent<Renderer>();         // get the parent object's renderer
    2. Bounds combinedBounds = parentRenderer.bounds;              // start with the parent's bounds
    3. Renderer[] renderers = GetComponentsInChildren<Renderer>(); // get all the child renderers
    4.  
    5. foreach(Renderer render in renderers) {
    6.     if(render != parentRenderer) {                          // if this renderer is not the parent renderer
    7.         combinedBounds.Encapsulate(render.bounds);          // grow the bounds to include the child bounds
    8.     }
    9. }
    10.  
    11. float halfWidth = combinedBounds.extents.x;
    With that half-width, you can take the current prefab X position, add the half width, then add the half with of the new prefab, and that will give you the X position for the new prefab to be edge-to-edge with the current one along the X axis.

    pseudo code:
    newPrefab.x = currentPrefab.x + currentPrefab.halfwidth + newPrefab.halfwidth
     
    Last edited: Dec 1, 2016
    tcotiago likes this.
  8. tcotiago

    tcotiago

    Joined:
    Jan 24, 2016
    Posts:
    4
    Great help!!

    Still having trouble however with some types of prefabs, as in if they aren't all equal (ex. cubes), there will be overlap because I need them to snap (prefab 1 end with prefab 2 start + spacing).



    Can I use this with romatallinn's approach? So they won't overlap?



    Thank you all for your time
     
  9. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    Yes but you won't want to use a grid as each prefab is a different size. You can instantiate one with a random index from the array of prefabs first, then calculate its bounding box and position it accordingly afterwards, adding extra spacing if desired.
     
    tcotiago likes this.
  10. tcotiago

    tcotiago

    Joined:
    Jan 24, 2016
    Posts:
    4
    Thank you so much, I'm going to try that now, sounds good!