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 /
avatar image
0
Question by HarleyK · Mar 24, 2017 at 10:51 PM · gameobjectarraymobileoptimizationobject pool

New Object Pooling Problem

As of right now i have a spawning script that is randomly choosing a prefab from an array of prefabs and randomly picking a transform to spawn into from a set array. This works perfectly, however ive been reading into object pooling because for what im doing (mobile) i need all the optimization i can get. So i have an object pooling script thats meant for multiple prefabs, however im still having trouble in the generation script as far as implementing the object pooling for the objects in my arrays. Here are the scripts.

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class Generation : MonoBehaviour {
 
     // These are the spawn point arrays that are being used as placement for what's being spawned
     public Transform[] terrainPoints;
     public Transform[] obstaclePoints;
     public Transform[] middlePoints;
     // These are the actual list of prefabs that will be spawning
     public GameObject[] terrainSpawn;
     public GameObject[] obstacleSpawn;
     public GameObject[] middleSpawn;
     // These are the time intervals in which the spawnings will occur
     public float terrainTimer = 2;
     public float obstacleTimer = 2;
     public float middleTimer = 2;
     public float newTime = 2;
     // This is the bool that determines whether the game will be pause (this is accessed by another script, not set by this one)
     public bool isPause;
     // This is accessing the level ring of the level, this isn't set in the inspector this is set dynamically
     public GameObject theGround;
 
     public static Generation S;
 
     void Awake()
     {
         S = this;
         theGround = GameObject.Find("level ring");
     }
     
     // Update is called once per frame
     void Update () {
         // If isPause is set to false then we proceed to spawn the clones using the custom functions
         if(isPause == false)
         {
             TerrainSpawn();
             ObstacleSpawn();
             MiddleSpawn();
         }
     }
     // This is the function thats being called thats doing the spawning for terrain prefabs
     void TerrainSpawn()
     {
         // This is taking the duration of time and decreasing it by a set frame
         terrainTimer -= Time.deltaTime;
         // If this is below or equal to zero, it spawns a new clone
         if(terrainTimer <= 0)
         {
             // This randomly chooses an indexed prefab and transform and spawns something at those points
             GameObject terrainClone = Instantiate(terrainSpawn[Random.Range(0, terrainSpawn.Length)], terrainPoints[Random.Range(0, terrainPoints.Length)].transform.position, transform.rotation);
             terrainClone.transform.parent = theGround.transform;
             // This resets the duration of time for the next spawn
             terrainTimer = newTime;
 
             ObjectPoolerScript.instance.GetObjectForType("ice_env1", true);
             ObjectPoolerScript.instance.GetObjectForType("ice_env2", true);
         }
     }
     // This is the function called to spawn the obstacle clones
     void ObstacleSpawn()
     {
         obstacleTimer -= Time.deltaTime;
         if(obstacleTimer <= 0)
         {
             GameObject obstacleClone = Instantiate(obstacleSpawn[Random.Range(0, obstacleSpawn.Length)], obstaclePoints[Random.Range(0, obstaclePoints.Length)].transform.position, transform.rotation);
             obstacleClone.transform.parent = theGround.transform;
             obstacleTimer = newTime;
         }
     }
     // This is the function being called to spawn clones for the middle section prefabs
     void MiddleSpawn()
     {
         middleTimer -= Time.deltaTime;
         if(middleTimer <= 0)
         {
             GameObject middleClone = Instantiate(middleSpawn[Random.Range(0, middleSpawn.Length)], middlePoints[Random.Range(0, middlePoints.Length)].transform.position, transform.rotation);
             middleClone.transform.parent = theGround.transform;
             middleTimer = newTime;
         }
     }
 }


Thats the generation script that does the spawning.

