Muhammad Faizan Khan
Muhammad Faizan Khan

Reputation: 10551

Spawn image at random position in canvas

I have a canvas and inside it a panel. I want to spawn different image UI object at random position inside my panel (on screen). I took x and y min and max limits of the panel in order to generate a random position (withing these limts) but the problem is object are not instantiating at desired position. This is my code.

public class ImageSpawnerScreen : MonoBehaviour {
    public float waitTime = 2;
    public float cubeSpawnTotal = 10;
    public List<GameObject> cubePrefabList;

    float xPosMinLimit = -347;
    float xPosMaxLimit = 340;
    float yPosMinLimit = -458f;
    float yPosMaxLimit = 450f;

    public GameObject panel;
    void Start()
    {
        StartCoroutine(SpawnCube());
    }


    IEnumerator SpawnCube()
    {
        for (int i = 0; i < cubeSpawnTotal; i++)
        {
            GameObject prefabToSpawn = cubePrefabList[Random.Range(0, cubePrefabList.Count - 1)];
            //Vector3 spawnPosition = Camera.main.ScreenToViewportPoint(new Vector3(Random.Range(0,Screen.width),0,Random.Range(0,Screen.height)));  //Random.Range(xPosMinLimit, xPosMaxLimit);

            float xPos = Random.Range(xPosMinLimit, xPosMaxLimit);
            float yPos = Random.Range(yPosMinLimit, yPosMaxLimit);
            Vector3 spawnPosition = new Vector3(xPos, yPos, 0f);
            GameObject spwanObj = Instantiate(prefabToSpawn, spawnPosition, Quaternion.identity) as GameObject;
            spwanObj.transform.parent = panel.transform;
            spwanObj.transform.position = spawnPosition;
            yield return new WaitForSeconds(waitTime);
        }
    }
}

I checked instantiated object positions are far away from the given random range position. What I am doing wrong? I think it is Rect Transform so i have to set its position differently.

Upvotes: 0

Views: 7575

Answers (3)

piep KDG
piep KDG

Reputation: 1

public class ImageSpawnerScreen : MonoBehaviour {
    public float waitTime = 2;
    public float cubeSpawnTotal = 10;
    public List<GameObject> cubePrefabList;

    public GameObject panel;
    void Start()
    {
        StartCoroutine(SpawnCube());
    }


    IEnumerator SpawnCube()
    {
        for (int i = 0; i < cubeSpawnTotal; i++)
        {
            GameObject prefabToSpawn = cubePrefabList[Random.Range(0, cubePrefabList.Count - 1)];
            //Vector3 spawnPosition = Camera.main.ScreenToViewportPoint(new Vector3(Random.Range(0,Screen.width),0,Random.Range(0,Screen.height)));  //Random.Range(xPosMinLimit, xPosMaxLimit);

            float xPos = Random.Range(0, Screen.width);
            float yPos = Random.Range(0, Screen.height);
            Vector3 spawnPosition = new Vector3(xPos, yPos, 0f);
            GameObject spwanObj = Instantiate(prefabToSpawn, spawnPosition, Quaternion.identity) as GameObject;
            spwanObj.transform.parent = panel.transform;
            spwanObj.transform.position = spawnPosition;
            yield return new WaitForSeconds(waitTime);
        }
    }
}

This should help u out.

Upvotes: 0

Quentin
Quentin

Reputation: 134

Indeed, you need to use RectTransform inside a Canvas. You also don't need the -1 for you List.Count. Check the link in the comment below.

I think the following script will do what you are looking for:

public class ImageSpawnerScreen : MonoBehaviour
{
    public float waitTime = 2;
    public float cubeSpawnTotal = 10;
    public List<GameObject> imagesList;

    public RectTransform panel;

    void Start()
    {
        StartCoroutine(SpawnImage());
    }


    IEnumerator SpawnImage()
    {
        for (int i = 0; i < cubeSpawnTotal; i++)
        {
            GameObject imageToSpawn = imagesList[Random.Range(0, imagesList.Count)]; // Remove -1 after count since is exclusive for int (https://docs.unity3d.com/ScriptReference/Random.Range.html)

            Vector3 spawnPosition = GetBottomLeftCorner(panel) - new Vector3(Random.Range(0, panel.rect.x), Random.Range(0, panel.rect.y), 0);

            print("Spawn image at position: " + spawnPosition);

            GameObject spwanObj = Instantiate(imageToSpawn, spawnPosition, Quaternion.identity, panel);
            yield return new WaitForSeconds(waitTime);
        }
    }

    Vector3 GetBottomLeftCorner(RectTransform rt)
    {
        Vector3[] v = new Vector3[4];
        rt.GetWorldCorners(v);
        return v[0];
    }
}

Let me know if you need more explanations.

Upvotes: 1

vmchar
vmchar

Reputation: 1323

To manage Canvas object's position you should definitely use RectTransform instead of regular transform. In your case you have to do something like :

m_RectTransform = GetComponent<RectTransform>();

As for setting position - coordinates you see on the object inside Canvas is not .position but RectTransform.anchoredPosition, so you should use it in your code. Here is an official documentation on anchoredPosition.

Upvotes: 0

Related Questions