Search Unity

Objects instantiated with random positions show up in the same spot

Discussion in 'Scripting' started by ahbowe, Dec 20, 2020.

  1. ahbowe

    ahbowe

    Joined:
    Dec 20, 2020
    Posts:
    3
    I've been banging my head against this problem for 2 days and I feel like there must be something I'm missing.
    I'm trying to instantiate a number of prefabs based on 2 criteria: quantity and maximum distance. So for example I would generate 15 trees spread out in a 200 meter radius. For some reason my code keeps instantiating all the trees on top of one another at 0,0.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class maybecreatetree : MonoBehaviour
    7. {
    8.  
    9.     public GameObject treegen;
    10.  
    11.     public int quantity = 20;
    12.     public int maxdist = 500;
    13.  
    14.     void Start()
    15.     {
    16.         for (int i = 0; i< quantity; i++)
    17.         {
    18.             Instantiate(treegen, new Vector3 (UnityEngine.Random.Range(-maxdist, maxdist),0, UnityEngine.Random.Range(-maxdist, maxdist)), UnityEngine.Random.rotation);
    19.  
    20.             print("thats a tree right there");
    21.         }
    22.     }
    23. }
    This code is sitting on an empty gameobject which is also generating Perlin noise terrain with a different script.

    I've tried a few different things although I suspect I'm just misunderstanding how to use Vector3.
    Any help would be greatly appreciated.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Break line 18 apart: assign the random position to a temp variable, print it out with Debug.Log()

    You shouldn't have such long lines in general because you can't really reason about them.

    How to break down hairy lines of code:

    http://plbm.com/?p=248
     
    ahbowe likes this.
  3. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    I agree with Kurt-dekkers plan.

    But one guess could be that you are passing in an int (maxdist) where a float is expected. I'm unsure how unity / c# handles that without trying it myself.

    Either way Print() out a vector3 to confirm the values, then assign it with the instantiate
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,697
    Adding to Mr Tree's suggestion, I'm going to guess that maxdist is actually zero or something small... since it is public, if you save this scene when it is zero, Unity's serialization will overwrite your 500 class initialization value. Look in the scene or prefab to be sure.
     
    tree_arb likes this.
  5. ahbowe

    ahbowe

    Joined:
    Dec 20, 2020
    Posts:
    3
    Unfortunately, the random values are being generated properly. I cleaned up the for loop though:

    Code (CSharp):
    1.         for (int i = 0; i< quantity; i++)
    2.         {
    3.             float r1 = UnityEngine.Random.Range(-maxdist, maxdist);
    4.             print("R1:" + r1);
    5.             float r2 = UnityEngine.Random.Range(-maxdist, maxdist);
    6.             print("R2:" + r2);
    7.  
    8.             Instantiate(treegen, new Vector3 (r1,0,r2), UnityEngine.Random.rotation);
    9.         }
    The output after I ran this was 20 values in between -500 and 500. The trees still all appeared at 0,0.
     
  6. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    A few ideas:

    Try directly typing floats in there (though it sounds like you covered that)
    Try assigning transform.position the line directly after instantiation of it.
    Try printing its Transform.position directly after instantiation and again later somewhere.

    Is it reading at the correct positition when created and assigned, and then later in the same frame set to 0,0 maybe something else is resetting or moving it.

    Is the prefab set to freeze position or anything.

    Try the same code but instantiating a different prefab, some simple object like a cube or something.
     
  7. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    So I just copy and pasted your original code from post#1 exactly as is and it works correct if the prefab is just a basic cube game object. cubes get generated in random positions.

    You must have something else going on with the treegen itself or code elsewhere doing something funny.

    also look at this
    Code (CSharp):
    1.         for (int i = 0; i < quantity; i++)
    2.         {
    3.            GameObject t;
    4.            t =  Instantiate(treegen, new Vector3(UnityEngine.Random.Range(-maxdist, maxdist), 0, UnityEngine.Random.Range(-maxdist, maxdist)), UnityEngine.Random.rotation);
    5.            print(t.transform.position);
    6.         }
    for me, i see all the random positions.
    Do you get that?
    If you do, but then the object is at 0,0 and also reads 0.0 later on (later on meaning possibly in the same frame even) then something is resetting it
     
  8. ahbowe

    ahbowe

    Joined:
    Dec 20, 2020
    Posts:
    3
    I fixed it (sort of). By attaching the tree generator script to a cube prefab and then using that as the treegen game object, for whatever reason the game handles it just fine. I wish it would work on just an empty object but for whatever reason it wont. The other oddity is that while it does generate trees all over the distance, for each one it still also generates an identical tree at 0,0. So I could have 50 trees all across the horizon, and then a 50-tree Frankenstein at 0,0.

    It's working enough for my purposes, so I'm going to leave it for now and maybe I'll write my own tree generator later. Below is the one I used for this experiment. (Probably should have mentioned that at the outset admittedly).

    https://unitylist.com/p/5bc/L-System-Trees-in-Unity
     
  9. tree_arb

    tree_arb

    Joined:
    Dec 30, 2019
    Posts:
    323
    Did you ever try to set the transform.position right after instantiation instead of inside the function? If you instantiate with a new position, and then the tree is immediately setting its own position... The very next line you might be able to just set the position there.

    Or push them to a List and change the positions "later", buying you time to position after the trees custom placement script.

    Or of course you can look under the hood and see what the tree is doing too.

    Or having them in an empty game object like you have is probably just fine too.