Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
1
Question by DustyScreen · Feb 06, 2015 at 10:51 AM · editor-scriptinggameobjects

Adding/removing objects in editor mode

I create a game, where level design is done generating different level objects. So far I've been generating the level it when entering playmode, but I would like to change that, so it's done in editor mode.

I'm not that skilled in editor scripting, so I would like to know, if I'm doing it right.

My script (stripped down to the very basics of creating level objects):

 using UnityEngine;
 using System.Collections;
 
 public class LevelElementGenerator : MonoBehaviour
 {
     public int amountOfLevelElements = 1;
     public GameObject masterLevelElementGO;
     private LevelElement[] levelElements = new LevelElement[0];
 
     public void ChangeAmountOfLevelElements()
     {
         if (!masterLevelElementGO)
         {
             Debug.LogError("Master Level Element Game Object not assigned!");
             return;
         }
 
         if (!masterLevelElementGO.GetComponent<LevelElement>())
         {
             Debug.LogError("Master Level Element Game Object haven't got a Level Element!");
             return;
         }
 
         for (int i = 0; i < levelElements.Length; i++)
         {
             DestroyImmediate(levelElements[i].gameObject);
         }
 
         levelElements = new LevelElement[amountOfLevelElements];
 
         for (int i = 0; i < levelElements.Length; i++)
         {
             GameObject go = Instantiate(masterLevelElementGO) as GameObject;
             go.transform.parent = transform;
             levelElements[i] = go.GetComponent<LevelElement>();
         }
     }
 }
 
 

And the editor script:

 using UnityEngine;
 using System.Collections;
 using UnityEditor;
 
 [CustomEditor(typeof(LevelElementGenerator))]
 public class LevelElementGeneratorEditor : Editor
 {
     private LevelElementGenerator levelElementGenerator;
     
     private void OnEnable()
     {
         levelElementGenerator = (LevelElementGenerator)target;
     }
     
     public override void OnInspectorGUI()
     {
         DrawDefaultInspector();
         
         if (GUILayout.Button("Change Amount"))
         {
             levelElementGenerator.ChangeAmountOfLevelElements();
         }
     }
 }
 

It seems to work, but I'm very much in doubt, if it's the right way to do it...

Could it be done better/smarter?

Reading the DestroyImmediate documentation, I get worried. It states:

Also note that you should never iterate through arrays and destroy the elements you are iterating over. This will cause serious problems (as a general programming practice, not just in Unity).

Isn't that exactly what I'm doing? What "serious problems" does it refer to - do I face great dangers?

Any solutions or comments are most welcome! I highly value any thoughts that help me understand this better :)

Comment
Add comment
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

1 Reply

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

Answer by VesuvianPrime · Feb 06, 2015 at 04:40 PM

I make a point of setting things to null after I have called destroy. I suspect the warning in the documentation is because you're leaving a bunch of bad references in the array.

Try this:

 public static T SafeDestroy<T>(T obj) where T : Object
 {
     if (Application.isEditor)
         Object.DestroyImmediate(obj);
     else
         Object.Destroy(obj);
     
     return null;
 }

 public static T SafeDestroyGameObject<T>(T component) where T : Component
 {
     if (component != null)
         SafeDestroy(component.gameObject);

     return null;
 }

Usage:

 for (int index = 0; index < levelElements.Length; index++)
     levelElements[index] = SafeDestroyGameObject(levelElements[index]);

If we were looping over a list I would then call List.Clear(), but since we're using an array:

 System.Array.Resize(ref levelElements, 0);

Remember to clean up after yourself!

Comment
Add comment · Show 3 · 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 DustyScreen · Feb 11, 2015 at 09:47 PM 0
Share

Thank you very, very much! The solution works like a charm - and I learned a lot as well. That’s brilliant.

Just to make sure I’ve understood it correctly:

  • SafeDestroyGameObject checks if the to-be-destroyed GameObject exists - avoiding nullrefs.

  • SafeDestroy chooses the right way to destroy, depending on unity-mode.

  • Setting levelElements[index] to null cleans up the ref.

Two small followup-questions - if you please have the time :)

1) Why are you passing down the return-value of null from SafeDestroy through SafeDestroyGameObject to levelElements[index]-assignment?

 levelElements[index] = SafeDestroyGameObject(levelElements[index]);

…is a beautiful one-liner, but returning void + this would have done the same right:

 SafeDestroyGameObject(levelElements[index]);
 levelElements[index] = null;

2) The array should be used again immediately. Can I just use the following?

 System.Array.Resize(ref levelElements, amountOfLevelElements);

Thanks again man - you’re a champ!

avatar image VesuvianPrime · Feb 12, 2015 at 01:51 AM 0
Share

SafeDestroyGameObject is just a lazy way of passing a Component in order to destroy the GameObject (thus destroying the component as well).

This means that:

 levelElements[index] = SafeDestroyGameObject(levelElements[index]);

Is actually the equivalent of:

 // Will throw a null ref if level Elements contains null
 SafeDestroy(levelElements[index].gameObject);
 levelElements[index] = null;

Returning null for the one-liner is of course optional, I just find it makes complex code read a lot better.

Resizing the array afterwards is absolutely fine, especially now we are setting all the elements to null. Just make sure the array always makes sense in the places it is being used.

avatar image DustyScreen · Feb 13, 2015 at 02:01 PM 1
Share

Brilliant! I'm so eager to learn all these important details. You've been a great help! Thanks man!

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

20 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

Related Questions

How can I disable the ability to delete gameobjects in scene view? 1 Answer

Get all gameObjects of unloading scene from editor Script 0 Answers

OnObjectCreate event 1 Answer

sorting game objects when placing them in editor 0 Answers

How to store, change and delete gameobject and it's list element? 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