Lesson 34 - Referencing Instantiated GameObjects, Parenting

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


There's a very handy feature in Unity where you can pair up GameObjects in the hierarchy on the left here in a parent-child fashion. One useful aspect of this is that you can group GameObjects that logically belong together. Another one is that child GameObjects, when the child of the parent follow the parent transform. What I'm going to do right now is show you how you can parent GameObjects directly in the editor and then later I'll show you how to do it in code The first thing I want to parent is the HUD as a child to the Main Camera GameObject parent. To do this it's really easy. You just click and drag the hud over top of the Main Camera. It becomes a child to the parent, Main Camera being the parent. That's parenting in the editor. Really simple, right? What if you want to parent GameObjects that are being dynamically created at run time? How would you do this in code? For example, you may have noticed that the PowerUps and Spheres as they're being created in a hierarchy they don't have any parenting. They just all get spit out into the hierarchy in no particular grouped order. With Spheres it's going to be a little bit harder to deal with. Right now let's just parent to the PowerUps just to make it a little bit more clean in the hierarchy and show you how it's done. We can do this in code.

Let's go to the PowerUpManager. Here where we're actually spitting out the instance, you see we're creating the instance via Instantiate() method. Recalling our method overloading options, we see here that this particular method version, which is that one, it returns an Object. We can return this to an Object. This isn't exactly going to work, not yet, until we play around with it a bit. Let's just do this and see what we can do to a local GameObject. Let's try to output it to this local variable. The Instantiate() method returns an Object but we know we're going to need a GameObject for referencing where we want to do this parenting. How are we going to solve this? You might think back to polymorphism and think somewhat correctly that a GameObject is an object so we should be able to make this work immediately. Remember an Object is a more general type than a GameObject. Earlier on we saw an error in our video to do with polymorphism when trying to stuff an Object into a Combatant. Here we're trying to stuff an Object into a GameObject which is pretty much the same problem. A GameObject is derived from an object which means it's got more information than an Object. You'll be trying to go from a lower information source and turn into a higher information source.

That won't work. It would okay if we said Objects here, that would work where we're returning an Object. We're not going to them have access to GameObject-like properties and methods. It's just being treated as an Object. We know we're going to need to return the instantiated Object into a GameObject. We're going to have to do that. How do you think we would solve this? How about we cast it? Casting applies to Objects just as well as it does to value types, as we look back in an earlier video. Why don't we just cast it to GameObject. The entirety of what this method's returning will cast a GameObject. Simple, right? Let's explain a bit about what's happening here. As we've seen the Instantiate() method being used before we never did return the result of the object into anything. What we're doing here is we're taking the GameObject being returned, actually Object, and then converting it to GameObject, from the Instantiate() method and storing it into a local GameObject reference. Remember we didn't use the new keyword here. We just need this local variable to point to the GameObject being created and stored in memory that's being returned by the Instantiate() method.

Don't let this confuse you too much as to why we didn't return anything before when we use the Instantiate() method. I mean you might understandably think, "Don't we have to return the GameObject to something?" "If it has a return type, the Instantiate() method," "why didn't we return anything before?" Surprisingly, no you don't have to regard the return type at all. If a method has a return and you don't do anything with that return, say store it in a variable or put in another method's input argument and so on, the compiler just ignores the return. Remember the GameObject has already been created before the return, or actually the object is being returned as an Object within the Instantiate() method. That's it's main purpose. That space in memory was created storing that Object even if we have nothing to handle the return immediately in code. Now that we have this local reference that we've returned the Object to this local reference, GameObject gO, we can do what we want with the GameObject in code. In this case we want to just parent it to another GameObject.

For that, we access the parent property that's part of the GameObject's transform. Referencing this local reference to the instantiated Object in memory which will be this particular PowerUp. This is like our handle to that PowerUp in the hierarchy. Think about it that way within code here. With a dot accessor we'll reference the transform for this particular GameObject and then the parent property within the transform property. We'll set it equal to this GameObject's transform We'll run it now just to see how this works, keeping an eye here on the PowerUpSpawn. We expect that to become the parent of all of our PowerUps now. We see a little arrow there and there we go. It's being created and destroyed but it's being parented to the PowerUpSpawn just as we intended. As I mentioned earlier one of the coolest things and most useful things about parenting GameObjects in this way is that the child inherits the transform of the parent. That's not particularly useful in this case because the PowerUpSpawn is never moving in our scene. It's not even visible. You can imagine many cases where you might want to move a bunch of GameObjects in some group-like fashion, even if they say individually have unique movement patterns within the group. When the parent moves X amount to the left or right or whatever, so will the entire group.

For example, you could have a herd of bullets, or perhaps you have a character that has many different parts for his upper torso, lower torso and his arms, but they all have to move in unison, even if they have different animations that move independently within that group. That's a useful case of that. This was a bit of a shorter video. We basically just looked at the Unity editor's features more than anything. I've been wanting to clean things up a bit and show a few other neat things in the editor. Let's first do a little bit of organization here with our Assets folders. Let's now create in the images folder sub folders. Now we have three distinct categories I would say. Just to keep this a little bit more neat and tidy. We have Characters. We have World stuff and we have Items. Let's just be a little bit more organizational here. IceSurface would be part of the World. Characters would go there. And Items would go there. Our scrips could also use a little bit of cleanup. Let's do pretty much the same thing. When we're looking at our scripts we know where to go first. World, Items and Characters. It's really neat that you can move these into different folders and Unity will automatically update the references. It's very handy.

HeadsUp would go in the World I think. PowerUp, these two I think are best put in the Items folder. Another thing you may have noticed here is that it doesn't always show all of our text here. You can use this little slider to make the icons bigger and smaller and maybe see more or less text, depending on what you want in your Assets pane here. The other thing I wanted to show you really quickly is a really cool thing about Unity that we'll make use of a few times I'm sure. It's how Unity allows you to make changes in the inspector while the game is running. You may have noticed at some points I may have done that. I'm not sure if I exactly showed you that. When the game is running you can make temporary changes in the game world in real time, which is great for things like testing and trying things out without committing those changes. Let's just do this really quickly. Let's just show you how you can run the game and let's just in real time change the PowerUp. Instead of spawning our tabors we can spawn cubes instead. Here our referencing the inspector is to the PowerUp. Let's just change that to Cube. You can do that. There's our little Cube being spawned there. We can change other things too that we can ... Would you look at that? Moving a group of cubes. Pretty neat.

We can change other things too. It's just really useful for testing. Now as you notice when I stop playing the game it reverts back to its old state. This is just really good for trying things out. Don't be too afraid when you're making changes. I know it could be a little bit touch-and-go when you're making changes in the inspector and the editor or even in code and you're worried about forgetting what you did or not being able to undo for whatever reason. This is a great way to just test we'll be covering a lot more interesting topics in the next video. I'll see you there.

Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Please login or register to add a comment