Controlling Game Items:
Scripting Objects And Components In Unity3D.
The Unity3D engine makes it very easy to add resources to projects, graphics, sounds, and animations are easy to drag and drop into the Project panel. Once they are in the project however they need to be bound together and infused with the logic that actually makes this heap of resources into a game. This is where your coding skills come into play. This post explores the ways in which Unity3D references resources and game objects within the code. Once you have a handle to a game object in your code the methods exposed by the game engine will allow you to manipulate the object in many ways, leaving the rest of the logic of your game in the hands of your competent C# skills.
Everything you add to the Scene panel (and therefore the Hierarchy panel) is a “Game Object” these are the components that make up your game. In Unity scripting the GameObject type tends to be used as a “catch all” type, as it is the base type of all the other types of game object, however, declaring a resource more accurately will expose more specific methods and properties. For example, Its possible to declare a camera as a GameObject and this will allow you to move it, rotate it, destroy it, and all the standard things along these lines, however if you want to change it from a Perspective type to an Orthographic type camera, you will need to cast it as a Camera type.
Game Object Methods and Properties
The static Instantiate method is used to create game objects dynamically. You’ll need a reference to an existing game object or prefab to clone, and this will be used as a parameter in the function to create the new game object. You’ll also need to specify the initial position and rotation of the new game object in the form of Vector3 and Quaternion parameters.
Instantiate(Object, Vector3, Quaternion)
It makes sense to return the new game object as a variable, you can do this by casting the returning type.
GameObject goNewObject = Instantiate(Object, Vector3, Quaternion) as GameObject;
The static Destroy function is used to destroy game objects and components. The game object will be removed from the game altogether.
Every game object has a child object of type Transform, called “transform”, that keeps the 3D game space coordinate details of the object. When the game object is selected in the editor the transform information is visible at the top of the Inspector panel. From within your code gameObject.transform.position is a Vector3 property that keeps the position coordinates of the object, and gameObject.transform.rotation is a Quaternion property that keeps the rotation information of the object. It’s possible to move and rotate the object by changing these properties, or by using the movement and rotation methods available in the transform property. To move an object you can use the Translate method, which will take a Vector3 type parameter determining the required change in the X, Y and Z coordinates.
To rotate an object you can use the Rotate function which also takes a Vector3 parameter but will this time use the values of the Vector3 as euler angles used to rotate the object on the X, Y and Z axis.
When working with game objects in your code you will need to access the components of the object. These are essentially the things you can see in the Inspector panel when the game object is selected. We can use C# generics to access the component of a game object using the GetComponent method in the form:
Accessing Game Objects Via Scripts
In order to see how your script will interact with a game object go ahead and create a simple cube object in the editor (GameObject – Create Other – Cube) and a C# script object (right click in the project panel and select Create – C# script). Call the new script “CubePosition” because you are going to use it to displace the cube using the transform property. Select your new cube and change its position properties in the Inspector panel so that the X,Y, and Z properties are all zero. Now double click on the new script and add the following code.
Attach this script to the cube (select the cube in the Hierarchy panel and drag and drop the script into its Inspector panel). You'll notice that the global parameters are exposed to the Inspector panel, this is because you declared them as public. If you click play and change these values the Update function will use the latest value to create the v3NewPosition variable and change the position of the cube accordingly.
In the above example the script has become a component of the game object and can therefore impact the game object directly. The gameObject keyword is identical to the “this” keyword in more conventional C# code, it refers to the game object that the script is attached to, and could also be ommited altogether. However sometimes you would like to impact game objects your code is not attached to, then you need to set the game objects as parameters of the code. In order to see this in action create a new empty game object (GameObject – Create Empty) and set its X, Y and Z position values in the Inspector panel to 3, then create a new c# script, this time call it RemoteCubePosition and code it as below.
Attach this script to the empty game object. You'll see that the goTheCube variable has been exposed publicly in the Inspector panel as before. You want that variable to be your cube object, so, with the empty game object selected in the Hierarchy panel, select the cube from the Hierarchy panel and drag and drop it into the goTheCube variable in the Inspector panel. You can now reference the cube from within the code in the empty game object.
So what is the RemoteCubePosition script doing? First, when it starts, its taking a reference to the CubePosition script thats on the cube object goTheCube, and setting it to its global of the same class type cpTheScriptOnTheCube. To do this you are using c# generics, calling the GetComponent method of the cube game object and matching the component you want to the CubePosition class, this gives you a reference to the CubePosition component of the cube.
Now, if you click play and, in the Scene panel move the empty game object, you'll see the cube will also move. We have therefore demonstrated how to impact the cube from a script attached to the cube itself, as well as from a script attached to another game object altogether.
When you drag and drop something into the Inspector panel when a game object is selected you are adding a component to the game object, components are objects that extend the game object, in the example above you added a script to a cube, in this case the cube is the game object and the script is the component. The Component class is the base class of all components that can be added to game objects. All components can be declared as a Component, however, as with game objects, declaring the component more accurately will expose more detailed API functions.
Adding a Component to a Game Object
If the component you want to add to the game object is visible in the Project panel, you can drag and drop it from the Project panel into the game objects Inspector panel (presuming the game object is selected in the Hierarchy panel). This is how you would add, for example, a script or a material to a game object.
If the component is one of the standard engine components, such as a physics rigid body or audio source, you then use the Component option in the top menu, with the game object selected in the Hierarchy panel drop down the Component menu at the top and select the component you wish to add.
Accessing Components via Scripts
Many of the generic engine components are available very easily via the GameObject class, as you can see in the CubePosition example above, you can reach the transform component simply as an extention of the game object, such as:
This is also true of a number of components such as rigidbody, audio, and collider. However when you are using components that you have created and added to the Project panel you have to use c# generics to access the component. We have already seen how to use the GetComponent method to access the script component of a game object, you can use the same method to get other components from the game object, in the form:
It may be easier to add the component as a public variable and just drag and drop it into the script from the editor. In order to test this, create a new cube object in the Scene panel (GameObject – Create Other – Cube) and a new material in the Project panel (right click in the Project panel and chose Create – Material). Then create a new c# script (right click in the project panel and select Create – C# script), call it “CubeColourChanger” and code it as below
You now need to add the components to the object. Select the cube and drag and drop the script and the material into the Inspector panel, then, also drag the material to the mMaterial variable of the script. If you change the value of the sColour variable in the Inspector panel to “white”, “red”, or “green” the colour of the cube will change accordingly. When designing your code it may be easier to use GetComponent or add the component to a variable, either can be an elegant solution depending on the goal of the script.
While working on a Unity3D project its likely that you will spend a lot of time creating more and more complicated game objects, adding multiple components and scripts, then setting the global variables of a script to the various game objects and components in the game. Wouldnt it be useful if you could save these objects and use them over and over again? The way you do this is through “Prefabs”. A prefab is a way to store a game object in the Project panel so that you can use it again through your code or simply so that you can drag and drop it into the Scene panel later on. In fact, prefabs are even more powerful than that, they can be used to store heirarchies of game objects and components and instantiate these with a single call.
In order to create a new prefab, right click in the Project panel and select Create - > Prefab. This will create an empty prefab, next, drag and drop any game object from the Hierarchy view into the empty prefab, the prefabs colour will change from grey to blue, this is now a “saved” version of the game object, you can drag and drop the prefab from the hierarchy view to the scene view to create a new instance, you can do this over and over again to create multiple instances of the single prefab.
If an object created from a prefab is selected in the Hierarchy panel the Inspector panel will have a new row of buttons available at the top. Select, Revert, and Apply. The Select button will select the original prefab that this object was instantiated from in the Project panel. The Revert button is used if you have made any changes to this instance and want to revert back to the prefab, and the Apply button is used if you have made changes to this particular instance that you would like to apply to the prefab.
Since the prefab is the parent of the objects instantiated from it, its possible to select the prefab in the Project panel and change its properties, this will change the properties of all of the object instantiated from that prefab.
When a game object that has been instantiated from a prefab has changed its parameters in the Inspector panel, the parameters will appear in bold text to show you that the parameter is out of synch with the values in the prefab. Its possible to click Revert to reassign the values from the prefab or Apply to save the changes to the prefab, either way the parameters will not appear in bold text, unless they include game objects that are external to the prefab. Its important to understand that only items that the prefab will be able to locate can be stored as parameters of a prefab. For example, if there is a light object in your scene that you add to a public script variable on an object instantiated from a prefab, that particular game object can see the light, but any future instantiation of the prefab wont know which light to refer to. Its possible to create a prefab of the light and add that as a parameter of a script on the prefab, its also fine to add the light as a child game object to the instantiated game object then use it in this way, however, an independent item assigned as a parameter of a script on an instantiated object cannot be saved to the prefab.
The Instantiate Command.
In order to show how to instantiate items at run time lets create a grid made up of multiple cubes, where each cube is from one parent prefab cube. First you have to create your prefab, right click in the Project folder and select Create ? Prefab, rename the prefab to “GridTile”. Then create a cube (top menu GameObject -> Create Other -> Cube) and drag and drop the cube from the Hierarchy panel into the GridTile prefab in the Project Panel.
Next create an empty game object (top menu GameObject ? Create Empty) and call it GameManager in the Hierarchy panel. Create a C# script (Project panel right click Create ? C# script) and call it “GridCreator” in the Project panel. Edit the script so it looks like this:
Add this script to the GameManager items Inspector panel and drag and drop the GridTile prefab from the Project panel to the goTile parameter of the script. Now when you click Play you will be able to see in the scene panel that a wall of cubes has been instantiated by the script.
Controlling Game Items: Scripting Objects And Components in Unity3D.
Controlling Game Items: