Chapter 3
Foundations
Now that we're familiar with the Unity Editor, it's time to starting making our game. This chapter will walk you through how to construct the objects and write the code that will comprise our game. We'll talk about software and design patterns used in Unity, along with some higher-level principles in Computer Science and how they're relevant to making games. You'll also learn how to control the player on-screen and play the player animations.
Game Objects: Our Contrainer Entities
Games in Unity consist of Scenes, and everything in a Scene is called a GameObject. You'll encounter Scripts, Colliders, and other types of elements in your Unity adventures, and all of these are GameObjects. It's helperful to thing of GameObjects as a srot of container, composed of many pieces of individually implemented functionalities. As we discussed in Chapter 2, GameObjects can even contain other GameObjects in parent child relationships.
We're going to create our first GameObject, then talk about why Unity uses GameObjects as a fundamental aspect of building games.
In the Hierarchy view, select the Create button in the top-left and select Create Empty. This creates a new GameObject in the Hierarchy view.
There are a few different ways to create GameObjects. You also could have right-clicked on the Hierarchy vew pane itself, or gone to the GameObject -> Create Empty in the top menu.
Right-click the new GameObject and select Rename. Call it "PlayerObject." This PlayerObject will contain all the logic related to the courageous player in our RPG!
Make a second GameObject and call it "EnemyObject." This EnemyObject will contain all the logic related to an enemy that our player must defeat.
As we learn how to build ga game in Unity, we're also going to learn Computer Science concepts that will make you a better programmer overall, and how those concepts will make your life easier as a game developer.
Entity-Component Design
There is a concept in Computer Science known as "separation of concerns." Separation of concerns is a design principle that describes how software is divided into modules based on the functionality they perform. Each module is responsible for a single functional "concern" that should be completely encapsulated by that module. When it coms down to implementation, a concern can be a somewhat loose and interpretive term--these concers can be as broad as the responsibility for rendering graphics on-screen, or as specific as calculating when one triangle in space overlaps with another triangle.
One of the primary motivations for separating concerns in softwar design is to reduce wastefulness seen when a developer writes duplicated or overlapping functionality. For example, if you have code that renders an image on-screen, you should only have to write that code once. A video game will have dozens or hundreds of situations where rnedering graphics to screen is needed, but the developer only had to write that code once and can resue it everywhere.
Unity builds on the philosophy of separation of concerns with a very popular design pattern in game programming called Entity-Component design. Entity-Component design favors "composition over inheritance," which is the notion that objects or "entities" should encourage code reuse by containing instances of classes that encapsulate specific functionality. Entities gain access to functionality via instances of these component classes. When used appropriately, composition can result in less code and be easier to understand and maintain.
This is different from the common design approach in which an object inherits functionality from a parent class. A disadvantage to suing inheritiance is that it can lead to deep and wide inheritance trees, whee changing one small thing in a parent class can have ripple-down effects with unintended consequences.
In Unity's Entity-Component design, something called a GameObject is the Entiry and the Components are actually called "components."
Everything in a Unity Scene is considered a GameObject, but GameObjects by themselves don't do anything. We implement all of our functionality in Components, then add these Components to our GameObjects to give then the behaviors that we want. Adding functionality and behaviours to an entiry becomes as straightforward as adding a component to that entiry.
The Components themselves can be thought of as distinct modules, only focused on one thing, and decoupled from other concerns and code.
Take a look at the following diagram to get a better idea of how we might use Entity-Component design in a hypothetical game setting. The Components that provide behaviors are in the top x-axis, and the Entities in our game are in the y-column on the left.
Graphics Renderer | Collison Detection | Physics integration | Audio Player | |
---|---|---|---|---|
Player | X | X | X | X |
Enemy | X | X | X | X |
Spear(weapon) | X | X | X | |
Tree | X | X | ||
Villager | X | X | X |
As you can see , the player and the enemy will need all four component functionalities. The spear weapon will need most of the functionality, especially physics for when it's thrown, but not audio. The tree doesn't require physics or audio--just graphics rendering and collision detection to ensure that anything bumping into it cannot pass throught it. The villager will just be walking around the scene, so they don't need physics. They might need audio thought, if we want our game to play an audio track of the villager interacting with the player.
The Unity Entity-Component design is not without its limitations, especially for large projects, and after many years has begun to show its age. It is due to be replaced in the future by a more data-oriented design.
Components: Building Blocks
Select our PlayerObject in the Hierarchy view, and notice how the values in the inspector have changed. You should see something that looks like figure 3-2.
The one element universal to all GameObjects in Unity is the transform component, which is used to determine the postion, rotation, and scale of that GameObject in the scene. We will be using the Transform component in our game when we want to move our Player character.
Sprites
If you're noew to game development, you might be asking, "What's sprite?" A sprite in the context of video game developments is just a 2D image. If you've ever seen Super Mario Brothers on Nintendo(Figure 3-3), or played a game like Stardew Valley(figure 3-4 ), Celeste, Thimbleweed Park; or Terraria, you've played games that used sprites.
Animation effects in 2D games can be achieved using a technique similar to how animated films, anime, or cartoons are made. Just like individual cells ( frames ) of a cartoon, sprites are illustrated and saved to a disk ahead of time. Displaying individual sprites in a rapid sequence can convey the impression of motion, such as a character walking, fighting, jumping, or inevitably dying.
To see the player character on screen, We need to desplay the images using a Sprite Renderer Component. We will add this Sprite Render Component to the Player GameObject. There are a few differenet ways of adding a Component to a GameObject but we're going to use the Add Component button the first time.
Select the Add Component button from the Inspector, then type in "sprite" and select Sprite Renderer( figure 3-5 ). This adds the Component to our Player GameObject. Instead we could have created a GameObject with the Sprite Renderer already attached by going to the GameObject menu, then selecting 2D Object->Sprite.
Add a sprite Renderer Component to the EnemyObject using the same technique.
Saving the scene is a good habit to get into, so let's save the Scene right now. Type Control(PC)/CMD(Mac) +s, then create a new foler and name it "Scenes." Save the scene as "LevelOne." We've created a new folder to hold this Scene and other Scenes that we'll create for our game.
Next create a folder called, "Sprites" in the Project view. As you might have guessed, this will hold all the sprite assets for our project. Create another folder underneath this Sprites folder called, "Player" and another called "Enemies." Select the Sprites folder in the Project view and then go to the folder in your Downloads directory, Desktop, or where ever you've placed the unzipped folder with the downloaded game assets for theis book.
In the downloaded assets for Chapter3, select the file named Player.png, EnemyWalki_1.png, and EnemyIdle_1.png, and drag them into the Sprites folder in the Project view. Once they're in the main Sprites folder, drag them into their respective Player and Enemies folders. Your Project view should resemble figure 3-6.
Now select the Player sprite sheet in the Project view. Notice how its properties hae appeared in the Inspector on the right. We're going to configure the Asset Import Settings in the Inspector and then use the Sprite Editor to slice up this sprite sheet into individual sprites.
Set the Texture type to "Sprite( 2D and UI)" and select the Sprite Mode dropdown picker and select "Multiple." This indicates that there are multiple sprites in that sprite sheet asset.
Change the pixels per unit to 32. We'll explain the pixels per unit, or PPU, settings when we talk about cameras.
Change Filter Mode to "Point ( no filter)." This will make the sprite texture appear blocky up close, which is perfect for the pixelated look of our artwork.
Toward the bottom, press the Default button, and select "None" for Compression.
Double-check that the propertiees in the Inspector match figure 3-7.
Press the Apply button to apply our changes, and then press the Sprite Editor button in the Inspector. It's time to slice our sprite sheet into sprites.
To be continued...
网友评论