Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Tiling Objects based on child object postions?

Discussion in 'Scripting' started by irjason, May 16, 2015.

  1. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    Im abit confused why this wouldn't work:


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ObjectSpawningNew : MonoBehaviour {
    5.  
    6.     public GameObject[] obj;
    7.     public float spawnMin = 1f;
    8.     public float spawnMax = 2f;
    9.     private Vector3 previousRight = new Vector3(0,0,0);
    10.     //private Vector3 previousLeft = new Vector3(0,0,0);
    11.     private int counting = 0;
    12.  
    13.  
    14.     // Use this for initialization
    15.     void Start () {
    16.         Spawn ();
    17.     }
    18.  
    19.     void Spawn()
    20.     {
    21.             //Spawn object and store it in a "Temp Var"
    22.             GameObject newPeice = Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity) as GameObject;
    23.          
    24.             //Find right postion of temp object
    25.             Transform childRight = newPeice.transform.Find("Right");
    26.  
    27.             //Find Left Postion of temp object
    28.             Transform childLeft = newPeice.transform.Find("Left");
    29.          
    30.             //Set Current Left
    31.             //Vector3 childLeftCurrent = childLeft.transform.localPosition;
    32.  
    33.             if (counting == 0){
    34.                 //If we havn't got any peices yet "Set the postion to left (so first one tiles)"
    35.                 newPeice.transform.localPosition = childLeft.transform.localPosition;
    36.                 }
    37.             //else if it isnt the first one..
    38.             else {
    39.                 //Move temp objects postion to the previous "temp objects" right postion
    40.                 newPeice.transform.localPosition = previousRight;
    41.             }
    42.  
    43.             //Set Current Right pos.
    44.             //Vector3 childRightCurrent = childRight.transform.localPosition;
    45.  
    46.             //Store temp objects right childs postion..
    47.             previousRight = childRight.transform.localPosition;
    48.          
    49.             //previousLeft = childLeftCurrent;
    50.          
    51.             //Increment by 1..
    52.             counting++;
    53.          
    54.         //Trigger loop..
    55.         Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
    56.     }
    57. }
    58.  
    59.  
    Get the "child" of the left and right of each object stored in an array... then set its postion to the previous postion.. / repeat (tiling) but to a postion i desire.. e.g. i can have multiple platforms with diffrent heights/widths etc and the postioning is determained by the "child left/right" makes sence right. well did in my note pad xD
     
    Last edited: May 16, 2015
  2. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    Hate to bump "but still stuck" (I think what is happening is its only finding the right/left of the first object.. I tried storing the newPeice as an array as well and using a index to determain what object it should be looking at in the find and no joy. I also tried findchild instead of just find. But looking in to it deeper find is basically the same if not a little faster than findchild.

     
    Last edited: May 16, 2015
  3. luke_2

    luke_2

    Joined:
    Nov 20, 2012
    Posts:
    29
    Have you tried changing
    newPeice.transform.localPosition= previousRight;
    to
    newPeice.transform.localPosition= new Vector3(previousRight.x+newPeice.transform.localScale.x/2f, previousRight.y+newPeice.transform.localScale.y/2f, previousRight.z);

    Try some debug on what previousRight is when running.
    e.g.
    Debug.log(counting+" "+previousRight);

    and maybe that will give you an idea of what is happening.
     
  4. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    I have tried that but oddly enough when debuging previous right it seems to be switching between to diffrent points and im not sure of why. Is it not finding the right child of left and right for some reason? Is it becuase im not storing the localpostion and then adding it to the previousRight postion?

    like?

    Code (CSharp):
    1. previousRight = childRight.transform.localPosition + newPeice.transform.localPosition;

    53 (2.9, 0.5, 0.0)
    UnityEngine.Debug:Log(Object)
    ObjectSpawningNew:Spawn() (at Assets/Runner/Scripts/Ingame/Object Related/ObjectSpawningNew.cs:56)

    54 (2.9, 0.5, 0.0)
    UnityEngine.Debug:Log(Object)
    ObjectSpawningNew:Spawn() (at Assets/Runner/Scripts/Ingame/Object Related/ObjectSpawningNew.cs:56)

    55 (1.9, 0.5, 0.0)
    UnityEngine.Debug:Log(Object)
    ObjectSpawningNew:Spawn() (at Assets/Runner/Scripts/Ingame/Object Related/ObjectSpawningNew.cs:56)
     
  5. luke_2

    luke_2

    Joined:
    Nov 20, 2012
    Posts:
    29
    If ChildRight is a child of obj then it will always return the same value as it is getting the position relative to its parent rather than its position in the world and new pieces aren't being made a child of the previously instantiated pieces.
    http://docs.unity3d.com/ScriptReference/Transform-localPosition.html
    Try setting previousRight to transform.position if this is the case.
     
    Last edited: May 16, 2015
  6. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    Still don't seem to be able to get it to tile from the postions i would like it to.From what your saying is if i use localpostion on a child then it will retreive the relative postion of what its parents postion is instead of its postion. But if i was just to use its own transform it would relate to the childs postion right? i have tired it but still the same result.. i dunno if im missing somthing really obvious i feel its "one of them things".

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ObjectSpawningNew : MonoBehaviour {
    5.  
    6.     public GameObject[] obj;
    7.     public float spawnMin = 1f;
    8.     public float spawnMax = 2f;
    9.     private float previousRightX;
    10.     private float previousRightY;
    11.     //private Vector3 previousLeft = new Vector3(0,0,0);
    12.     private int counting = 0;
    13.     private GameObject newPeice;
    14.  
    15.    
    16.     // Use this for initialization
    17.     void Start () {
    18.         Spawn ();
    19.     }
    20.    
    21.     void Spawn()
    22.     {
    23.             //Spawn object and store it in a "Temp Var"
    24.         newPeice = Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity) as GameObject;
    25.                
    26.             Transform childRight = newPeice.transform.FindChild("Right");
    27.             //Find right postion of temp object
    28.                 //Transform childRight = newPeice.transform.GetChild(3);
    29.             //Find Left Postion of temp object
    30.                 //Transform childLeft = newPeice.transform.GetChild(2);
    31.             Transform childLeft = newPeice.transform.FindChild("Left");
    32.            
    33.  
    34.             float leftPosX = childLeft.transform.position.x;
    35.             float leftPosY = childLeft.transform.position.y;
    36.  
    37.             float currentPosX = newPeice.transform.position.x;
    38.             float currentPosY = newPeice.transform.position.y;
    39.  
    40.             //Set Current Left
    41.             //Vector3 childLeftCurrent = childLeft.transform.localPosition;
    42.  
    43.             if (counting == 0){
    44.                 //If we havn't got any peices yet "Set the postion to left (so first one tiles)"
    45.             currentPosX = leftPosX + currentPosX;
    46.             currentPosY = leftPosY + currentPosY;
    47.                 }
    48.             //else if its not the first one..
    49.             else {
    50.                 //Move temp objects postion to the previous "temp objects" right postion
    51.             currentPosX = previousRightX;
    52.             currentPosY = previousRightY;
    53.             }
    54.  
    55.             float rightPosX = childRight.transform.position.x;
    56.             float rightPosY = childRight.transform.position.y;
    57.  
    58.             //Set Current Right pos.
    59.             //Vector3 childRightCurrent = childRight.transform.localPosition;
    60.  
    61.             //Store temp objects right childs postion..
    62.             previousRightX = currentPosX + rightPosX;
    63.             previousRightX = currentPosY + rightPosY;
    64.  
    65.             Debug.Log("x " + counting + " " + previousRightX);
    66.             Debug.Log("y " + counting + " " + previousRightY);
    67.            
    68.             counting++;  
    69.            
    70.             //previousLeft = childLeftCurrent;
    71.            
    72.            
    73.         //Trigger loop..
    74.         Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
    75.     }
    76. }
    77.  
    78.  
    Result:



    Not tiling from the correct position =[
     
    Last edited: May 16, 2015
  7. luke_2

    luke_2

    Joined:
    Nov 20, 2012
    Posts:
    29
    In the above code I can't see the new transform being set to the currentPos anywhere...
    maybe add line 6
    1. else {
    2. //Move temp objects postion to the previous "temp objects" right postion
    3. currentPosX = previousRightX;
    4. currentPosY = previousRightY;
    5. }
    6. newPeice.transform.position=new Vector3(currentPosX+newPeice.transform.localScale.x/2f,currentPosY,newPeice,transform.position.z);
     
    Last edited: May 16, 2015
  8. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    That is a very valid point lol.. (knew it would be somthing dumb im missing) !

    Wouldn't i also need its current postion as well? and add that on or it would just sit at a "set area"?


    Code (CSharp):
    1.     else {
    2.                 //Move temp objects postion to the previous "temp objects" right postion
    3.             currentPosX = previousRightX+newPeice.transform.localScale.x/2f+newPeice.transform.position.x;
    4.             currentPosY = previousRightY+newPeice.transform.localScale.y/2f+newPeice.transform.position.y;
    5.             }
    6.  
    7.             newPeice.transform.position = new Vector3(currentPosX,currentPosY,newPeice.transform.position.z);
     
  9. luke_2

    luke_2

    Joined:
    Nov 20, 2012
    Posts:
    29
    >>Wouldn't i also need its current postion as well?

    Nope, you want to set the new pieces position to the previous pieces right hand position, then add on 1/2 the new piece's width (assuming the center of the new pieces origin is in the middle of the object) so they don't overlap (the addition of 1/2 the new piece's width is missing from your new code).

    Hope that works,
    Good luck.
     
  10. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    I think i see what your saying but im not wanting to use the origin of the actually sprite itself rather the (right/left) empty game object's as the orgin points for the determaining the postion of where they spawn. Because i could of just found the render bounds and then got its height/width and do it that way. But due to the platforms having diffrent shapes/sizes i thought the best solotion would be to have left/right empty game objects to determain the postioning of each orgin point for the new object to spawn. And since the game objects of left and right are empty wouldn't it mean the orgin of them is 0 always? since they have no size.


    "^ Scrap that i think i understand what u mean now xD!"
     
    Last edited: May 16, 2015
  11. luke_2

    luke_2

    Joined:
    Nov 20, 2012
    Posts:
    29
    The left and right objects may not have any size, but they have a position, by getting the transform.position of them you are getting their position in the world space.

    The new piece is then positioned at the world position of the right empty gameobject. However it is likely that the center of the new piece will be on top of the right empty gameobject, so it needs to be moved across so its center is offset by the new pieces size (hence why the suggestion of adding half the new objects width).

    Personally I wouldn't bother with the left/right empty gameobject and just base it all on the objects size.
    So (assuming every piece has it's center point in the middle of the sprite) you'd store the previous objects transform.position and the previous objects transform.localScale and the new piece would be set to the position
    oldPosition.x+oldLocalScale.x/2f+newLocalScale.x/2f,oldPosition.y,oldPosition.z;
    Your approach would work, but has extra empty gameobjects, and you need to ensure they are set correctly for each sprite you use. (maybe the render bounds method you mention would work - but I've never used them - so can't comment)
     
    Last edited: May 16, 2015
  12. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    Well after "Grabbing out a notepad" and writing the method out on paper i kinda wrote it wrong on how it should world from the get go. And i was going to orginally used your method you mentioned but due to wanting diffrent size platforms. "Go up / down" etc i thought this method might work nicer giving abit more flexibility but i do agree aligning the empty object's is going to be a nightmare.

    and all bounds are is a invinsble box around your gameobject effectivly so nothing special or anything. But i might go back to the simpler method as you said just by using the sprites postioning.

    Ill try re-writing this in a diffrentish approach and see how it works. Thanks for all your help =]
     
  13. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    don't get it no matter how hard i try.. they always over lap on the x... =/


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class ObjectSpawningNew : MonoBehaviour {
    5.  
    6.     public GameObject[] obj;
    7.     public float spawnMin = 1f;
    8.     public float spawnMax = 2f;
    9.     private float previousRightX;
    10.     private float previousRightY;
    11.  
    12.     private float previousPos;
    13.     private float previousPosY;
    14.     private float move;
    15.     private float moveX;
    16.     private float moveY;
    17.     private int counting = 0;
    18.     private GameObject newPeice;
    19.  
    20.  
    21.     // Use this for initialization
    22.     void Start () {
    23.         Spawn ();
    24.     }
    25.  
    26.     void Spawn()
    27.     {
    28.             //Spawn object and store it in a "Temp Var"
    29.         newPeice = Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity) as GameObject;
    30.  
    31.             //Get the children
    32.             Transform childRight = newPeice.transform.Find("Right");
    33.             Transform childLeft = newPeice.transform.Find("Left");
    34.             Transform childPlat = newPeice.transform.Find("Plat");
    35.  
    36.             float left = childLeft.transform.position.x;
    37.             float lefty = childLeft.transform.position.y;
    38.          
    39.             float currentPos = newPeice.transform.position.x;
    40.             float currentPosy = newPeice.transform.position.y;
    41.  
    42.  
    43.             if (counting == 0){
    44.             move = currentPos;
    45.             moveY = currentPosy;
    46.                 }
    47.             else {
    48.             move = previousPos - newPeice.transform.localScale.x/2f;
    49.             moveY = previousPosY - newPeice.transform.localScale.y/2f;
    50.             }
    51.             newPeice.transform.position = new Vector3(move,moveY,newPeice.transform.position.z);
    52.          
    53.             float right = childRight.transform.position.x;
    54.             float rightY = childRight.transform.position.y;
    55.  
    56.             previousPos = right;
    57.             previousPosY = rightY;
    58.  
    59.             counting++;  
    60.          
    61.         //Trigger loop..
    62.         Invoke ("Spawn", Random.Range (spawnMin, spawnMax));
    63.     }
    64. }
    65.  
    66.  
    yet on the y.. it's fine..

    Tried many things on the x (getting the sprite and then grabing the sprites width) tried using the bounds size .. and everything no joy..
     
  14. irjason

    irjason

    Joined:
    Sep 15, 2012
    Posts:
    42
    So i thought i would do it the simpler way but yet still my platforms are over lapping what am i doing wrong =[


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SpawnObjectSize : MonoBehaviour {
    5.  
    6.     public GameObject[] obj;
    7.     public float spawnMin = 1f;
    8.     public float spawnMax = 2f;
    9.  
    10.     private GameObject newPeice;
    11.  
    12.     private Vector3 previousScale;
    13.     private Vector3 previousPos;
    14.  
    15.     private bool isFirst = true;
    16.  
    17.     // Use this for initialization
    18.     void Start () {
    19.         Spawn ();
    20.     }
    21.  
    22.     void Spawn()
    23.     {
    24.         //Instantiate a object.. and assign it to new peice
    25.         newPeice = Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity) as GameObject;
    26.  
    27.         //Set up the current scale/current pos var's
    28.         Vector3 CurrentScale = newPeice.transform.localScale;
    29.         Vector3 CurrentPos = newPeice.transform.position;
    30.  
    31.         if (!isFirst){
    32.             //If its not first then - Set its postion (its last postion + half its previous scale + half its current scale) //erm might not work with diffrent size platforms..
    33.             newPeice.transform.position = new Vector3(previousPos.x + previousScale.x/2f + CurrentScale.x/2f,
    34.                                                       previousPos.y,
    35.                                                       previousPos.z);
    36.         }
    37.         else{
    38.             //If it is the first one .. just set it up where it is...
    39.             newPeice.transform.position = new Vector3(CurrentPos.x + CurrentScale.x,
    40.                                                       CurrentPos.y + CurrentScale.y,
    41.                                                       CurrentPos.z);
    42.             //no longer first..
    43.             isFirst = false;
    44.         }
    45.  
    46.         //Get its now current postion and local scale and set it.. to previous pos and scale.
    47.         previousPos = newPeice.transform.position;
    48.         previousScale = newPeice.transform.localScale;
    49.  
    50.         //loop through at a set spawn rate.. range
    51.         Invoke ("Spawn",Random.Range(spawnMin,spawnMax));
    52.     }
    53. }
    54.  
    Interestingly i thought "what if its the localscale" that is giving me the wrong values... so i thought why not try using the size of the collider to try and align it all.. and it allined perfectly.. Anyone have any idea what the localscale wouldn't give me the correct sizing?


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class SpawnObjectSize : MonoBehaviour {
    5.  
    6.     public GameObject[] obj;
    7.     public float spawnMin = 1f;
    8.     public float spawnMax = 2f;
    9.  
    10.     private GameObject newPeice;
    11.     private Vector3 previousScale;
    12.     private Vector3 previousPos;
    13.     private bool isFirst = true;
    14.  
    15.     // Use this for initialization
    16.     void Start () {
    17.         Spawn ();
    18.     }
    19.    
    20.     void Spawn()
    21.     {
    22.         //Instantiate a object.. and assign it to new peice
    23.         newPeice = Instantiate (obj [Random.Range (0, obj.GetLength (0))], transform.position, Quaternion.identity) as GameObject;
    24.  
    25.         //Set up the current scale/current pos var's
    26.         //Vector3 CurrentScale = newPeice.transform.localScale;
    27.         Vector3 CurrentPos = newPeice.transform.position;
    28.         BoxCollider2D collider = newPeice.GetComponent<BoxCollider2D>();
    29.         Vector3 CurrentScale = collider.size;
    30.  
    31.         if (!isFirst){
    32.             //If its not first then - Set its postion (its last postion + half its previous scale + half its current scale) //erm might not work with diffrent size platforms..
    33.             newPeice.transform.position = new Vector3(previousPos.x + previousScale.x/2 + CurrentScale.x/2,
    34.                                                       previousPos.y,
    35.                                                       previousPos.z);
    36.         }
    37.         else{
    38.             //If it is the first one .. just set it up where it is...
    39.             newPeice.transform.position = new Vector3(CurrentPos.x + CurrentScale.x,
    40.                                                       CurrentPos.y + CurrentScale.y,
    41.                                                       CurrentPos.z);
    42.             //no longer first..
    43.             isFirst = false;
    44.         }
    45.  
    46.         //Get its now current postion and local scale and set it.. to previous pos and scale.
    47.         previousPos = newPeice.transform.position;
    48.         //previousScale = newPeice.transform.localScale;
    49.         previousScale = collider.size;
    50.  
    51.         //loop through at a set spawn rate.. range
    52.         Invoke ("Spawn",Random.Range(spawnMin,spawnMax));
    53.     }
    54. }
    55.  
     
    Last edited: May 17, 2015