Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
0
Question by Joorst · Nov 01, 2016 at 01:41 PM · instantiatearrayssetactiveobjectpool

How to find the active random object in an object pool array

Hi there guys.

I have a bit of a problem with a script I use to generate an endless levels. The original script uses instantiation to add the new level as the player moves in the Y direction (up). But the object being instantiated does too much heavy lifting, and I get fragmentation when a new part of the level or a new "room" is instantiated, which is why I would like to pool the prefab objects and just set them active as needed.

This is my original level generation script:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class RoomGenScript : MonoBehaviour {
 
     public GameObject [] availableRooms;
     public List<GameObject> currentRooms;
     private float screenHeightInPoints;
 
     // Use this for initialization
     void Start () {
         float width = 1f * Camera.main.orthographicSize;
         screenHeightInPoints = width*Camera.main.orthographicSize / 64f;
     }
    
     // Update is called once per frame
     void Update () {
 
     }
 
     void FixedUpdate()
     {
         GenerateRoomIfRequired ();
     }
 
     void AddRoom(float farthestRoomEndY)
     {
         int randomRoomIndex = Random.Range (0, availableRooms.Length);
         GameObject room = (GameObject)Instantiate (availableRooms [randomRoomIndex]);
         float roomHeight = room.transform.FindChild ("floor").localScale.y;
         float roomCenter = farthestRoomEndY + roomHeight * -0.678f;
         room.transform.position = new Vector3 ( 0, roomCenter, 0);
         currentRooms.Add (room);
     }
 
     void GenerateRoomIfRequired()
     {
         List<GameObject> roomsToRemove = new List<GameObject> ();
         bool addRooms = true;
         float playerY = transform.position.y;
         float removeRoomY = playerY - screenHeightInPoints;
         float addRoomY = playerY + screenHeightInPoints;
         float farthestRoomEndY = 0;
         foreach (var room in currentRooms) {
             float roomHeight = room.transform.FindChild ("floor").localScale.y;
             float roomStartY = room.transform.position.y - (roomHeight * 0.1f);
             float roomEndY = roomStartY + roomHeight;
 
             if (roomStartY > addRoomY)
                 addRooms = false;
             if (roomEndY < removeRoomY * 1f)
                 roomsToRemove.Add (room);
             farthestRoomEndY = Mathf.Max (farthestRoomEndY, roomEndY);
         }
 
         foreach (var room in roomsToRemove) {
             currentRooms.Remove (room);
             Destroy (room);
         }
         if (addRooms)
             AddRoom (farthestRoomEndY);
     }
 }

So I've tried my hand at pooling the objects and then just setting them active, but I'm missing something and just not sure exactly how to go about it. In my modified script, I've instantiated the objects in the start menu and then gotten rid of the instantiation in my "AddRoom" function, and set a random object from the array to active. Now Im not sure how to add the random active "room" to my "currentRooms" List in the "AddRooms" function.

This is the modified script:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class RoomGenScript : MonoBehaviour {
 
     public GameObject [] availableRooms = new GameObject[4];
     public List<GameObject> currentRooms;
     private float screenHeightInPoints;
     public GameObject room1;
     public GameObject room2;
     public GameObject room3;
     public GameObject room4;
     // Use this for initialization
     public void Start () {
         float width = 1f * Camera.main.orthographicSize;
         screenHeightInPoints = width*Camera.main.orthographicSize / 64f;
 
             
         availableRooms [0] = (GameObject)Instantiate (room1);
         availableRooms [1] = (GameObject)Instantiate (room2);
         availableRooms [2] = (GameObject)Instantiate (room3);
         availableRooms [3] = (GameObject)Instantiate (room4);
         room1.SetActive (false);
         room2.SetActive (false);
         room3.SetActive (false);
         room4.SetActive (false);
         }
 
     
     // Update is called once per frame
     void Update () {
 
     }
 
     void FixedUpdate()
     {
         GenerateRoomIfRequired ();
     }
 
 
 
     void AddRoom(float farthestRoomEndY)
     {
         int randomRoomIndex = Random.Range (0, availableRooms.Length);
         availableRooms [availableRooms.Length].SetActive (true);
         float roomHeight = transform.FindChild ("floor").localScale.y;
         float roomCenter = farthestRoomEndY + roomHeight * -0.678f;
         transform.position = new Vector3 ( 0, roomCenter, 0);
         currentRooms.Add (//What do I add in here?);
     }
 
     void GenerateRoomIfRequired()
     {
         List<GameObject> roomsToRemove = new List<GameObject> ();
         bool addRooms = true;
         float playerY = transform.position.y;
         float removeRoomY = playerY - screenHeightInPoints;
         float addRoomY = playerY + screenHeightInPoints;
         float farthestRoomEndY = 0;
         foreach (var room in currentRooms) {
             float roomHeight = room.transform.FindChild ("floor").localScale.y;
             float roomStartY = room.transform.position.y - (roomHeight * 0.1f);
             float roomEndY = roomStartY + roomHeight;
 
             if (roomStartY > addRoomY)
                 addRooms = false;
             if (roomEndY < removeRoomY * 1f)
                 roomsToRemove.Add (room);
             farthestRoomEndY = Mathf.Max (farthestRoomEndY, roomEndY);
         }
 
         foreach (var room in roomsToRemove) {
             currentRooms.Remove (room);
             Destroy (room);
         }
         if (addRooms)
             AddRoom (farthestRoomEndY);
     }
 }

I feel like I'm looking at this the wrong way. Any guidance would be greatly appreciated. Thank you in advance.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Anton-Korhonen · Nov 01, 2016 at 04:16 PM 0
Share

There is so much optimization you could do it hurts my eyes :) Calling transform.FindChild is not recommended to do inside a loop. Also move the roomsToRemove list creation outside the loop. You could just create it on start and then clear it at the end of the loop as there is no need to create a new list every loop.

