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

Resolved How to make objects in heiarchy also appear visible in the scene.

Discussion in 'Scripting' started by dragonalumni, Sep 27, 2022.

  1. dragonalumni

    dragonalumni

    Joined:
    Jun 25, 2021
    Posts:
    31
    I had a very simple block manager that created objects at XYZ in the scene. Trying to add the functionality to be able to destroy a block at XYZ has been something that's definitely a bit over my head. Currently the code
    adds blocks with material names to the hierarchy but does not add to the scene, the destroy function currently works in that it destroys objects from the hierarchy but should like the Spawn function be working with scene objects. The script is attached to a game object and the inspector is populated with the correct prefabs. However, as stated it's only making objects in the hierarchy.

    Code (csharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using System;
    6. using UnityEngine.UIElements;
    7.  
    8. public class BlockManager : MonoBehaviour
    9. {
    10.     public GameObject blockGrass1, blockGrass2, blockGrass3, blockGrass4;
    11.     Dictionary<Vector3Int, GameObject> objectRef = new Dictionary<Vector3Int, GameObject>();
    12.  
    13.     public void SpawnBlock(string material, int x, int y, int z)
    14.     {
    15.             Debug.Log("Spawn" + material +" " + x + " " + y + " " + z);
    16.             DestroyBlock(x, y, z); // remove any existing block first.
    17.             Vector3Int pos = new Vector3Int(x, y, z);
    18.             GameObject obj = new GameObject(material);
    19.             obj.transform.position = pos;
    20.             objectRef[pos] = obj;
    21.             //Instantiate(obj, new Vector3(x,0,z), Quaternion.identity);
    22.             //^ this just adds another clone to the hierarchy.          
    23.      }
    24.  
    25.     public void DestroyBlock(int x, int y, int z)
    26.     {
    27.         Vector3Int pos = new Vector3Int(x, y, z);
    28.         if (objectRef.TryGetValue(pos, out GameObject obj))
    29.         {
    30.             Destroy(obj,10);  // 10 sec delay for debug
    31.             objectRef.Remove(pos);
    32.         }
    33.     }
    34.  
    35. }
    36.  
     
  2. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    348
    Hmm I think you may have your wires crossed. If it's in the Heirarchy window, that's everything in your current scene.

    If it destroys objects from the heirarchy, it is destroying the object in the current scene.

    Are you saying the scene/heirarchy doesn't get the objects but they appear in your dictionary? Or are you saying they appear in your scene/heirarchy, but you don't see them in the dictionary?

    I think what you're saying is that the objects are appearing in the scene, but your dictionary still looks empty in the inspector? If so, Unity doesn't serialize Dictionaries, which means you can't see its contents in the inspector. To check what's in your dictionary, you'd have to either

    a) Debug.log() your dictionary elements to print its values in to the console
    b) Transfer all the dictionary values in to a List which Unity does serialize and show in the inspector
    c) Install a third party addon like Odin Inspector that allows you to serialize dictionaries
    d) have some scene text that lists your dictionary values

    If I'm wrong about your problem, please clarify :) Right now it's confusing because you're using scene and heirarchy to mean different things. Your heirarchy just displays objects in your current scene.
     
  3. dragonalumni

    dragonalumni

    Joined:
    Jun 25, 2021
    Posts:
    31
    I'm sorry I wasn't clear. What I mean is that the objects are listed in the hierarchy as normal but they do not show up in the scene as expected, and that is as solid blocks / prefabs. Instead they are invisible objects.

    This is my old method to creating objects that is modified from from a tutorial.
    Code (csharp):
    1.  
    2.         switch (material)
    3.         {
    4.             case "grass1":
    5.                   GameObject a = Instantiate(blockGrass1) as GameObject;
    6.                   a.transform.position = new Vector3(x, y, z);
    7.             break;
    8.         }
    9.  
    etc.

    In this case objects show up in the scene properly (visible) as defined by the prefabs linked in the inspector.
     
    Last edited: Sep 28, 2022
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Line 18 in your top post makes an empty GameObject().

    Those are invisible.

    Either:

    - instead Instantiate() a prefab the way you are doing in your response post

    OR

    - add Components (a MeshFilter with Mesh, a MeshRenderer with Material, plus any Collider(s) you want) to the blank GameOBject.

    Otherwise the code above is working perfectly and making empty invisible GameObjects, as I would expect it to.

    If you doubt me, replace line 18 above with:

    Code (csharp):
    1. GameObject obj = GameObject.CreatePrimitive( PrimitiveType.Sphere);
    And you will see spheres all over your scene.

    PS - if this is just a minecraft clone, you will need to check out some tutorials for that because once you get above about 30 x 30 x 30 cubes or so this will come grinding to a halt. Might not even get that far honestly... that would be 27000 GameObjects, which is a LOT.
     
    spiney199 likes this.
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,611
    That would indicate they don't have a mesh renderer, or a valid material/shader.

    Glancing at your code, you're just making empty game objects instead of instantiating prefabs or whatnot.
     
    Kurt-Dekker likes this.
  6. mopthrow

    mopthrow

    Joined:
    May 8, 2020
    Posts:
    348
    Ohh right, I see now. Sorry I didn't understand the first time.

    It's because you're making a new GameObject() on line 18 of your OP. This makes an empty game object. It has a transform and you can move it around, but there's no graphics attached to it.

    You have two choices:

    1. Add the necessary components to the object via script. For a 3d object, make a new 3d object in the scene, like a cube, and see what components it has. A Mesh Filter with a mesh assigned, Mesh Renderer with a material assigned. The Transform you get for free as a new GameObject() has that.

    2. Make your object first. Get it up and running in the scene with the right material etc, then drag/drop the final object from your heirarchy in to your Project to make a prefab. Give your script a reference to that prefab and use Instantiate to instantiate the ready made thing with graphics. All you'd need to do then is set its position.

    It looks like you've done 2 already, so instantiate those :)

    Edit Whew Kurt and Spiney too fast for me.
     
    Kurt-Dekker likes this.
  7. dragonalumni

    dragonalumni

    Joined:
    Jun 25, 2021
    Posts:
    31
    Thank you three guys for your replies, with your feedback and bit of courage I've found my actually problem.

    It has to do with trying to slim down my code and trying to pass a defined gameObject as a string through material, which apparently isn't a thing.

    This works but required me to make switch statement to convert the string passed into a concrete statement such as.
    Code (csharp):
    1.  
    2.    GameObject a = Instantiate(blockGrass1) as GameObject;
    3.  
    This of course works fine.


    Trying to pass, string material directly to Instantiate fails.
    Code (csharp):
    1.  
    2.     public GameObject blockGrass1, blockGrass2, blockGrass3, blockGrass4;
    3.     string material = "blockGrass1";
    4.     GameObject a = Instantiate(material) as GameObject;
    5.  
    I was trying to reduce the lines of code in the rewrite, ended up costing me an entire night trying to figure out just where I went wrong.

    Kurk, yes my first hour in Unity was me making a massive block of cubes, but that was over a month ago and I've moved on to something doable as an early project. I can appreciate the fact that you probably see those kinds of attempts often.
     
    Last edited: Sep 28, 2022
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,611
    You don't want to be using
    new GameObject()
    , you want to be using
    Instantiate
    to make copies of prefabs.
     
  9. dragonalumni

    dragonalumni

    Joined:
    Jun 25, 2021
    Posts:
    31
    @spiney199 Yeah sorry actually posted the wrong code block in the last message.
     
    Last edited: Sep 28, 2022
  10. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,611
    Well to answer your question.

    Because new GameObject() is just a constructor that makes a new, empty game object with nothing but the transform component that every game object has. You can click the link to see the other overloads for the constructor.

    Instantiate returns a copy of a game object. You can click the link to see its various overloads too, which handle instantiating at a specific position, rotation, and with a particular parent game object.