here is the object pooler

 using System;
 using System.Collections.Generic;
 using UnityEngine;
 
 
 /// <summary>
 /// Repository of commonly used prefabs.
 /// </summary>
 [AddComponentMenu("Gameplay/ObjectPool")]
 public class ObjectPoolerScript : MonoBehaviour
 {
 
     public static ObjectPoolerScript instance { get; private set; }
 
     #region member
     /// <summary>
     /// Member class for a prefab entered into the object pool
     /// </summary>
     [Serializable]
     public class ObjectPoolEntry
     {
         /// <summary>
         /// the object to pre instantiate
         /// </summary>
         [SerializeField]
         public GameObject Prefab;
 
         /// <summary>
         /// quantity of object to pre-instantiate
         /// </summary>
         [SerializeField]
         public int Count;
     }
     #endregion
 
     /// <summary>
     /// The object prefabs which the pool can handle
     /// by The amount of objects of each type to buffer.
     /// </summary>
     public ObjectPoolEntry[] Entries;
 
     /// <summary>
     /// The pooled objects currently available.
     /// Indexed by the index of the objectPrefabs
     /// </summary>
     [HideInInspector]
     public List<GameObject>[] Pool;
 
     /// <summary>
     /// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
     /// </summary>
     protected GameObject ContainerObject;
 
     void OnEnable()
     {
         instance = this;
     }
 
     // Use this for initialization
     void Start()
     {
         ContainerObject = new GameObject("ObjectPool");
 
         //Loop through the object prefabs and make a new list for each one.
         //We do this because the pool can only support prefabs set to it in the editor,
         //so we can assume the lists of pooled objects are in the same order as object prefabs in the array
         Pool = new List<GameObject>[Entries.Length];
 
         for (int i = 0; i < Entries.Length; i++)
         {
             var objectPrefab = Entries[i];
 
             //create the repository
             Pool[i] = new List<GameObject>();
 
             //fill it
             for (int n = 0; n < objectPrefab.Count; n++)
             {
 
                 var newObj = Instantiate(objectPrefab.Prefab) as GameObject;
 
                 newObj.name = objectPrefab.Prefab.name;
 
                 PoolObject(newObj);
             }
         }
     }
 
 
 
     /// <summary>
     /// Gets a new object for the name type provided.  If no object type exists or if onlypooled is true and there is no objects of that type in the pool
     /// then null will be returned.
     /// </summary>
     /// <returns>
     /// The object for type.
     /// </returns>
     /// <param name='objectType'>
     /// Object type.
     /// </param>
     /// <param name='onlyPooled'>
     /// If true, it will only return an object if there is one currently pooled.
     /// </param>
     public GameObject GetObjectForType(string objectType, bool onlyPooled)
     {
 
         for (int i = 0; i < Entries.Length; i++)
         {
             var prefab = Entries[i].Prefab;
 
             if (prefab.name != objectType)
                 continue;
 
             if (Pool[i].Count > 0)
             {
 
                 GameObject pooledObject = Pool[i][0];
 
                 Pool[i].RemoveAt(0);
 
                 pooledObject.transform.parent = null;
 
                 pooledObject.SetActiveRecursively(true);
 
                 return pooledObject;
             }
             if (!onlyPooled)
             {
                 GameObject newObj = Instantiate(Entries[i].Prefab) as GameObject;
                 newObj.name = Entries[i].Prefab.name;
                 return newObj;
             }
         }
 
         //If we have gotten here either there was no object of the specified type or non were left in the pool with onlyPooled set to true
         return null;
     }
 
     /// <summary>
     /// Pools the object specified.  Will not be pooled if there is no prefab of that type.
     /// </summary>
     /// <param name='obj'>
     /// Object to be pooled.
     /// </param>
     public void PoolObject(GameObject obj)
     {
 
         for (int i = 0; i < Entries.Length; i++)
         {
             if (Entries[i].Prefab.name != obj.name)
                 continue;
 
             obj.SetActiveRecursively(false);
 
             obj.transform.parent = ContainerObject.transform;
 
             Pool[i].Add(obj);
 
             return;
         }
     }
 }
 


Could someone please point me into the right direction? I'm confused.

Comment
Add comment · Show 4
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 AlwaysSunny · Mar 24, 2017 at 10:51 PM 1
Share

That's an awful lot of code to ask strangers to debug. Can you point out where you think the problem is? Or at least explain exactly what's going wrong and when. Include error messages if you're getting any.

avatar image HarleyK AlwaysSunny · Mar 25, 2017 at 02:29 AM 0
Share

hope that helps

avatar image HarleyK · Mar 25, 2017 at 02:09 AM 0
Share

okay so i have created a new code that is much better for what im trying to do, i now have a custom script on the objects being spawned and the object pooling happening in the generation script. but im getting and error in these sets of lines:

    class PoolObject
     {
         public GameObject go;
         public int id = -1;
         public bool isBeingUsed = false;
     }
 
     private List<PoolObject> obstaclePool;
 
     GameObject GetPoolObstacle()
     {
         if (obstaclePool == null)
             obstaclePool = new List<PoolObject>();
         else
         {
             for (int i = 0; i < obstaclePool.Count; i++)
             {
                 if (!obstaclePool[i].isBeingUsed) // not in use
                     return obstaclePool[i].go;
             }
         }
 
         // if we made it this far, instantiate one
         GameObject newGO = Instantiate(obstacleSpawn[Random.Range(0, obstacleSpawn.Length)], obstaclePoints[Random.Range(0, obstaclePoints.Length)].transform.position, transform.rotation);
         PoolObject pO = new PoolObject();
         pO.go = newGO;
         pO.isBeingUsed = true;
         pO.id = obstaclePool.Count;
         obstaclePool.Add(pO);
         GetComponent<DestroyClones>().ID = pO.id;
         return newGO;
     }
 
 
 
     // This is the function called to spawn the obstacle clones
     void ObstacleSpawn()
     {
         obstacleTimer -= Time.deltaTime;
         if(obstacleTimer <= 0)
         {
             GameObject obstacleClone = GetPoolObstacle();
             obstacleClone.transform.parent = theGround.transform;
             obstacleTimer = newTime;
         }
     }

currently im trying to access the destroyClones script and making the public int ID into the id of the object being instantiated aka pO. But im getting this error with strange behavior

NullReferenceException: Object reference not set to an instance of an object Generation.GetPoolObstacle () (at Assets/Revamp/Scripts/Generation.cs:92) Generation.ObstacleSpawn () (at Assets/Revamp/Scripts/Generation.cs:106) Generation.Update () (at Assets/Revamp/Scripts/Generation.cs:39)

and when i click on the error it takes me to this line

GetComponent().ID = pO.id;

avatar image HarleyK · Mar 25, 2017 at 02:12 AM 0
Share
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class DestroyClones : $$anonymous$$onoBehaviour {
 
     public int ID = 0;
 
     void OnEnable()
     {
         Invoke("Destroy", 7);
     }
 
     void Destroy()
     {
         gameObject.SetActive(false);
     }
 
     void OnDisable()
     {
         CancelInvoke();
     }
 }

thats the custom code on the objects being spawned

1 Reply

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

Answer by AlwaysSunny · Mar 25, 2017 at 11:45 AM

Null Reference Exception questions are forbidden at UA. Check out the FAQ.

The reason is they always have the same answer: You're trying to access a variable that is not populated with data.

Most likely you were trying to indicate this line, but if you don't format it as code, UA cuts out stuff inside less-than and greater-than symbols:

 GetComponent<DestroyClones>().ID = pO.id;

The likely culprit is that the object with this script attached does not also have a DestroyClones script attached. Ergo when you attempt to access its "ID" variable, you encounter a null ref exception.

Are you expecting the DestroyClones script to lie on the instantiated prefabs? In that case, you need to call GetComponent on the instance. Simply call

 myObjectWhichHasADestroyClonesScriptAttached.GetComponent<DestroyClones>().ID
Comment
Add comment · Show 1 · 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 HarleyK · Mar 26, 2017 at 04:26 AM 0
Share

ah thank you that seemed to solve the problem.

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Code optimisation - how to use arrays? 4 Answers

Merging together all GameObjects of an Array? 1 Answer

script optimization (choosing an object in game by click) 1 Answer

Why is Unity loading disabled GameObjects at scene start? 1 Answer

Cells for a mobile app stacked vertically, not moving correctly 0 Answers


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