avatar image Joorst Anton-Korhonen · Nov 01, 2016 at 04:46 PM 0
Share

Haha thanks! Always helps to have a pair of more fresh and experienced eyes contribute. Which other way could I use to get the size of that game object besides transform.FindChild or transform.Find

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Anton-Korhonen · Nov 01, 2016 at 04:09 PM

Just access the gameobject from the availableRooms list with the randomRoomIndex you generated:

 currentRooms.Add(availableRooms[randomRoomIndex]);

Did you mean to set the room with the index randomRoomIndex active? Like this:

 availableRooms[randomRoomIndex].SetActive (true);

Comment
Add comment · Show 10 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Joorst · Nov 01, 2016 at 04:36 PM 0
Share

Hi StickTick, thanks for the reply.

Yes I did mean to set the room that way, lol I overlooked that, thanks. Your solution has helped, but what I need to add to "currentRooms" is the room that is currently active in the scene, wouldn't currentRooms.Add(availableRooms[randomRoomIndex]); just add any random room from "availableRooms", even though they are not active in the scene?

avatar image Anton-Korhonen Joorst · Nov 01, 2016 at 05:07 PM 0
Share

Yes it does. I thought that's what you wanted at first, but now if i understand correctly you want the room with the farthestRoomEndY position?

avatar image Joorst Anton-Korhonen · Nov 01, 2016 at 05:08 PM 0
Share

Sorry for not clearing that up, yes that's what I want. The lowest room in Y direction.

Show more comments
Show more comments
avatar image Anton-Korhonen Joorst · Nov 01, 2016 at 07:26 PM 0
Share

I overlooked your comment. currentRooms.Add(availableRooms[randomRoomIndex]) adds the same room to the array that you set active. randomRoomIndex is just an integer and doesn't call Random.Range again.

avatar image Anton-Korhonen · Nov 01, 2016 at 06:07 PM 0
Share

@Joorst That means that the script reaches the AddRoom function without going through if(farthestRoomEndY < roomEndY). I think that not expected behaviour? At that point farthestRoomEndY hasn't been modified and it equals zero.

You talked about "the lowest room in Y direction". Does this mean that farthestRoomEndY should be the room with the lowest Y value? If that's the case, then you should reverse the if(farthestRoomEndY < roomEndY) statement. The word "farthest" makes it a little bit unclear, because farthest could be farthest up or down.

avatar image Joorst Anton-Korhonen · Nov 01, 2016 at 06:38 PM 0
Share

Can't seem to get it to work, the error stays. The most clear definition of what i would like is:

In the original script, the GameObject room was instantiated (line 30 of the original script), once that gameobject gets instantiated it would be active in the scene and would be added to the List "currentRooms".

What I need is just to replace the instantiate with setactive. Which ever object is active in the scene (room1, room2, room3 or room4), needs to then be added to "currentRooms". Ive tried currentRooms.Add (availableRooms[randomRoomIndex].activeInHierarchy), but that didn't work.

avatar image Anton-Korhonen Joorst · Nov 01, 2016 at 07:06 PM 0
Share

This is the thing that i don't understand. If you're setting the gameobject availableRooms[randomRoomIndex] active, then don't you want the exact same gameobject added to the list?

These lines of code choose a random room from the availableRooms array and set it active:

 int randomRoomIndex = Random.Range (0, availableRooms.Length);
 availableRooms [randomRoomIndex].SetActive (true);

This line (in my original answer) adds the exact same room to the currentRooms list that we just set active

 currentRooms.Add(availableRooms[randomRoomIndex]);

It does exactly the same thing as your original AddRoom code. You can ditch the larger modified code i gave you with the GameObject Room argument in the AddRoom function. I thought you needed a reference to a room but you only need those lines of code in my original answer.

randomRoomIndex doesn't get a new value when you refer it at the end of the AddRoom function. I think it's clear:

1. You choose a random room

2. You set that room active

3. You add that room to the currentRooms list

The code above does just that.

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

88 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

how to instantiate an object from an array above the previously instantiated object from the same array? 1 Answer

how to destroy the previously generated prefab so that we can populated with new set of prefabs ? 0 Answers

Instantiate players in Photon. Error: Index was outside the bounds of the array. 1 Answer

Adding a new GameObject to an Array without overriding the others 0 Answers

Instantiate() and Destroy() vs setActive() 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges