Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Load, not load; destroy object; simply move object, what is your opinion?

Discussion in 'General Discussion' started by derf, Nov 22, 2017.

?

What do you do with objects in game you must "remove" from play?

  1. Just Destroy it

    0 vote(s)
    0.0%
  2. Make it inactive

    100.0%
  3. Move it outside the play area

    0 vote(s)
    0.0%
  1. derf

    derf

    Joined:
    Aug 14, 2011
    Posts:
    356
    Lets get back to general discussion about development.

    When you are designing your game and you know your going to have events that will change or spawn specific objects do you load them and simply have them inactive or moved out of the general play area?

    If you have to deal with interacting objects like a med kit. When a player clicks on it, how do you deal with it being removed from the player's game play area? Do you destroy it or simply move it to a position far from the player area or do you simply set its mesh renderer and collider to an inactive state?

    You can call destroy but we all know this creates garbage for the GC. I know of several designers who simply relocate the object position to say -1000 on the Y position. They also tend to load in all objects that are going to perform an action or are temporary to the scene when the scene loads up and use them as needed.

    You can set specific components to inactive like the mesh renderer and colliders so the player can no longer see the object or click on it? What is your opinion on simply "deactivating" in game objects?

    It is obviously easier to simply move an object to a point outside the scope of player influence, but do you have a limit to how many objects you will have in a scene that will relocate to the heavens before it becomes a problem for your game?

    Example, you have a specific thing that will occur when the player reaches a specific point down a corridor. Just as they reach the half way point of a corridor; you have a horror model simply walk past the intersection down the corridor as a jump scare. Now to prevent the player from running down quickly and interacting with the model what do you choose to do with the model?
     
  2. gilley033

    gilley033

    Joined:
    Jul 10, 2012
    Posts:
    1,181
    If you think of each game object as a real entity inside your game world, then realistically there is no difference between destroying a game object and deactivating it. Both "destroy" the entities presence in the world. Ideally we would be able to just destroy it and instantiate or load a new copy when one was needed, as this would better reflect the natural process of death and rebirth. However, due to obvious garbage generation issues, this is best avoided, at least for objects which are constantly being destroyed and reloaded.

    So I vote for the deactivate option. The one caveat being memory. If the object is rather large memory wise than just deactivating it will still leave it in memory. If that is an issue than destroying it is the only option, though for your particular question I doubt this is a factor to consider.

    I would not go the "move to the heavens" route or just deactivate the renderer and physics components. Both options would leave other MonoBehaviours on the game object as active and thus their Update loops would continue to run unnecessarily. These options also muddy the state of the game object in question. A game object with its renderer disabled infers that it is simply invisible, but otherwise has the same presence in the game world. Disabling it for the purpose of destroying its presence in the world confuses the state of the world unnecessarily in my opinion.
     
  3. ShilohGames

    ShilohGames

    Joined:
    Mar 24, 2014
    Posts:
    3,015
    If it is one medkit in a room, just destroy that. You don't need to worry about the GC impact of destroying one object in a scene on a relatively infrequently basis. You could alternatively just make the entire game object inactive, but that might cause memory issues if this will be a long running game on a platform with limited memory since there could be many game object sitting around in memory. Moving the game object to a distant location is a bad idea, because that would leave some of the behaviors running which would be a waste of both CPU and memory resources.

    The situation to worry about is when you have hundreds or thousands of objects getting created and destroyed really quickly. For example, if you made a shmup (shooter with lots of projectiles), the creation and destruction of those projectiles can create GC issues. You won't create and destroy enough medkits in a small period of time to create GC problems.

    And if you do build a shmup, then you can use an object pool or an instancing pool to manage the projectiles. In my current game (Disputed Space), I use instancing pool extensively because I have literally thousands of projectiles flying around in the scene. Instancing lets me completely eliminate the individual game objects normally associated with the projectiles. Obviously, my instancing solution would be complete overkill for managing a single medkit pickup in a room.
     
    Last edited: Nov 22, 2017
  4. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,617
    This statement is technically correct, but very misleading.

    Sure, the managed objects attached to a GameObject or script become "garbage" when the object is destroyed and their references are dropped. That's true. But...

    Deallocating objects does not directly cause work for the Garbage Collector, nor does it trigger garbage collection passes. Both of those things actually happen at allocation time.

    First, keep in mind that setting something to null does not "delete" it, it just drops the reference. The Garbage Collector is responsible for keeping track of which objects are referenced by other objects, so the amount of work it has to do is not based on "how many things have had all of their references dropped" but rather on "the total number of objects it has to keep track of". Implementation details aside, it has to track all of your objects in case any of them have their references dropped.

    Second, C#'s runtime environment and the Garbage Collector are designed in part based on the idea that there's little benefit to spending time/effort freeing up memory until it potentially has to be used. (That's debatable in areas where performance is important, but it's out of our control.) So the GC doesn't jump in when stuff is nulled out. (Which we might not like anyway, because it would add all sorts of other complications. There are really no easy answers here.) It jumps in when we allocate new objects if certain criteria have been met. In simplified terms, it checks to see if it can and should free up some no-longer-used memory before it goes ahead to allocate new objects.

    ...

    All of that aside, there absolutely, definitely are costs to calling Destroy(...). They just aren't what the statement above suggests that they are, and if you're doing stuff where that matters then the details may very well be important.