IntroductionWelcome| 00:04 | Hi! I'm Sue Blackman, and I'd like
to welcome you to the Unity 3D 3.5
| | 00:08 | Essential Training.
| | 00:10 | Unity is a multi-platform game engine
used to create mobile and desktop games as
| | 00:15 | well as real-time simulations.
| | 00:17 | In this course, we'll start off
with the basics by exploring the Unity
| | 00:20 | interface and getting familiar with the
fundamentals of 3D space, navigation, and transforms.
| | 00:27 | Next, we'll learn how to create
lush environments using Unity's Terrain
| | 00:30 | Editor and atmospherics.
| | 00:33 | We'll ease into Unity scripting,
and see how it's used to bring your art assets
| | 00:37 | to life using physics and logic.
| | 00:40 | Using a game environment created
just for this course, we'll explore
| | 00:44 | cameras, lighting, particle systems, and other
popular components of level and game design.
| | 00:50 | If you're ready to look at one of
today's most popular game engines then let's
| | 00:54 | get started with Unity
3D 3.5 Essential Training.
| | Collapse this transcript |
| Unity basics| 00:00 | In this course, we will cover the
basics of the Unity game engine.
| | 00:04 | Unity comes in two versions:
| | 00:06 | a free and a pro version.
| | 00:08 | We'll be recording using the pro
version, but most everything we cover can be
| | 00:12 | done in the free version as well.
| | 00:13 | I will let you know in the few
videos where we cover pro-only features.
| | 00:18 | The Unity game engine can be used
on either Mac or Windows machines.
| | 00:21 | As Unity game development encompasses an
eclectic mixture of skill sets, I'll be
| | 00:27 | working off the assumption that you
have a passion for creating games but not
| | 00:31 | necessarily experience in any or all
of the fields we will be making use of.
| | 00:36 | Knowledge of 2D texture making,
3D modeling and animation, programming
| | 00:41 | and real-time game engines is a plus but not
crucial to this essential training course.
| | 00:47 | In Unity, most of the functionality
has to be scripted, and while there is
| | 00:51 | a massive amount of freely available
scripts floating around in the Unity
| | 00:54 | community, figuring out how and where to
use them can be frustrating and intimidating.
| | 00:59 | To that end, I've designed this
course to take you through the basic Unity
| | 01:03 | feature set while learning how to
write scripts to tie everything together.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you are a Premium member of the
lynda.com online training library, you have
| | 00:05 | access to the exercise files
used throughout this title.
| | 00:09 | The Unity project files are
compatible with Unity 3.5.
| | 00:14 | The exercise files are in the exercise
files folders, which I've placed on the desktop.
| | 00:19 | You can store them wherever you'd like.
| | 00:22 | The exercise files for
this course are very large,
| | 00:25 | so we've cut them into smaller chapter
folders so you can download them as needed.
| | 00:29 | They reside in sub-folders
named according to the movies.
| | 00:34 | In the folders, you will find
scripts, art assets, Unity packages, code
| | 00:41 | snippets, and the Unity project.
| | 00:44 | We have also provided code snippets
in a free exercise files folder that is
| | 00:49 | available to all subscribers.
| | 00:51 | It is not necessary for you to use these files.
| | 00:54 | Feel free to use your
own files in place of them.
| | 00:57 | When you open the files, Unity will
not necessarily show the same view in the
| | 01:01 | scene window that you will see in the videos.
| | 01:04 | You may have to adjust your view using
the basic viewport navigation controls.
| | 01:09 | One more tip before we get started:
| | 01:11 | be sure to save the scene and save
the project at the end of each video.
| | 01:19 | If you're a Monthly or Annual
subscriber to lynda.com, you don't have access to
| | 01:24 | the exercise files, but you can
follow along with your own work.
| | 01:28 | Let's get started.
| | Collapse this transcript |
|
|
1. Exploring Unity 3DExploring the interface| 00:00 | When you first start Unity, the
demo project will automatically load,
| | 00:04 | Angry Bots for this version.
| | 00:06 | The Welcome screen has several useful links
that you may want to investigate at a later time.
| | 00:11 | I'm going to turn off Show at
Startup and then I'll go ahead and close
| | 00:14 | the Startup screen.
| | 00:15 | Let's start with a brief
overview of the Unity Editor.
| | 00:18 | Unlike many of the button-heavy interfaces you
may be used to, Unity's UI is fairly minimal.
| | 00:24 | The Unity Editor is made up of
several tabbed windows called views.
| | 00:29 | With the default layout, we can see
the menu bar, toolbar, Scene, Hierarchy,
| | 00:37 | Project, and Inspector views.
| | 00:40 | We can also easily tab to the Game view.
| | 00:44 | This layout is referred to as the wide
layout and is useful while the project is
| | 00:48 | fairly small, or for showing
the contents of the Scene view.
| | 00:52 | On the right side of the screen,
we've got the Layout dropdown and that will
| | 00:56 | allow us to go between the
2 x 3 layout and the wide layout.
| | 01:00 | We'll be using both those
regularly throughout the series.
| | 01:04 | The Scene view is the graphical
representation of the currently loaded scene.
| | 01:09 | In Unity, a game or project may consist
of several scenes, but only one can be
| | 01:14 | active in the Editor at any one time.
| | 01:17 | You'll be able to see 2D and 3D assets
as well as icons representing things like
| | 01:22 | cameras and lights and other
non-rendering scene objects.
| | 01:27 | This is where you'll be able to
populate your game and arrange the environment.
| | 01:32 | Besides navigating the view and
positioning the assets, the Scene view also has
| | 01:36 | its own toolbar that controls how and
what you will see and hear in the view.
| | 01:40 | Tabbing to the Game window, you'll find the
scene is viewed from usually the main camera.
| | 01:47 | The Game view is a runtime environment
where you'll be able to test your game
| | 01:51 | play while still having access to
its contents in the other views.
| | 01:55 | You'll only be able to
interact with it during Play mode.
| | 01:59 | Close to the Scene and Game views,
no matter which layout you're using, you'll
| | 02:03 | see the Hierarchy view.
| | 02:05 | It contains all of the game
objects currently in the loaded scene.
| | 02:09 | The arrows next to the object
names indicate parented objects.
| | 02:13 | At runtime, you will be able to see
objects being dynamically added and
| | 02:16 | destroyed in the Hierarchy view.
| | 02:19 | The Project view is the
repository of all your scene's assets.
| | 02:23 | This includes textures, 3D assets,
scripts, sound files, scenes--in other words,
| | 02:29 | everything associated with your project.
| | 02:32 | It mirrors the Assets folder in the
Project folder created on your machine.
| | 02:37 | Once an asset has been added to the
project, you must never move it around
| | 02:41 | outside of the Unity Editor.
| | 02:43 | The Inspector view is where you'll
be able to adjust and view properties
| | 02:47 | or parameters associated with game objects,
scripts, scenes, or the project in general.
| | 02:53 | Most changes made during Play mode
are only temporary, allowing you to
| | 02:57 | experiment without the fear of
losing your original settings.
| | 03:01 | At the far left of the toolbar,
you'll find the navigation tools.
| | 03:05 | The leftmost button deals with the
Scene view navigation, while the other three
| | 03:10 | are for transforming objects in the scene.
| | 03:13 | Several keyboard shortcuts can be used in
conjunction with the mouse for scene navigation.
| | 03:18 | The next set of buttons have to do with
the coordinate systems and pivot points
| | 03:21 | when transforming objects in the Scene view.
| | 03:24 | The Play mode buttons allow you to go
from Edit mode to Play mode, so you can
| | 03:29 | test your game and tweak
parameters to fine-tune it.
| | 03:31 | Once in Play mode, the UI darkens to
remind you that you are in Play mode and
| | 03:36 | most changes made are temporary.
| | 03:38 | The play button is toggled on an
off as there is no stop button.
| | 03:42 | The Layers dropdown allows you to select
which objects are displayed in the Scene view.
| | 03:47 | The Layout dropdown, as we've already
seen, allows you to change the UI layout
| | 03:52 | using presets, or manage custom layouts.
| | 03:56 | The menu bar is where files are
handled, projects and assets managed, game
| | 04:01 | objects created and embellished, terrains
created, and specialty features or views accessed.
| | 04:08 | The Help menu will take you quickly
to Unity's online help, user forum for
| | 04:12 | general discussion, and other useful places.
| | 04:16 | If you have a quick question that only
requires a simple answer, try Unity's Answers.
| | 04:21 | So, there is your brief
overview of the Unity layout.
| | 04:24 | We'll be starting our own
project in the next video.
| | Collapse this transcript |
| Organizing your project| 00:00 | When you first open Unity,
it loaded the demo project.
| | 00:04 | Once you've loaded a project, every
time you open Unity from that point on, it
| | 00:08 | will automatically load the last project.
| | 00:11 | So, let's start a new project of our own.
| | 00:13 | From the File menu, select New Project.
| | 00:18 | Unity's Project Wizard opens
to the Create New Project tab.
| | 00:23 | Start by setting the location.
| | 00:25 | I'm going to browse and I'm going to
create mine in my chapter 1, movie 2,
| | 00:31 | exercise file folder:
| | 00:33 | Desktop/exercise files1_5/Ch01/01-02.
| | 00:37 | At this point we need to create a new folder.
| | 00:45 | So I'm going to right-click,
New > Folder, and I am going to name
| | 00:51 | this MyFirstProject.
| | 00:58 | This is the name of your Unity
project, by the way, this folder.
| | 01:03 | And then we say Select Folder.
| | 01:06 | Once again, this folder is the new project.
| | 01:11 | Back in the Project Wizard,
we'll need to import a few packages to start
| | 01:14 | populating our project.
| | 01:17 | Packages can contain just about any
kind of asset, from scripts to art assets
| | 01:22 | to readymade scenes.
| | 01:24 | Let's start by choosing Character
Controller, and we want Scripts, and let's
| | 01:31 | grab the Terrain Assets.
| | 01:33 | We'll be adding other packages,
both Unity standard and custom, as our
| | 01:39 | project progresses.
| | 01:40 | For now, click Create.
| | 01:42 | Now, we don't want to save changes
made to the AngryBots scene, so we'll just
| | 01:47 | click Don't Save, and wait
for the packages to load.
| | 01:51 | Whenever you load a new project,
Unity closes and reopens with the new one.
| | 01:56 | You cannot have multiple versions
of Unity running on the same machine.
| | 02:00 | The first thing you may want to
do is choose the layout preset.
| | 02:04 | Since we have nothing to look at in the
Scene view, let's use the 2x3 to start.
| | 02:08 | This is over in Layout.
| | 02:10 | I'm going to choose the 2 x 3, right now.
It's on Wide, and there we have 2 x 3.
| | 02:15 | The next thing you may wish to do is change
the color scheme if you're using Unity Pro.
| | 02:22 | From the Edit menu, Preferences, under
General, if you have Unity Pro, you can
| | 02:30 | choose between the light
scheme or the dark scheme.
| | 02:38 | If you're not using Unity Pro, you
will only be able to use the Light skin.
| | 02:43 | I prefer the light skin, but I'm going
to switch back to remind you that I'm
| | 02:47 | using Pro since there are several
features that are only available with Pro, and
| | 02:51 | we can close this Preferences dialog now.
| | 02:53 | Now that we've got a bit of the setup
out of the way, let's look and see what we
| | 02:58 | have available in our project at this point.
| | 03:01 | So, we brought in several standard
assets, and we can see a folder for each of
| | 03:06 | those packages we brought in,
over in the Project folder.
| | 03:11 | Let's open them up and see what we've got:
| | 03:13 | Scripts, Terrain Assets.
| | 03:17 | Rather than opening each subfolder with
its subfolders manually, we can expand
| | 03:22 | them all by holding the Alt
key while clicking the arrow.
| | 03:25 | So, I'm going to close this up again,
hold my Alt key, and now, when I open
| | 03:30 | it, we see everything.
| | 03:32 | We can close it and open
again, and it's still expanded.
| | 03:39 | But if you hold your Alt key and
close it, next time you open it up,
| | 03:44 | it's compact again.
| | 03:46 | Let's take a few minutes to see what's in there.
I'm going to drag the view wider to see things easier.
| | 03:51 | Once again, I'll hold Alt key and
expand, and as you can see, you can resize
| | 03:59 | the views by clicking and
dragging on the separator bars.
| | 04:03 | Let's go up to the operating system and
see what we have in the Project folder.
| | 04:07 | When we created our project,
Unity created four folders:
| | 04:10 | Assets, Library, ProjectSettings and Temp.
Let's go find them.
| | 04:15 | I'm going to right-click here, open
the Windows Explorer, find my Desktop, my
| | 04:23 | 1_5 exercise files/Ch01/
01-02. Here's my project.
| | 04:31 | When I open that up, we'll see Assets,
Library, ProjectSettings, and Temp.
| | 04:38 | The only thing we're going to
deal with is the Assets folder.
| | 04:42 | When we open it up, we'll find Standard
Assets, and the three packages we brought in:
| | 04:49 | Terrain Assets, Scripts,
and Character Controllers.
| | 04:54 | The Assets folder is the only folder we
will be dealing with, and the only thing
| | 04:58 | you can do with it, outside of the
Editor, is to drop new assets into it.
| | 05:02 | See all those extra cryptic folders?
| | 05:04 | Let's go back up here.
| | 05:07 | Library, ProjectSettings, and Temps.
| | 05:09 | That's where the paths and
relationships between scripts, meshes, materials,
| | 05:14 | textures, and everything else are stored.
| | 05:17 | If you do any rearranging of assets
through the operating system rather than the
| | 05:21 | Unity Editor, the relationships will
not be updated and things will get broken.
| | 05:25 | We'll go back to the 01-02 Folder.
| | 05:29 | The next thing to understand about your
Unity project is that to create a backup
| | 05:33 | of it or to take it to another machine,
you'll need to duplicate or move the
| | 05:37 | entire project folder.
| | 05:39 | The Unity project was designed to be
used in conjunction with a sub-versioning
| | 05:43 | system such as SVN or Unity's own Asset
Server, where each time the project or
| | 05:49 | scene is saved, a backup of the
original is automatically saved.
| | 05:54 | Since the majority of casual users in
small studios probably can't justify the
| | 05:58 | expense of a sub-versioning system,
you may occasionally want to save off
| | 06:02 | versions of the project manually.
| | 06:05 | Let's close this out.
| | 06:07 | Let's go ahead and save the current
scene, even though it's only got the
| | 06:10 | default camera in it. File > Save Scene.
| | 06:15 | Back in the Editor, from the File menu,
choose Save Scene. Name it MyFirstScene
| | 06:21 | and save it in the
default location. MyFirstScene.
| | 06:28 | Before we close and reopen the project,
let's deal with the warning message that
| | 06:32 | popped up at the bottom.
| | 06:34 | Click and double-click the
message to bring up the console.
| | 06:36 | So I'm going to click, and I want to
double-click the message in the console,
| | 06:42 | and that will bring up the Script Editor.
| | 06:45 | We'll see a lot more about the console later,
but for now, we just need to fix the problem.
| | 06:50 | In line 193, it looks
like it needs an extra bar.
| | 06:54 | So add the bar, save the script,
and close the Script Editor.
| | 07:03 | Our message goes away,
and now we can close the console.
| | 07:09 | So, let's go ahead and save
the project and then close Unity.
| | 07:16 | Now, you can open a Unity
scene through the operating system,
| | 07:20 | Windows Explorer or Mac Finder.
| | 07:23 | Back in the operating system,
we need to open our folder, locate our
| | 07:29 | project, MyFirstProject, and then
you need to open it up, and from the
| | 07:35 | Assets folder--which by the way is the
Project folder, when you're inside the
| | 07:40 | Editor--we can find MyFirstScene.
| | 07:45 | Click on the newly created scene.
| | 07:47 | Unity opens with that scene loaded.
| | 07:50 | As a final tip, if on the rare occasion
your project is somehow gotten corrupted
| | 07:56 | and Unity is not able to open it,
your best bet is to manually open another
| | 08:00 | project through the operating system.
| | 08:03 | At that point, it may be necessary to
clear some of those cryptic cache folders,
| | 08:07 | but only as a last resort.
| | 08:09 | So now you've created your first scene in Unity.
| | Collapse this transcript |
| Exploring Scene view| 00:00 | Since we do not yet have anything in our
test scene, let's open the demo project
| | 00:04 | so we'll have something to
explore the Scene view with.
| | 00:07 | From the File menu, select Open Project,
and the Unity Project Wizard comes open.
| | 00:14 | What we want to do this time is we want to select
from a recently open project. We want AngryBots,
| | 00:21 | but if you've got a
different demo project, just open it.
| | 00:24 | So, select it and Open, and
Unity loads the new project.
| | 00:29 | Switch to the wide layout so the Scene
view will take up lots of real estate.
| | 00:33 | If you remember, it's over on this far
dropdown, I'm going to switch over to Wide.
| | 00:38 | Notice that the Hierarchy view shows
only the default camera of the new scene.
| | 00:44 | In the Project view, locate the Scene icon for
the project and click on it to load the scene.
| | 00:50 | Here it is, right here, so we'll click it in.
| | 00:54 | If you are using a project other than
Angry Bots, you may need to go looking
| | 00:57 | for a scene to open.
| | 00:59 | In Unity, scenes are like levels,
so there may be several of them and the author
| | 01:03 | may have created a Scenes folder to hold them.
| | 01:05 | Scenes may also contain nothing but
menus, so you may need to open a few before
| | 01:10 | you find one with level-type content.
| | 01:13 | In Angry Bots, you will see something like this.
| | 01:16 | Let's experiment with the Scene view toolbar.
| | 01:19 | At the left, you will see it set
to Textured for the Display mode.
| | 01:24 | Let's click on that and
experiment with some of these.
| | 01:28 | Wireframe is going to leave you with a
bunch of black wires. Sometimes it's useful.
| | 01:35 | And Text-Wire--that's the other one
that we'll probably be using occasionally--
| | 01:39 | is going to show both the objects,
the textures, and you can also see the
| | 01:44 | wires in there as well.
| | 01:45 | So those are two we are going to use most often:
| | 01:48 | Textured and Text-Wire.
| | 01:49 | We're going to go ahead and
switch that back to Textured now.
| | 01:54 | The next button is the RGB dropdown,
and it offers several other options.
| | 01:58 | The next one though is the Lighting toggle.
| | 02:02 | In Angry Bots, if I toggle the Scene
Lighting icon off and on, there's very
| | 02:06 | little difference, indicating most of
the lighting has been baked into textures
| | 02:10 | or that the lights in the scene have
been limited in range or will only be
| | 02:14 | activated at certain times.
| | 02:16 | The next button, the Game Overlay
button, toggles things like background and 2D
| | 02:21 | objects off and on in the view.
| | 02:23 | In Angry Bots, the background images
toggles off and on and the grid appears.
| | 02:30 | To the right of the Overlay button is
the icon that toggles sound off and on.
| | 02:34 | You will only hear the sound if an
object with an audio component is selected.
| | 02:38 | The Gizmos dropdown on the right-hand
side lets you see which 2D icons are
| | 02:45 | being used to represent things like
lights, cameras, and other objects, as well
| | 02:49 | as letting you assign custom icons.
| | 02:52 | You can allow scaling of
icons or adjust the size.
| | 02:58 | If I increase the size, you can see
that there are actually lots of lights and
| | 03:02 | other icons in the scene.
| | 03:03 | Enabling scaling prevents the icons
from cluttering the scene and blocking
| | 03:08 | out the 3D geometry.
| | 03:09 | In the next video, we'll be
going over scene navigation.
| | Collapse this transcript |
| Navigating Scene view| 00:00 | You're probably itching to
start looking around the scene.
| | 00:03 | Navigating the Scene view is
easily done with keyboard and mouse.
| | 00:07 | Position the cursor inside the Scene
view, and to pan, hold the middle-mouse
| | 00:11 | roller down and move the mouse back and forth.
| | 00:15 | Note that the Pan button becomes
active up on the navigation toolbar.
| | 00:20 | If you have no middle-mouse roller,
click on the icon, hold the left-mouse
| | 00:25 | button down while moving the mouse.
| | 00:28 | Hold the right button down while moving the
mouse and you can look up, down, and around.
| | 00:35 | This time the button changes to the Orbit icon.
| | 00:39 | To zoom the viewport, hold the Alt
key plus the right-mouse button and move
| | 00:45 | the mouse up and down.
| | 00:50 | For Flythrough mode, hold the right-mouse
button down, and use the W, A, S, D keys.
| | 00:58 | W, A, S, D. Plus Q and E for up and down.
| | 01:06 | Q, E. This puts you into a
quick first-person view navigation.
| | 01:14 | You can also select an object in the
Hierarchy view and press the F key.
| | 01:19 | Let's find the Player.
| | 01:22 | So, if I click on the Player, and I
press my F key, as long as my cursor is in
| | 01:27 | the viewport, it zooms right to him.
| | 01:30 | This centers the Scene view and
pivot point on the selected object.
| | 01:35 | The arrow keys allow you to
move around on the X and Z planes:
| | 01:39 | left, right, up, down.
| | 01:45 | For CAD and Max users, Y is up in the
world rather than Z. I would recommend
| | 01:51 | that you use a three-button mouse,
but if you only have a one-button mouse
| | 01:55 | available, you can check the
Unity manual for more instructions.
| | 01:58 | We'll go there quickly.
| | 02:01 | Help > Unity Manual. And we want to
look up Scene View Navigation, and you can
| | 02:09 | look through that for different options.
| | 02:13 | So we'll close that. And back in the
Unity Editor, the Scene Gizmo--this little
| | 02:18 | guy up here--lets you switch between
perspective views and orthographic views.
| | 02:23 | If I click on this one, it swings
around. And you can keep your mouse in one
| | 02:29 | spot and get the different views:
| | 02:33 | top view, back view. And you can go back
into perspective by clicking on the center cube.
| | 02:41 | At this point, I would encourage you
to spend some time navigating around the
| | 02:45 | scene to get comfortable with the controls.
| | 02:47 | In the next video, we'll be
creating some Unity objects of our own.
| | Collapse this transcript |
| Creating objects| 00:00 | Unity allows you to create several
different types of primitive objects.
| | 00:04 | Primitives are objects that can be
described by a set of parameters such as a
| | 00:08 | sphere's radius, a cylinder's
height, or a plane's length or width.
| | 00:12 | In Unity, you won't be able to change
the number of segments or modify the
| | 00:16 | primitives, but they can be quite useful as is.
| | 00:19 | Let's open the project we started in
the earlier video, or open the project from
| | 00:24 | this video's exercise files folder
through the Open Other button. So File >
| | 00:31 | Open Project, and you can either open
it here if you have your own file or if
| | 00:38 | you are using the exercise files folder,
Open Other, locate it, and in chapter
| | 00:48 | 01-05, MyFirstProject.
| | 00:52 | When we are opening this way, we don't
have to open the scene; we are opening
| | 00:56 | the entire project, so Select Folder.
| | 00:59 | And we don't need to save the AngryBots scene.
| | 01:03 | We won't be adding very many
objects, so let's use the Wide layout.
| | 01:08 | We are already in it on
this one, so we are good to go.
| | 01:11 | Make sure the Game
Overlay button is toggled off.
| | 01:16 | And now we can see the grid.
Let's start by making a plane.
| | 01:19 | From the GameObject menu, select
Create Other and click on Plane.
| | 01:25 | If you haven't messed around in the
Scene view yet, the plane will be created at
| | 01:29 | 0, 0, 0, as can be seen in
the Inspector, in the Transform section.
| | 01:35 | In the last video, we learned how to
navigate the Scene view in general, and
| | 01:39 | while that's useful, as soon as we
start dealing with objects on an individual
| | 01:43 | basis, we will want a more
direct way to zoom in on them.
| | 01:47 | Now that we have an object that we
want to work with, we can do just that.
| | 01:51 | Select the plane in the
Hierarchy view and double-click it.
| | 01:56 | The plane becomes the focus of the
Scene view, and you can zoom closer if you
| | 02:01 | need to, using Alt and the right mouse.
| | 02:08 | You can also use the
middle-mouse roller to zoom back and forth.
| | 02:17 | At this point, if you orbit the view--
Alt+Left Mouse--it orbits around the plane.
| | 02:26 | If you are new to 3D, you will also
notice that when you tip the view to look
| | 02:30 | under the plane, you can no longer see it.
| | 02:34 | In polygon modeling, objects are
represented by surfaces only and are
| | 02:38 | not actually solid.
| | 02:39 | The surface is drawn only on
one side: the face normal side.
| | 02:44 | A normal is an imaginary line which is
perpendicular to the surface of the face
| | 02:48 | or triangle, and its direction indicates
the side the surface will be drawn on.
| | 02:52 | Another way to focus or find an
object in the scene is to use the F key on your keyboard.
| | 02:58 | Pan the view, hold down the middle-
mouse button. and shift the view so that the
| | 03:05 | plane is still selected in the
Hierarchy view but is off to the side.
| | 03:09 | Make sure that the plane is still
selected in the Hierarchy view and the cursor
| | 03:13 | is in the Scene view, and then
click the F key on your keyboard.
| | 03:18 | Once again, the view
changes to focus in on the plane.
| | 03:22 | Before you start adjusting the
view, let's create another object.
| | 03:27 | From the GameObject menu, this time
select Create Other > Cube. Create Other > Cube.
| | 03:35 | As long as you didn't change the view
after you focused in on the plane, the
| | 03:39 | cube will come in at
0, 0, 0, just like the plane.
| | 03:42 | But since, unlike the plane, it has a height,
| | 03:45 | it is buried halfway through the plane.
| | 03:48 | Let's see what happens if we shift the view.
| | 03:49 | Zoom and pan so the
objects are off to one side.
| | 03:57 | Create another cube:
GameObject > Create Other > Cube.
| | 04:03 | Instead of being created at 0, 0, 0,
it appears in the current center of the Scene view.
| | 04:09 | If we look over the Transform section
of the Inspector, we can see that it
| | 04:13 | is not at 0, 0, 0.
| | 04:14 | The other thing to note is that
Unity does not increment game names of new objects.
| | 04:21 | If you look over at the
Hierarchy view, we now have two cubes.
| | 04:25 | If you have 123 rocks in your scene,
you probably have no reason to give
| | 04:30 | them each unique names.
| | 04:32 | If, however, you do need to be able to
access a particular object, you will
| | 04:36 | want to rename it.
| | 04:37 | Select the latest cube in the Hierarchy view.
| | 04:40 | In case, you can't remember which it is,
as long as you are not in the viewport
| | 04:44 | navigation mode, the object's
transform gizmo will let you know which one
| | 04:48 | you've selected.
And here is the transform gizmo.
| | 04:53 | Left-click on it in the Hierarchy
view to put it into Rename mode.
| | 04:57 | Give it a unique name to
differentiate it from the original cube.
| | 05:01 | I am just going to add a 2.
| | 05:04 | When you have a large number of objects
in your scene, you will also be able to
| | 05:08 | use the Hierarchy search
feature to find objects.
| | 05:11 | Click in the field next to the Q and type "cube."
| | 05:15 | So if I type "cube," when you press
Enter, the hierarchy is filtered to show
| | 05:21 | objects with cube in their name,
and the Scene view grays out all
| | 05:25 | non-filtered objects.
| | 05:26 | Since ours was gray covered to begin
with, it doesn't look much different.
| | 05:31 | The main point here is to think
about your naming conventions.
| | 05:34 | They can help you to quickly
locate objects in a large scene.
| | 05:37 | Go ahead and turn off the filter by
clicking the little X to the right of the field.
| | 05:42 | Although Unity doesn't have any formal
alignment system, there are a few options
| | 05:47 | for moving objects to the same place.
| | 05:50 | The most obvious and most tedious is
to copy and paste the transforms of
| | 05:55 | one object to another.
| | 05:57 | When we get to hierarchies in
parenting, you will find that this method
| | 06:00 | won't always work.
| | 06:01 | The quickest way to get an existing
object over to another's location is to
| | 06:06 | select the target object. In this
case our target object will be Cube2.
| | 06:11 | This time I am going to double-click
on the cube's name in the Hierarchy
| | 06:15 | to focus in on it.
| | 06:16 | Now I am going to select the original
Cube and to move this guy over to Cube2, I
| | 06:24 | am going to go to GameObject > Move To view.
| | 06:28 | And now our cube is sitting in the same
exact spot as Cube2, as we could tell
| | 06:36 | if we pulled it away.
| | 06:38 | And I am going to do an undo to
pop it back into the same spot by
| | 06:42 | clicking Ctrl+Z to undo.
| | 06:45 | This won't align the orientation to
match, but usually you only want to get an
| | 06:49 | object close so you can
manually finish its placement.
| | 06:53 | Unity has a very nice set of snapping
tools that we will investigate in a later
| | 06:56 | chapter when we are building
with imported modular objects.
| | 07:01 | Before we save the scene,
let's look at the title bar.
| | 07:04 | It says Untitled.
| | 07:06 | Since it was just an empty scene,
you probably didn't notice when we reopened
| | 07:09 | the project that we neglected to
open the scene that we saved last time.
| | 07:13 | So this time we will use Save
Scene As to overwrite the first one.
| | 07:18 | So from File > Save Scene as, we'll
chose MyFirstScene, and we'll overwrite it.
| | 07:26 | And yes, we want to replace it.
And from File > Save Project as well.
| | 07:33 | In the next video, we will delve
into transforms and coordinate systems.
| | Collapse this transcript |
| Transforming objects| 00:00 | If it's not already open, let's open our
MyFirstProject from Ch01, video six.
| | 00:08 | And we are going to open the project file
first and then the Assets folder, and then
| | 00:15 | we look for our scene with the icon next to it.
| | 00:19 | Double-click it and our
scene will eventually open up.
| | 00:23 | Check the title bar to make
sure MyFirstScene is loaded.
| | 00:26 | If not, you'll need to find it in
the Project view and double-click it to open in there.
| | 00:31 | Our little scene is pretty minimal now,
so now is a good time to learn about
| | 00:36 | transforms and coordinate systems.
| | 00:37 | Transforms are position, rotation, and scale.
| | 00:41 | The concept of position as a location
of an object in 3D space and rotation--
| | 00:47 | its orientation in 3D space--is easy
to grasp as being discrete from the actual object.
| | 00:54 | Scale is a bit more confusing, as an
object that has been scaled to half height
| | 00:58 | could look the same as an object
that was that height to begin with.
| | 01:01 | An object that was scaled to half
height, or 0.5, can be returned to its original
| | 01:07 | height with a scale value of 1.
| | 01:10 | Let's start with the position transform.
| | 01:12 | First off though, we've got two cubes
in here and I think we want to get rid of one of them.
| | 01:18 | If we click on Cube number 2 and
right-click, we can click on Delete.
| | 01:25 | You can also delete it by using
the keyboard once it's selected.
| | 01:29 | Now if we click on the cube in the
viewport or the Hierarchy and we are not in
| | 01:33 | Scene navigation mode,
we can see its transform gizmos.
| | 01:38 | If you are in navigation mode,
you will need to press the Transform button on
| | 01:42 | the toolbar to get into navigation mode.
| | 01:45 | The gizmo is color-coded were RGB
equals XYZ. In other words, red represents
| | 01:51 | X, green represents Y, and blue
represents Z. If you grab, say, the Z, or blue,
| | 01:59 | arrow, and drag, the cube is
constrained to moving along the Z direction.
| | 02:05 | Let's try moving the cube in the
three directions with the gizmo arrows.
| | 02:08 | While you are transforming the cube's
position, watch the Position values change
| | 02:17 | in the Inspector over here.
| | 02:24 | Note also that an active arrow turns yellow.
| | 02:27 | Now take a look at the colored
squares in the center of the gizmo.
| | 02:31 | These will constrain the movements to
two directions, indicated by the plane
| | 02:36 | the square lies on.
| | 02:38 | If we look at the colors, the color of
the square indicates the only direction
| | 02:42 | the object can't go.
| | 02:47 | If I select the red one, we can go up
into the Z, but it can't move forward
| | 02:54 | in the X. If we drag the green square,
the cube moves in both the X and Z
| | 03:00 | directions, as you can see by watching
the Position values change in Inspector again.
| | 03:04 | Moving an object on the X or Z along
with the Y can often produce unwanted
| | 03:12 | results in the perspective view,
| | 03:13 | so don't be shy about switching
to an orthographic view to help
| | 03:17 | position objects.
| | 03:18 | I am going to click the Scene gizmo to
put myself into an orthographic viewport.
| | 03:25 | Now when I move the X and the Z,
I know exactly where the cube is going.
| | 03:31 | And when I am finished, I can
click the center cube to put me back into Perspective.
| | 03:36 | Middle-mouse pan brings my
cube back into the viewport.
| | 03:41 | Let's take a look at rotation next.
| | 03:44 | With the cube still selected,
switch to the rotation by clicking the Rotation
| | 03:48 | button in the toolbar or pressing the E key.
| | 03:54 | The rotation gizmo appears as several circles.
| | 03:57 | The colors represent the axes
the object will be rotated on.
| | 04:01 | Start by rotating the cube on the Y axis--
| | 04:04 | that's the green circle--
about a quarter of a turn.
| | 04:06 | The Inspector reports the rotation in degrees.
| | 04:12 | So I have just rotated
this guy about -43 degrees.
| | 04:16 | With the introduction of rotation,
we are faced with the concept of
| | 04:20 | coordinate systems.
| | 04:21 | In Unity, the choice is simple:
World or Local, as in local to the
| | 04:26 | selected object.
| | 04:28 | If you toggle the coordinate system
button, you can see that in World the
| | 04:33 | gizmo is aligned with the scene gizmo,
while in Local, it's aligned with the
| | 04:37 | object itself.
| | 04:39 | We are going to go up here. Tight now
it's in Local and there it is in Global.
| | 04:44 | So in Global, it's aligned with the world.
| | 04:47 | In local, it's aligned with the object.
| | 04:50 | The gray outer circle, which we might
be able to see better if we zoom out a
| | 04:55 | bit--there we go--the great outer
circle will rotate the object on a plane
| | 04:59 | parallel to the viewport.
| | 05:01 | Note that once the object has been
rotated on more than one axis, all numbers
| | 05:05 | will change with each additional rotation.
| | 05:07 | So if I rotate this guy and then that
guy, now every time I rotate one, the
| | 05:16 | rest all rotate as well.
| | 05:19 | Let's put the cube's
rotation back to its original value.
| | 05:23 | Enter 0 in each of the rotation
fields by clicking to highlight the current
| | 05:27 | value and typing 0. So click,
type 0; click, type 0; and click, type 0.
| | 05:40 | Unity will add the decimal point when necessary.
| | 05:43 | The coordinate system used for
stationary objects is usually not an issue since
| | 05:47 | most can easily use either
Local or World for rotation.
| | 05:52 | If a stationary object rotates off Y in
World space or Z in Local space to give
| | 05:58 | the same result, we really don't care.
| | 06:00 | We just need to be aware of which we are using.
| | 06:03 | An object that is not stationary,
however, will almost always be transformed
| | 06:07 | in local space.
| | 06:09 | Let's select the cube again and set
the coordinate system to Local space.
| | 06:14 | In this case we already are there.
| | 06:16 | In the Inspector, let's
set its Y Rotation to 45,
| | 06:22 | switch over to Move, and move the
cube in the positive X direction, the
| | 06:29 | direction the arrow points.
| | 06:33 | Rotate the cube in the Y again.
| | 06:36 | This time I am going to position my
cursor over the Y and I can drag in the
| | 06:41 | Inspector to rotate it.
| | 06:43 | And then we'll move it
forward in the X position again.
| | 06:48 | No matter which way the cube is facing,
in Local coordinates it will always move
| | 06:54 | forward with the same arrow.
| | 06:56 | As you can guess, this is
extremely important for transforming
| | 06:59 | characters throughout a scene.
| | 07:02 | The last transform to look at is Scale.
| | 07:04 | You've probably got the hang
of the X-Y-Z stuff by now.
| | 07:07 | Selecting and dragging any of the
three colored cubes will produce a
| | 07:11 | non-uniform scale.
| | 07:12 | So let's turn on Scale and non-
uniform in the X, non-uniform in the Y, and
| | 07:21 | non-uniform in the Z. I am going to
use my middle-mouse button to pan back
| | 07:25 | into the center again.
| | 07:26 | There is currently no way to scale two
axes at once though, so your best bet is
| | 07:32 | to do a uniform scale first--uniform is
the center one--and then do a non-uniform
| | 07:38 | scale on the single axis to
achieve the result you are going for.
| | 07:43 | Try making a large load box.
| | 07:46 | You may have noticed that the
coordinate system is grayed out and set to Local.
| | 07:52 | If you think about it, performing a
non-uniform scale on a rotated object would
| | 07:56 | produce a skewed result,
| | 07:58 | so Unity removes the
temptation by removing the option.
| | 08:02 | Next to the coordinate
system is the Pivot button.
| | 08:04 | Since Unity's native objects all have
the pivot points in their centers, we'll
| | 08:08 | hold off on pivot points for now.
| | 08:10 | To recap, transforms are
position, rotation, and scale.
| | Collapse this transcript |
|
|
2. Exploring the Terrain EditorSetting up the terrain geometry| 00:00 | Let's continue with MyFirstProject.
| | 00:03 | We're going to be using the Terrain
Editor in this chapter, so let's go ahead
| | 00:06 | and make a new scene in the project.
| | 00:08 | From the File menu, select New Scene.
And next we're going to go ahead and save
| | 00:17 | our scene: Save Scene As.
| | 00:19 | We're going to name this
scene TerrainTest. Enter.
| | 00:28 | And we'll let it save in the default location.
| | 00:31 | So now here's our new scene,
TerrainTest, and our original Scene, MyFirstScene.
| | 00:38 | And if you didn't notice it before,
it's now pretty clear that the Project view
| | 00:42 | is always listed alphabetically.
| | 00:43 | As you create your game, it will be up
to you to keep your assets organized,
| | 00:48 | so let's get started by
creating a folder just for scenes.
| | 00:52 | If we right-click in the Project view
we can bring up the Create menu, and
| | 00:59 | we're going to create a folder.
| | 01:02 | So let's name this new folder Scenes.
| | 01:08 | Now we can drag our two scenes into the folder.
| | 01:14 | Okay, let's make a terrain.
| | 01:16 | From the Terrain menu, select Create
Terrain, select the terrain in the Hierarchy
| | 01:23 | view, and then let's find or
focus it by double-clicking on it.
| | 01:29 | The first thing worth noting is
that it comes in at 0, 0, 0.
| | 01:33 | And its pivot point, though, is at
a corner rather than its center.
| | 01:37 | Let's get a closer look.
| | 01:39 | Put the cursor over the terrain in
the Scene view and press the F key.
| | 01:45 | We're zoomed in to a very
close view of the terrain.
| | 01:48 | If we move the cursor off the terrain
again and press F, it zooms out so we
| | 01:54 | see the whole terrain.
| | 01:56 | If you look in the Inspector, you'll find
nothing that tells us how big the terrain is,
| | 02:00 | so that would be the
first thing we want to set up.
| | 02:04 | From the Terrain menu,
we're going to select Set Resolution.
| | 02:13 | This is where we will determine the size
and height of the terrain plus the size
| | 02:17 | of the various bitmaps that will be
used internally to keep track of the
| | 02:20 | topography, terrain meshes,
and texture placement.
| | 02:24 | The terrain defaults to 2000 by
2000 by 600 for the maximum height.
| | 02:30 | In Unity one unit is considered to
be one meter, or about three feet,
| | 02:36 | so the default is a pretty big chunk of terrain.
| | 02:39 | It's tempting to start with a large
terrain just because you can, but remember,
| | 02:44 | your player would need to traverse it,
and preferably not by placing a soda can
| | 02:48 | on one of the arrow keys.
| | 02:51 | So let's go ahead and reduce the size
of our test terrain to 200 by 200 for the
| | 03:00 | width and length, and we will
use maybe 400 for the height.
| | 03:03 | We'll leave the rest of this
stuff on the default numbers.
| | 03:08 | And we'll go ahead and hit Set
Resolution. And then I'm going to use middle-
| | 03:12 | mouse roller to zoom in. And you can even
double-click on the middle-mouse button
| | 03:22 | to zoom in on an object in the viewport.
| | 03:25 | The next step is crucial.
| | 03:28 | We need to decide how deep we want to
be able to paint depressions for lakes,
| | 03:32 | rivers, pits, or any other low-lying features.
| | 03:35 | From the Terrain menu, we're going to
select Flatten Heightmap. And we'll set the
| | 03:44 | Height to 100 and click Flatten.
| | 03:51 | What this means is that when we're
painting a terrain lower it cannot go any
| | 03:57 | lower than 100 meters.
| | 03:59 | The crucial thing about this step is
that if you do it after painting your
| | 04:04 | topography, all of your hard work will be lost,
| | 04:08 | so remember to do this one
right after setting the resolution.
| | 04:13 | Okay, now we're ready to
start creating our environment.
| | 04:16 | We'll do that in the next video.
| | Collapse this transcript |
| Painting the topography| 00:01 | In this video, we'll be using the
first three terrain editor tools to
| | 00:04 | create some topography.
| | 00:05 | Let's select the terrain and get started.
| | 00:08 | In the Inspector, move the cursor over the
toolbar to see the tooltips for each tool.
| | 00:14 | We're going to be using the first three.
| | 00:16 | So let's use the first one,
raise and lower the terrain height.
| | 00:20 | I'm going to zoom out so I can
see all of my terrain to start.
| | 00:24 | As you can see, there are
lots of brushes to start with.
| | 00:27 | We may as well start with the default,
but let's adjust the size of the brush
| | 00:31 | before we get going.
| | 00:33 | And I'm going to make it large so we can
see it and when I bring it into the viewport,
| | 00:37 | you can see it goes blue.
| | 00:39 | This shows the brush size.
| | 00:41 | We'll go ahead and start painting
by holding the mouse button down--
| | 00:44 | that's the left mouse button--
and moving the mouse around.
| | 00:48 | The Opacity setting controls the strength of
the brush, so I'm going to reduce it a bit.
| | 00:53 | Now when I paint,
the results are not so drastic.
| | 00:57 | You can also see that painting is additive.
| | 01:00 | If we keep painting over
something, it gets higher and higher.
| | 01:04 | Let's check out a few of the other brushes.
| | 01:06 | Many are very good at adding texture to
the terrain when the opacity is quite low.
| | 01:12 | Let's try this one.
| | 01:13 | A simple click gives kind of a nice result.
| | 01:17 | You may have noticed that when you
first click with the brush the texture has
| | 01:21 | more definition than after you let go.
| | 01:23 | Unity's Terrain Editor has a built-
in LOD, or Level of Detail, feature.
| | 01:27 | Not only is the terrain polygon
resolution adjusted for the features we paint on
| | 01:31 | it, it's dynamically adjusted
according to the distance from the camera.
| | 01:35 | As you get further away,
the terrain mesh is reduced.
| | 01:39 | Most meshes show their wireframes when
selected, but the terrain mesh does not.
| | 01:44 | To see what's going on with it, we can
change the viewing mode to Tex-Wire.
| | 01:49 | Now you can see the resolution increase when
you zoom in and out, as well as when you paint.
| | 01:57 | Let's set the viewing back to
Textured and try some depressions.
| | 02:08 | For depressions we hold the Shift key
down. And that is also additive, but it
| | 02:14 | will bottom out at the 100 meters
that we set in the flattened heightmap.
| | 02:20 | The next tool over is the Set Height tool.
| | 02:23 | This one allows you to specify height
limits within the maximum height we set
| | 02:27 | when we set first set up the terrain.
| | 02:29 | Under the height, you can see that the
range will top out at 400 meters, the
| | 02:34 | height we specified.
| | 02:36 | This one though I'm going to set to
about just over a hundred and now when I
| | 02:41 | paint, we'll get a nice low plateau.
| | 02:45 | You can also find out where you are
on this one. With the Set Height tool
| | 02:51 | when you hold your Shift key, it will
sample the height range that your cursor is over.
| | 02:57 | So if we watch over in the Inspector
and I move my cursor over this mountain
| | 03:02 | peak and click Shift, then it
sets it to whatever height that was.
| | 03:07 | So it's an easy way to find out how high
you are before you start painting again.
| | 03:11 | Note that the brush size and opacity
are retained between these two tools.
| | 03:16 | The next tool is the Smooth Height tool,
perfect for softening edges of jagged
| | 03:20 | peaks left over from the other tools.
| | 03:22 | So here is the relax. And if we turn the
Opacity up, you'll see much more result
| | 03:29 | here. Then it sort of
lowers and flattens things.
| | 03:34 | If you have gone beyond the point of no
return, like I sometimes do, feel free
| | 03:38 | to flatten the heightmap
again for a clean slate.
| | 03:41 | And we'll set this to 100 again and Flatten.
| | 03:47 | We still need our terrain,
| | 03:48 | so I'm going to press
Control+Z to get it back again.
| | 03:52 | In the next video we'll start
painting textures on our terrain.
| | Collapse this transcript |
| Painting the terrain textures| 00:00 | Unity has several very nice terrain
textures included in the terrain assets
| | 00:04 | package we included when
we first set up the project.
| | 00:07 | If you don't see the Terrain Assets
folder inside the Standard Assets folder,
| | 00:12 | you can easily get them through the
Assets > Import Package > submenu.
| | 00:18 | Assets > Import Package, and
the submenu shows it right here.
| | 00:26 | Ours is here, so we can go ahead.
| | 00:29 | If you wish to use your own images for
the terrain, make sure they tile in all
| | 00:33 | directions, are based to size such as
512 by 512, and are already loaded in the
| | 00:39 | project, either through the operating
system or through Assets > New Assets.
| | 00:45 | Once inside the project, you may wish to
create a folder for your own textures.
| | 00:50 | The first texture we add to our
terrain though will fill the entire surface,
| | 00:54 | so we need to choose accordingly.
| | 00:56 | Once again, we select the terrain, and
in the Inspector we are going to use
| | 01:02 | Paint Terrain Texture.
| | 01:03 | And the first thing we need to add is a texture.
| | 01:08 | So under Edit Textures, we click on Add Texture.
| | 01:14 | The first thing we need to
do is select the texture.
| | 01:19 | The Asset Browser opens up and
we see a bunch of textures here.
| | 01:23 | In the Asset Browser you can choose
how much detail you want to see on your
| | 01:29 | assets, whether they're textures or whatever.
| | 01:32 | And you can do this by
moving the slider over here.
| | 01:35 | I'll put it back to about this one.
| | 01:38 | Let's start with the cliff layer.
| | 01:39 | Now remember, this is the first
texture we are adding so it's going to cover
| | 01:44 | the entire terrain.
| | 01:45 | I can double-click it in and now I have to
click Add and now our entire terrain is
| | 01:53 | covered with that particular texture.
| | 01:56 | Let's load a few more textures to paint with.
| | 01:58 | Once again, Edit Texture > Add Texture,
browse for a new texture--this time I'm
| | 02:08 | going to choose Grass--double-
click it in, and click on Add.
| | 02:13 | Now we've got two textures in here, and
the one that's blue, or blue-rimmed, will
| | 02:19 | be the one that you're painting with.
| | 02:21 | So now let's paint with the grass.
| | 02:22 | And I will choose one of the other
brushes. And now might be a good time to zoom in,
| | 02:30 | so I'm going to hit my F key and it
zooms me in closer, and now I can continue
| | 02:37 | painting with this texture.
| | 02:39 | Besides all of our usual brushes,
brush size, and opacity, we also pick up a new
| | 02:47 | parameter called Target Strength.
| | 02:49 | Opacity is additive just like the
topography painting, but Target Strength gives
| | 02:54 | you a way to cap the opacity.
| | 02:57 | For places where inorganic meets
organic--say a pebbly path through a grassy
| | 03:01 | meadow--you'll probably find that full
strength and opacity plus a hard-edge
| | 03:05 | brush will give a better result
than a soft blend of textures.
| | 03:09 | Let's take a minute to look at the
mechanism that Unity uses to store
| | 03:13 | the painted textures.
| | 03:15 | To do so, first we need to save the scene.
| | 03:18 | Take a quick look in the
Project view before you do.
| | 03:21 | There's our terrain and there's
our two scenes. Terrain, two scenes.
| | 03:28 | Now save the scene: File > Save Scene.
| | 03:33 | Now you'll see an arrow next to
the new terrain in the Project view.
| | 03:37 | If we click on that, we find SplatAlpha O.
The splat map is a mask that uses RGB
| | 03:46 | values to save the textures.
| | 03:49 | By selecting it, we can see it in the Inspector.
| | 03:53 | The red is my original texture and
the green bit is where I painted the grass texture.
| | 04:00 | You may think that we are limited to
only three textures--RGB: red, green,
| | 04:05 | blue--but that's not so.
| | 04:07 | Unity will continue to create more splat
maps to handle the overflow, but at the
| | 04:13 | cost of another 1.3 MBs.
| | 04:17 | If we look down here, we can see
that's how big this particular map is.
| | 04:22 | Also be aware that splat maps are
stored in the Project view and unless you're using
| | 04:26 | versioning software, you won't be
able to revert back to an earlier version
| | 04:31 | that you remember liking better.
| | 04:33 | The terrain may be used in a particular
scene, but it is an asset that resides
| | 04:38 | in the project.
| | 04:40 | For my third texture, I'm going
to load an alpha channel map.
| | 04:43 | So I'm going to switch back to the
Terrain and I'm going to Edit Textures > Add
| | 04:49 | Texture, go to the browser again,
| | 04:52 | and this time I'm going to use one
of these alpha channel maps. Totally
| | 04:58 | inappropriate for a terrain, but we
are going to see some stuff with it.
| | 05:02 | I'm going to say Add, and go ahead
and select it. Notice it reverted back
| | 05:07 | to this guy.
| | 05:08 | So I need to highlight this one.
And now I can paint with this texture.
| | 05:18 | Notice that it ignores the alpha channel.
| | 05:21 | So what about tiling?
| | 05:23 | As long as we kept to the texture
specifically created for terrain painting, the
| | 05:27 | textures are all nicely propionate to
each other using the default tiling size.
| | 05:32 | My totally inappropriate grass
clumps will be easy to experiment with.
| | 05:37 | To edit the texture's Terrain properties,
we select the texture--mine is already
| | 05:42 | selected--we go to Edit
Textures, and click on Edit Texture.
| | 05:48 | The Tile Size X and the Tile
Size Y are a bit misleading.
| | 05:52 | Where normally we may be used to
adjusting the number of tilings, in this case we
| | 05:57 | are adjusting the size relative to the world,
| | 06:00 | so the results will be consistent no
matter how big or small the terrain is.
| | 06:05 | Bottom line is, the smaller the tiling
number, the more tiles, or smaller the
| | 06:10 | images on the terrain.
| | 06:12 | We can see that if I change these to 5.
| | 06:17 | Now you can see my totally
inappropriate grass structure is tiling higher.
| | 06:21 | Then we'll go ahead and click Apply.
| | 06:27 | Now if we decide we no longer want
a texture, which I'm pretty sure we
| | 06:30 | don't want this one, we can select it
and in Edit Textures, we can click on
| | 06:37 | Remove Texture.
| | 06:38 | And when we remove it, it reverts
back to the original base texture.
| | 06:43 | There's one last thing to be aware of.
| | 06:47 | Any edits we make on the terrain--
topography, textures, et cetera--in Play mode
| | 06:52 | will not be lost when we go back to Edit mode.
| | 06:56 | So that's something to be aware of
when you add anything, whether it's trees,
| | 07:01 | textures, or topography in your terrain.
| | 07:04 | In the next video, we'll start
painting some trees on our terrain.
| | Collapse this transcript |
| Painting trees and forests| 00:00 | Let's continue with our test terrain.
| | 00:02 | Select the Terrain and click on the
Place Trees tool in the Inspector.
| | 00:07 | Let's start by taking a peek into
the Terrain Assets folder to see what
| | 00:10 | trees are available.
| | 00:12 | We'll open up Standard Assets > Terrain
Assets > Trees Ambient-Occlusion. Here we go.
| | 00:21 | It looks like we've just got one choice, a
palm tree, so let's go ahead and load it.
| | 00:25 | Just like textures, we need to load the
trees we plan to use in the Terrain Editor.
| | 00:30 | This time the button is named Edit
Trees, as you would expect, but the drill is
| | 00:33 | the same: Edit Trees > Add Tree, click
the target to find the available assets,
| | 00:40 | and click the tree in.
| | 00:43 | Before we click Add,
let's look at the tree parameters.
| | 00:46 | There's only one associated
with individual trees: Bend.
| | 00:49 | The rest are applied to trees in general.
| | 00:51 | We won't see the Bend in action for a
while yet, but you can go ahead and give
| | 00:55 | it something like 0.2.
A little goes a long way with Bend.
| | 00:59 | Then click Add to finish the loading process.
| | 01:05 | Our new tree is loaded and ready to paint.
| | 01:08 | We no longer have lots of brushes to
choose from, so Brush Size and Density
| | 01:11 | are the main controls.
| | 01:13 | Let's set the Brush Size and Density low
to start with and try painting some trees.
| | 01:20 | And that should be fairly
safe. Now we start painting.
| | 01:24 | Okay, so there's only a few trees painting.
| | 01:26 | I'm going to move the Density up a little
higher, and now we're starting to get some trees.
| | 01:37 | Unlike the tools we've used so
far, painting is not additive.
| | 01:40 | To get more trees, we need to
turn up the Density and paint again.
| | 01:44 | As soon as you begin to orbit the
Scene view, you will start to see something
| | 01:48 | odd happening: the trees will seem to pop
up and down further back in the Scene window.
| | 01:55 | There they go.
| | 01:58 | With trees, there are two levels of LOD.
| | 02:01 | With the terrain mesh we saw polygons
being reduced the further away we got.
| | 02:05 | With trees we get two levels of LOD.
At the first, at the closer distance, the
| | 02:11 | 3D trees are swapped out for planes
with an image of the 3D tree, the same
| | 02:15 | image that was generated as a preview as soon
as you loaded the tree in the Terrain Editor.
| | 02:20 | The plane is billboarded, that is,
it rotates to always face the camera.
| | 02:24 | The second level of detail removes
even the billboarded version once that
| | 02:29 | distance is reached.
| | 02:31 | If you zoom way out from the
terrain, you would eventually see the
| | 02:33 | billboarded trees disappear.
| | 02:36 | The culling distance is set to 2000
meters as a default, so ours will hang in
| | 02:40 | there for quite a while.
| | 02:41 | We'll take a look at the settings later on.
| | 02:44 | The tree parameters all
work pretty much the same way.
| | 02:47 | You won't see the changes
until you paint new trees.
| | 02:50 | To get additional terrain assets,
you can go to the Unity web site:
| | 02:54 | www.unity3d.com/support/
resources/assets/terrain-assets.
| | 03:07 | Put the downloaded package in a handy
folder outside of the Project folder.
| | 03:11 | Then import the new assets into your scene
through Assets > Import Assets > Custom Package.
| | 03:16 | While these maybe freely used for
commercial and non-commercial use, they may
| | 03:21 | not be redistributed,
| | 03:22 | so I'll be using a package with some
assets I made or altered so we can give
| | 03:27 | you the projects for each video.
| | 03:29 | Back in the Editor, I'm going to go
ahead and import the extra terrain assets
| | 03:33 | from the exercise folder for this
video: Assets > Import Package > Custom
| | 03:40 | Package, and for the 02-04 video,
ExtraTerrainAssets. Import. And now we have
| | 03:52 | a few more folders:
| | 03:53 | Terrain Meshes, Terrain
Textures, and Ambient Occlusion Trees.
| | 03:58 | Now we can add our extra tree--Edit
Trees > Add Tree--and we'll see our new tree,
| | 04:07 | BanyanOld, in the Asset
Browser. Click it in, Add.
| | 04:14 | Before I start painting, notice that
that the palm tree is still selected.
| | 04:17 | Let's select the new tree, BanyanOld, and
paint a few of those guys around the scene.
| | 04:26 | Okay, now we can test the Erase functionality.
| | 04:29 | As the instructions say, hold down the
Shift to erase trees, hold down the Ctrl
| | 04:35 | to erase the selected tree type.
| | 04:37 | Well, we've got the Banyan selected
now, so I'm going to hold Ctrl and if I
| | 04:42 | erase, it only erases banyans.
| | 04:46 | If I hold my Shift key, it erases everybody.
| | 04:50 | Okay, save the scene and save the project.
| | 04:53 | Next up, we'll be painting details.
| | Collapse this transcript |
| Painting grass, shrubs, and 3D geometry| 00:00 | The next tool in the Terrain
Editor is the Paint Details tool.
| | 00:03 | With it we can paint the grass, shrubs,
and other details that help flesh out our
| | 00:08 | terrain environment.
| | 00:09 | It consists of two main types of
objects or features: grass and detail meshes.
| | 00:15 | The first, grass, is created is created
solely from textures that are placed on
| | 00:20 | internally created planes,
just like the billboarded trees.
| | 00:22 | There are a couple of good grass
textures in the terrain assets package we
| | 00:26 | loaded, so we'll start there.
| | 00:29 | Let's click on Terrain, and in the
Terrain Editor we'll move over to Paint Details.
| | 00:36 | As expected, we need to click on
the Edit Details button first.
| | 00:41 | From its menu, let's choose Add Grass Texture.
| | 00:45 | A nice, somewhat familiar dialog
pops up, and we can load one of the
| | 00:48 | grass textures.
| | 00:51 | Let's go for Grass.
| | 00:55 | Remembering that it will be
generating planes for the image, most of the
| | 00:59 | parameters are pretty self-explanatory.
| | 01:01 | Noise Spread is the clumping parameter.
| | 01:03 | A large number will
result in more isolated clumps.
| | 01:07 | There are two colors that
get added into the mix as well.
| | 01:10 | The default Healthy Color is a bit too
saturated for me, so I'm going to tone
| | 01:14 | it down a little.
| | 01:21 | The Dry Color will be used around
the edges of the grass clusters.
| | 01:25 | When we bake light maps for the
terrain, the Shadow Color on the terrain
| | 01:29 | will also be added in with the other
two colors so the grass will appear to
| | 01:32 | be shadowed as well.
| | 01:34 | As a default, the planes will be
billboarded, but you also have the option
| | 01:38 | to turn that off.
| | 01:39 | Let's go ahead and click Add and
see what else we've got to work with.
| | 01:43 | Our interesting choice of brushes is
back and can be very helpful in placing the grass.
| | 01:48 | Brush Size may seem rather small,
but it's really easy to go overboard
| | 01:52 | when painting grass.
| | 01:53 | To start, I recommend setting the
Opacity to 0.1 and the Target Strength
| | 02:02 | nearly the same.
| | 02:05 | And my Brush Size down. No, I
think I'll leave my Brush Size up.
| | 02:11 | So I'm going to zoom in with my middle-
mouse roller to find a place I can paint
| | 02:14 | on, and start painting.
| | 02:20 | And this is using a single-
click method. And it's pretty dense.
| | 02:24 | Okay, now paint by holding your key
down. And I'm going to zoom out again.
| | 02:32 | And at some point, you'll be painting
and you won't see anything happening.
| | 02:37 | That's because the LOD for grass
is different than the LOD for trees.
| | 02:42 | Grass is set to a
default of about 80 meters.
| | 02:46 | So if we zoom in to the far side
where we were painting, you can see the
| | 02:50 | grass now appears.
| | 02:53 | If we zoom out, it disappears quickly.
| | 02:59 | As with the other tools, holding Shift
while painting removes the grass. And I'm
| | 03:03 | holding my Shift key and
down and removing my grass.
| | 03:09 | Unlike trees that are limited in density,
grass allows you to keep adding more.
| | 03:14 | If I load the Grass2 texture, under
Edit Details > Add Grass Texture, and I
| | 03:22 | choose Grass2 this time and Add,
| | 03:27 | I'll select my Grass2 and it will let
me paint Grass2 right in with Grass1.
| | 03:37 | If we zoom in, we'll be able to
see that better. So this one is
| | 03:45 | definitely additive.
| | 03:46 | Feel free to add more grass to your
terrain, and remember to zoom in when you
| | 03:51 | are working, just so you can tell
if you've actually painted or not.
| | 03:54 | And now we can go ahead and save
the scene and save the project.
| | Collapse this transcript |
| Painting detail meshes| 00:00 | The second type of detail we can
paint onto our terrain is a detail mesh.
| | 00:04 | We have two options here.
| | 00:06 | The Detail object can make use of
alpha channel bitmaps and relatively simple
| | 00:10 | polygons such as you might want
for shrubs or other leafy plants,
| | 00:14 | or it can be a solid mesh, such as a
rock or cactus or something that doesn't
| | 00:20 | need to use opacity.
| | 00:22 | Besides the restriction on texture
type, there are a couple other pretty big
| | 00:25 | differences that we'll be seeing.
| | 00:28 | So let's get started.
| | 00:29 | We already have a few detail meshes
from the Extra Terrain Assets package
| | 00:34 | from an earlier video.
| | 00:36 | Let's take a peek at the new
folders to see what we've got.
| | 00:40 | In the Extra Terrain Meshes folder,
we've got a rock, a banana plant, and
| | 00:45 | something called StripeyPlant.
| | 00:47 | That should be plenty for us to experiment with.
| | 00:50 | Select the terrain and the Paint Details tool.
| | 00:54 | Click Edit Details and this
time choose Add Detail Mesh.
| | 01:00 | Let's start by loading the StripeyPlant.
| | 01:05 | The Healthy Color is a little too bright for
my taste, so I'm going to tone it down a little.
| | 01:11 | In fact, this is a detail mesh,
so I'm going to make it all the way white.
| | 01:15 | And we'll keep the Render mode
to Grass, and then we'll click Add.
| | 01:20 | This is still a detail with a close LOD
so let's use F to zoom in on the terrain
| | 01:24 | before we start painting.
| | 01:25 | I'll just clear a little grass area
here by using our Shift key, and then we'll
| | 01:37 | select our new plant, StripeyPlant.
And I'm going to make sure that my Opacity and
| | 01:44 | Target Strength is pretty low.
| | 01:46 | A little goes a long way with the
detail meshes. And we'll click and there we
| | 01:54 | have detail meshes.
| | 01:56 | Let's click play and see how this thing behaves.
| | 01:59 | Since we haven't added a camera yet,
we're going to need to switch back to the
| | 02:03 | Scene view, but now you can see that
detail meshes will also react to the wind.
| | 02:13 | I'll go ahead and stop.
| | 02:15 | So everything that is a grass detail
and all the detail meshes set to Grass
| | 02:20 | Render type will sway in the breeze.
| | 02:24 | Right about now you're figuring out why
there are two options with our Detail meshes.
| | 02:28 | We obviously don't want our rocks or
solid objects swaying in the breeze.
| | 02:33 | Speaking of rocks, let's go ahead
and add one to our plant library.
| | 02:37 | So Edit Detail > Add Detail Mesh,
and this time we're going to choose the rock.
| | 02:47 | And here is where we change the Render mode.
| | 02:50 | If it's grass, it's going to sway.
| | 02:51 | We don't want it to sway, so we are going to
choose VertexLit, and then we'll click Add.
| | 02:58 | This is another one where you want to
keep your Opacity and Target Strength down.
| | 03:02 | Now if we click, we need to
remember to switch over to a rock.
| | 03:09 | And there we go, rocks.
| | 03:11 | Our rocks are kind of green, so I'm
going to go back into my Edit and I'm
| | 03:16 | going to turn the Healthy Color down to white
and the Dry Color, and then we'll click Apply.
| | 03:26 | And now my rocks are, well, they sort
of blend in, but if we zoom in using the
| | 03:31 | middle-mouse roller, you can
see that we've got lots of rocks.
| | 03:35 | You may be thinking that the Terrain
Editor would be a good way to add boulders
| | 03:39 | to your environment, but the problem
would be that just like the grass, they
| | 03:44 | would be distance called by LOD mechanism.
| | 03:47 | In case you are curious, let's try a
plant mesh using the VertexLit option.
| | 03:52 | We'll load the StripeyPlant in
again, Add Detail Mesh. We'll grab our
| | 03:58 | StripeyPlant. And this time we are
going to set it to VertexLit and Add.
| | 04:09 | This time when we put StripeyPlant--
and I'm going to remember to change my
| | 04:13 | selection this time--
| | 04:15 | I've just planted a bunch of StripeyPlants.
| | 04:17 | If we zoom in closer, we can see that
the Opacity is not respected on the
| | 04:22 | VertexLit plants. So I'm going to
undo, Ctrl+Z, and get rid of these.
| | 04:28 | And of course I'm going to go
to my Edit Details and remove my
| | 04:32 | VertexLit StripeyPlant.
| | 04:36 | So the things to remember about detail
meshes are one, in Grass Render mode
| | 04:42 | they may use alpha channel textures and
will be affected by grass type wind, and
| | 04:47 | two, in VertexLit Render mode, alpha
channels are ignored in textures and the
| | 04:53 | mesh is not affected by grass type wind.
| | 04:55 | In the next video, we'll be
looking at the Terrain Settings tool.
| | 05:00 | Save the scene and save the project.
| | Collapse this transcript |
| Adjusting terrain settings| 00:00 | The final tool for the Terrain
Editor is the Terrain Settings section.
| | 00:04 | This is where you can adjust LOD settings for
terrain features, as well as a few other things.
| | 00:10 | Let's select the terrain and
head over to the Inspector again.
| | 00:14 | Our last button is Terrain Settings.
| | 00:17 | While fine-tuning these settings is
more of an advanced task, it's good to know
| | 00:22 | they exist and where they're located.
| | 00:24 | If you're new to real-time game engines,
dispelling some of the mysteries may
| | 00:28 | make the learning process less intimidating.
| | 00:31 | By now you've heard me
mention LOD several times.
| | 00:34 | When making real-time games or
simulations, part of making them fun, challenging,
| | 00:39 | or interactive is making sure that
frame rate is fast enough to allow the play
| | 00:43 | not to be plagued by laggy
choppy graphics and game play.
| | 00:48 | LOD is all about keeping the poly count
low so that the engine doesn't have to
| | 00:52 | render unnecessary geometry.
| | 00:54 | So let's take a look and see what's in here.
| | 00:56 | Under Base Terrain, Pixel Error is the
setting that affects the terrain mesh.
| | 01:02 | To experiment with this, you would want to
use the Text Wire setting in the scene display.
| | 01:08 | It controls the overall mesh density.
| | 01:11 | Base Map Distance has to do with
mipmapping and where the original resolution
| | 01:15 | texture is swapped out for
blurrier mipmapped versions.
| | 01:20 | You may think more resolution is better,
but at some point back in the scene you
| | 01:23 | may get artifacting.
| | 01:25 | This is one of the settings I
usually leave as is, unless the problem
| | 01:29 | becomes noticeable.
| | 01:30 | If the ground texture becomes too
sparkly as you move through a scene, you may
| | 01:34 | want to use a lower setting so
the blurrier version happens closer.
| | 01:38 | The next setting, Cast Shadows, is about
whether the terrain itself should cast shadows.
| | 01:44 | When checked it doesn't mean it will;
it just means it can if shadows are
| | 01:48 | being used or calculated.
| | 01:51 | Draw turns off and on all the stuff
we've painted on our terrain with the
| | 01:55 | Terrain Editor. Pretty useful if you
need to do some remodeling on the terrain
| | 01:59 | after you've already foliated it.
| | 02:02 | Detail Distance is the distance in
which the details--that's the grass and detail
| | 02:07 | meshes--are longer drawn.
| | 02:08 | Detail Density gives you an option
to sort of thin them out at a distance
| | 02:13 | before they're fully culled.
| | 02:15 | Tree Distance is where the trees are no
longer drawn, and Billboard Start is how
| | 02:20 | far away the mesh trees are
swapped for the billboard versions.
| | 02:24 | Max Mesh Trees allows you to overwrite
the billboarding distance without having
| | 02:28 | to bother with the relevant settings.
| | 02:30 | To see what the Wind Settings do, we
can hit play and switch back to the view
| | 02:35 | settings and experiment.
| | 02:37 | So we are going to hit play and we'll
switch back over to Scene, and now let's
| | 02:44 | adjust the Wind Settings.
| | 02:48 | There is a high setting. Pretty rough.
| | 02:52 | Lower. And you can adjust a lot of this stuff.
| | 02:56 | Be warned that changing these settings
during runtime will not revert when we
| | 03:00 | switch back to Edit mode.
| | 03:02 | So if we keep an eye on our
settings and stop, they're still the same.
| | 03:10 | So there you have a brief
run-through of the Terrain Editor settings.
| | 03:14 | You may not need to tweak any of them
for a while, but hopefully you have a
| | 03:18 | better idea of when they might prove useful.
| | 03:20 | Go ahead and save the
scene and save the project.
| | Collapse this transcript |
|
|
3. Creating the EnvironmentAdding sun, sky, and fog| 00:00 | Let's add a few more
important things to our test scene.
| | 00:03 | So far, we've added lots of trees
and detail meshes to the environment.
| | 00:07 | And while that's pretty empowering,
it still doesn't look as good as it should.
| | 00:11 | The addition of a light to the
scene will make things look much better.
| | 00:14 | We'll be adding a
directional light to our scene.
| | 00:17 | Directional lights emit rays
that are parallel to each other.
| | 00:21 | They're not location-dependent so
will light the scene equally wherever they are.
| | 00:26 | From the GameObject menu, Create
Other, let's create a directional light.
| | 00:32 | To see the light's effect in the Scene
view, we need to have the Toggle Scene
| | 00:36 | Lighting button turned on.
| | 00:37 | Mine is, but yours might not be.
| | 00:40 | So let's double-check. And there we go!
| | 00:43 | Now, we can rotate the
light until we like the effect.
| | 00:47 | I'm going to zoom out a little bit first,
and then I'll switch over to Rotate.
| | 00:52 | And as I rotate the light, you can
see it has an effect on the scene.
| | 01:00 | I'm going to use that one.
| | 01:02 | If I switch over to Move and switch to
Global, you can see that we can pull the
| | 01:09 | light around wherever we'd like and
it doesn't affect the scene at all.
| | 01:13 | Remember, directional lights
are not location-dependent.
| | 01:18 | So the light makes things look
better, but now we need a sky.
| | 01:21 | The traditional way to make a sky was
to use a hemisphere and map an image to it.
| | 01:27 | A more modern way is to use a cube
map with a shader to apply the six sides'
| | 01:32 | images in the background.
| | 01:34 | First off, we need to
import the Skyboxes package.
| | 01:37 | So, from Assets > Import Package,
we are going to choose Skyboxes.
| | 01:45 | Import. And you'll find these guys in
the Standard Assets folder, and you can
| | 01:56 | find the skyboxes in the Skyboxes folder.
| | 02:01 | In the Inspector, you'll be able to
see the component parts of the cube maps
| | 02:04 | that are being used for them.
| | 02:05 | If we click on one of them over here
in the Inspector, and we can see the six
| | 02:12 | images that are being used.
| | 02:14 | To add the Skybox to the scene though,
we're going to need to Edit > Render
| | 02:19 | Settings, and load it in through there.
| | 02:23 | Skybox Material. We click on our little target.
| | 02:26 | And this is one time when if we were
looking at images, here are some of our
| | 02:34 | skyboxes, and you can see the images
really don't give as much information.
| | 02:38 | So, I'm going to switch it back
down to names and I'm going to choose Sunny1 Skybox.
| | 02:47 | To see it, we'll need to toggle on the
Game Overlays button, which is right next
| | 02:53 | to the Lights toggle.
| | 02:55 | Now, if I rotate my view and zoom
back a bit with my middle mouse, you
| | 03:01 | should eventually see, ah!
There it is, our sunny sky.
| | 03:08 | So, as long as we are in the Render
Settings, let's go ahead and try out some fog.
| | 03:11 | Up at the top, we have the Fog button.
| | 03:15 | So we want to use fog.
| | 03:17 | We can change its color. The nice
thing is we can see it happening in the
| | 03:25 | view as we are changing it.
| | 03:29 | And depending on your mode, you can add density--
oops, that's overkill--and get it just how you like it.
| | 03:39 | You can try the different types of fog
modes. With either Exponential, you can
| | 03:43 | change the density. With Linear Falloff
Type, you can adjust the start and end
| | 03:47 | parameters to get the look you want.
| | 03:49 | I'll let you try that on your own.
| | 03:52 | So, our scene is starting to shape up
nicely but is lacking one important thing: shadows.
| | 03:56 | We will cover lights and baked
lighting later, but we can have a quick
| | 04:01 | sneak peek at it now.
| | 04:03 | Shadows tend to be resource
hogs even at the best of times,
| | 04:06 | so first we'll need to tell our
directional light to cast them.
| | 04:09 | So we select this guy, and over in
Shadow Types, if you are using Pro, you can
| | 04:17 | tell it to use hard or soft shadows.
| | 04:24 | From the Window menu,
open the Lightmapping dialog.
| | 04:29 | Here it is right here, Lightmapping.
And we're going to switch over to Bake.
| | 04:36 | If you are using Pro, you can leave
Dual Lightmaps on, but if you are using the
| | 04:40 | free version, you will
want to use Single Lightmaps.
| | 04:44 | Then all we need to do is click Bake
Scene. And that's probably going to take a while.
| | 04:51 | And there we go! So, we can close the Lightmapping
dialog and now we can see shadows in our scene.
| | 04:58 | If you are using Pro, your dynamic
shadows may turn off at this point.
| | 05:02 | To fix that, you guys can go to
Edit > Project Settings > Player, and under
| | 05:14 | Other Settings, make sure you change your
Path from Forward to Deferred Lighting.
| | 05:20 | Now that we have baked shadows, we can
see how the baked shadows are added to
| | 05:25 | the grass and detail meshes,
even as they sway in the wind.
| | 05:29 | Of course we'll have to start Play
mode, and then we'll switch back to the
| | 05:34 | scene. And I suppose I should move
this over to find some of our grass.
| | 05:44 | And there we go:
dynamically swaying grass with shadows.
| | 05:49 | In the next video, we'll get a chance
to experience the environment firsthand,
| | 05:54 | so go ahead and save the
scene and save the project.
| | Collapse this transcript |
| Using the First Person Controller| 00:01 | So far, we've only looked at
our scene in the Scene view.
| | 00:04 | To see it in the game
window, we'll need a camera.
| | 00:07 | Fortunately, we have already got one,
| | 00:09 | so all we need to do is adjust that
default camera that was made when we
| | 00:12 | created the scene.
| | 00:13 | If we select the camera in the
Hierarchy view, we get a small preview of it
| | 00:19 | over in the Scene view.
| | 00:21 | We can see where it's pointed, but
better yet, now we can move it to match the view.
| | 00:26 | We do that by going to the GameObject
menu and choosing Align With view, and
| | 00:32 | the camera is positioned to see
the view we are currently enjoying.
| | 00:36 | Now when we click Play, we can stay
and watch the scene from the game window.
| | 00:42 | Pretty, but it's kind of boring.
| | 00:43 | So I think it's time to experience
our scene firsthand, or first person as
| | 00:47 | the case maybe.
Let's toggle back into Edit mode.
| | 00:50 | Unity is designed to let you script
any kind of controller you want, but does
| | 00:56 | come with both a first-person and a
third-person controller to get you up and
| | 01:00 | running around your scene.
| | 01:01 | In the Project view, Standard
Assets Folder, we see a folder called
| | 01:05 | Character Controllers.
| | 01:08 | Let's start by dragging the
first-person controller into the Scene view.
| | 01:12 | It's represented by a capsule.
| | 01:13 | So we're going to grab the first-person
controller and drag it into the scene.
| | 01:20 | Now is a good time to switch to the
2 x 3 layout so we can see both where the
| | 01:24 | controller is and what he
is seeing at the same time.
| | 01:27 | We'll switch our layouts.
| | 01:29 | Up here, we were using Wide; now we
are going to be using the 2 x 3 layout.
| | 01:35 | You might have noticed
that the Scene view changed.
| | 01:37 | That happens when you change the layout.
| | 01:39 | But it's easy to select the main
camera again and use the Align view to
| | 01:43 | select it again.
| | 01:45 | So, we'll select our main
camera, go to GameObject menu,
| | 01:49 | and this time we'll use Align view
to Selected. And we get back to our
| | 01:53 | Camera view.
| | 01:55 | Now, we can see that the Game view
is definitely different from the view
| | 01:58 | from the main camera.
| | 01:59 | Let's see what's going on.
| | 02:01 | If we click the down arrow on the
first-person controller, we can see that
| | 02:04 | it has its own camera,
| | 02:06 | and from the looks of it, it takes
priority over the original default camera.
| | 02:10 | If we click play, we can look
around the viewport by moving the mouse.
| | 02:14 | In the Scene view, if we select the
first person's main camera, we can also see
| | 02:19 | the camera's view gizmo moving.
| | 02:22 | By clicking in the Scene view,
we can move the character with the
| | 02:24 | Transform Gizmo.
| | 02:26 | To drive through the scene,
we actually need to click back in the Game view.
| | 02:30 | Then we can use our mouse to look the
direction we want to move and use our W,
| | 02:35 | A, S, D keys to move through our scene.
| | 02:43 | Let's stop Play mode for a
minute and look at the status line.
| | 02:46 | So we'll click up here and stop.
And in the status line we see there are two
| | 02:51 | audio listeners in the scene.
| | 02:53 | Please ensure that there's always
exactly one audio listener in the scene.
| | 02:57 | To use any audio in your scene,
you must have an audio listener.
| | 03:01 | To see anything in your
scene, you must have a camera.
| | 03:04 | So, Unity automatically adds the
listener to cameras whenever they're created.
| | 03:08 | Since we may or may not keep the
original main camera, let's remove the
| | 03:12 | audio listener from it.
| | 03:13 | So we'll select our original main camera,
and over in the Inspector, here is our
| | 03:19 | Audio Listener, and we can right-
click and say Remove Component.
| | 03:25 | At some point, the message will go away now.
| | 03:28 | Before clicking play again, let's try
Maximize on Play from the Game window.
| | 03:34 | Now click play and enjoy
the scene all on its own.
| | 03:41 | We can drive around just like we did
before, W, A, S, D, using the mouse to look
| | 03:49 | up and down and around.
| | 03:52 | Let's toggle back to Edit mode.
| | 03:53 | With something of interest in the
Game window, we can look at a couple of
| | 04:00 | more of its tools.
| | 04:01 | From the first dropdown, we can
change from Free Aspect to various other aspect ratios.
| | 04:07 | Stats, over here, lets us see where
the game's resources are being used,
| | 04:12 | including the frame rate.
| | 04:14 | If we turn off Stats and look at Gizmos,
we can see things that are usually not
| | 04:19 | rendered in the game window.
| | 04:20 | Here, we can just barely
see the camera's view range.
| | 04:24 | So now that we are finally mobile in the
scene, we are going to take a look at a
| | 04:27 | few more options for
creating terrain in the next video.
| | Collapse this transcript |
| Publishing project settings| 00:00 | Now that we've got the bare essentials
under control, let's see how easy it is
| | 00:04 | to build and publish a Unity scene.
| | 00:06 | To start, always make sure
you've saved your current scene.
| | 00:10 | Now, we can go to the File menu,
select Build Settings, and add our
| | 00:17 | current scene to the build.
| | 00:19 | We do that by clicking on Add Current.
| | 00:23 | Now, here it is, our TerrainTest scene.
| | 00:26 | Next, we are going to
choose our target platform.
| | 00:29 | I'm using Windows, and I want to
make sure I'm on PC and Mac Standalone.
| | 00:35 | I've selected PC and Mac Standalone,
but you can see there are several
| | 00:38 | other options as well.
| | 00:40 | Next, we want to make sure our target
platform matches, and this is Windows so
| | 00:44 | we are good, and I'm
going to click Build And Run.
| | 00:48 | First thing we need to do is to
decide where we are saving it.
| | 00:51 | We probably don't want to save it in
with the first project, so I'm going to go
| | 00:55 | up a folder, and give it a
name, and let's call it testRun.
| | 01:03 | I'm saving it here in my exercise
files; you can obviously save it
| | 01:06 | wherever you'd like. And here we go!
| | 01:11 | This is our startup screen.
| | 01:13 | You notice that we can change the
aspect ratio or the graphics quality, and we
| | 01:20 | can even remap the keys for input.
| | 01:23 | Let's go ahead and click
play just to see if it worked.
| | 01:28 | There's the splash screen, and here we are!
| | 01:30 | And now can drive around using our W, A, S,
D keys just like we could in the Game view.
| | 01:37 | Let's go ahead and close this.
| | 01:38 | We'll close the Build Settings.
| | 01:44 | Now that we've seen how easy it is to
publish, let's see what else we could
| | 01:48 | do with the project.
| | 01:50 | From the Edit menu, select
Project Settings > Player.
| | 01:57 | In the Inspector, we now get a bunch of choices.
| | 02:01 | Under Icon, either here or here, we
can add an image, and I'm going to choose
| | 02:07 | one for my Extra Terrain Textures,
something like my colocaleaf, and now
| | 02:16 | we've got our icon.
| | 02:18 | And then remember the splash screen
that came up? We could select the splash
| | 02:22 | image for it, and under Other Settings,
we can change things like the Rendering
| | 02:28 | Path from Deferred Lights to Forward Rendering.
| | 02:32 | And in Resolution and Presentation,
we can disable Display Resolution dialog;
| | 02:38 | that prevents the player from being
able to change many of the game settings.
| | 02:43 | If we now go back over to File > Build
Settings, and Build And Run, we'll save
| | 02:52 | it in the same place,
and yes, we want to replace it,
| | 02:59 | now, when the game runs, we no
longer get the Settings dialog;
| | 03:02 | we go directly into the game itself.
| | 03:05 | Let's go ahead and close the
game. Close the Build dialog.
| | 03:10 | We'll make it enabled again.
| | 03:17 | We'll go back to the Build Settings, and
Build And Run again, and you'll see it come back.
| | 03:24 | Save. Yes, we want to overwrite,
and there it is! All right!
| | 03:30 | So we are just going to quit at this point.
| | 03:33 | So now you've seen how to go
ahead and build a game in Unity.
| | Collapse this transcript |
| Introducing the game environment| 00:00 | Up until now, we've covered the
basics of creating an environment.
| | 00:04 | Next, we are going to create a new
project that, with the help of a few
| | 00:08 | extra assets, will become the
framework for a game that we'll be creating in this course.
| | 00:13 | So let's start by creating a new project.
| | 00:16 | As we saw earlier, its name will appear
in the Configuration dialog and on the
| | 00:20 | title bar of the stand-alone.
| | 00:22 | So let's name it something clever
like UnitySampler. File > New Project >
| | 00:29 | Create New Project. And I'm going to
browse to the Desktop where I've got my
| | 00:37 | folders. 03-04. And remember in Unity,
the folder is the project, so I'm going
| | 00:48 | to right-click and say new folder, and
I'm going to name this UnitySampler, and
| | 01:01 | select the folder.
| | 01:04 | Now for this game, for this project,
we are going to need the Character
| | 01:09 | Controller, the Scripts, Skyboxes, and
the Tree Creator, and so we we'll create.
| | 01:24 | Creating a nice terrain can take a
while, even at the best of times, so I've
| | 01:28 | saved out a Unity package with
the terrain already created for you.
| | 01:33 | Let's right-click. Import Package >
Custom Package. And in the exercise files
| | 01:42 | folder for this video/Assets,
we're going to bring in MainLevel.
| | 01:52 | I'll click Open and then Import.
| | 01:54 | And when we look in our Project view,
we can see that it even has a scene for us.
| | 02:01 | So let's double-click the MainLevel scene.
| | 02:05 | We don't need to save the default.
| | 02:09 | And here is our new scene.
It comes with a terrain.
| | 02:19 | And then the next asset we're
going to need is some structures.
| | 02:22 | So right-click again, Import Package >
Custom Package, and from the Assets
| | 02:32 | folder again, bring in structures.
And click Import again and here it goes.
| | 02:43 | This time we have an imported Assets
folder and we are going to bring Structures
| | 02:49 | for Scene into our Hierarchy view.
| | 02:53 | This adds them to our scene and if we
zoom up close, we can see that we've added
| | 03:00 | a building and a few barricades.
| | 03:06 | Our game, because it's really more of a
game sampler, may be a bit silly, but it
| | 03:10 | will be more fun than a
disjointed set of technique videos.
| | 03:13 | So here is a quick rundown of the project.
| | 03:16 | It starts with three
areas in a canyon-like space,
| | 03:23 | a staging area--you can just
see it here--a nature area.
| | 03:31 | The next one will be a dry rocky blasted-
looking area with the dog leg so we can
| | 03:36 | eventually hide a sentry system behind it.
| | 03:39 | The next feature will be a stone-face
building or compound, which we can see
| | 03:44 | here. And then we've got a deep chasm
and finally, a tall peak with a little
| | 03:52 | ledge at the very top.
| | 03:54 | So let's look and see a couple
of things that are added to this.
| | 03:58 | I've added a directional light
so we can see the shadows.
| | 04:04 | If you're using Pro and you zoom in,
you'll be able to see the dynamic shadows.
| | 04:09 | If you zoom out, you can see they fade out.
| | 04:13 | Besides the trees you've already
worked with, we have a new addition in
| | 04:16 | the nature area.
| | 04:17 | It's a tree created with the Tree Creator.
| | 04:20 | We'll cover the Tree Creator later in
the series, but we'll make good use of the
| | 04:23 | sample tree that came in with it.
| | 04:25 | In the next video, we'll revisit the
first-person controller to make sure that he
| | 04:30 | can get around in our new scene.
| | Collapse this transcript |
| Fine-tuning the First Person Controller| 00:00 | Now that we've got our fancy new terrain,
we'll need a first-person controller.
| | 00:05 | Let's go ahead and add a first-person
controller from the Standard Assets folder.
| | 00:08 | Here is our Standard Assets, Character
Controllers, and our First Person Controller.
| | 00:14 | If we are careful, we can drag him
straight into the compound area and then we
| | 00:19 | can rotate him, if we zoom in a
little bit here, to face the compound.
| | 00:34 | And if you want to move him a little more
to get him kind of in front of the steps,
| | 00:39 | that will be even better.
| | 00:41 | So first off, we need to focus in on him,
| | 00:44 | and we can double-click him. And we want
to make sure that I am using my Alt key
| | 00:49 | to rotate the view, make sure that he
is not struck in the ground, because we
| | 00:53 | want to prevent a free-fall accident.
| | 00:56 | And now we can go ahead and click
play and drive up the front steps.
| | 01:05 | So I've just used my mouse to get
oriented in here, and I am going to go ahead
| | 01:10 | and move him by pressing my W key.
| | 01:13 | We try to go in here and we get blocked.
| | 01:17 | So the first-person controller goes
smoothly up the steps, but when we get to
| | 01:21 | the doorway, the ledge seems to block us.
| | 01:24 | You can jump over it using a spacebar,
but we'll have the same problem with the
| | 01:28 | rest of the stairways inside the building.
| | 01:31 | So there are two things at work here.
| | 01:33 | Let's go ahead and exit play mode, and
if you open the Structure's folder in the
| | 01:39 | Buildings group and find something
called Stair ramp, we can see that it has its
| | 01:47 | Mesh Renderer turned off.
| | 01:49 | Let's click that on for a minute, and now we
can see, especially in the Game view here,
| | 01:54 | that there is actually a plane
there that covers the steps and makes
| | 01:58 | navigation smoother.
| | 01:59 | This is a fairly common trick,
especially in real-time applications such as
| | 02:03 | architectural walkthroughs.
| | 02:05 | Let's go ahead and turn the Mesh Renderer off.
| | 02:08 | The rest of the stairways don't have
ramps, so we are going to need to make some
| | 02:12 | adjustments to the First
Person Controller's parameters.
| | 02:16 | Select him in the Hierarchy view and
over in the Inspector, we are going to look
| | 02:22 | at the Character Controller section.
| | 02:25 | And we want to change the
Slope Limit to 90 degrees.
| | 02:31 | If we click play and try it now,
it move easily into the area and navigates
| | 02:36 | the stairs with ease.
| | 02:37 | And we go up here, and it goes right on in.
| | 02:46 | I have also left gizmos on, so I need to turn
that off as soon as we get out of Play mode.
| | 02:54 | So I'll exit Play mode. The first thing
I'll do is turn off gizmos, and I am going
| | 03:00 | to turn off Maximize on Play,
and let's try one more thing.
| | 03:04 | Now I'll click play again,
and this time we've got a problem.
| | 03:11 | Not only can he get up the steps,
but if we click the spacebar to make him
| | 03:17 | jump, he can also climb straight up
the sides of the cliffs, and that's
| | 03:22 | probably not a good thing.
| | 03:24 | So let's exit Play mode, and we
need to change our Slope Limit again.
| | 03:29 | If we set the Slope Limit back to 45
and set the Step Offset to say 1, he will
| | 03:35 | be able to go over steps shorter than
one meter high, but he still won't be able
| | 03:39 | to go up small inclines.
| | 03:41 | So the best solution for easy navigation
without full access in this environment
| | 03:46 | is probably going to be a
compromise between the two.
| | 03:49 | Let's go ahead and set the Slope
Limit to 60 and then Step Limit to 0.5.
| | 03:57 | Now we would be able to click Play and
explore the inside of the compound but
| | 04:02 | not be able to climb the Canyon walls.
| | 04:05 | Let's click Play and
explore the rest of the terrain.
| | 04:09 | If we head out from the compound,
you'll soon hit a little crevice that we can
| | 04:13 | jump by hitting the spacebar.
| | 04:16 | If you are not a very good navigator like me
though, you might want to put a plank there.
| | 04:20 | Let's exit Play mode and in the
Structures for Scenes, you'll find something
| | 04:26 | called Bridge Plank.
| | 04:28 | If we double-click on it and use
Alt to orbit our view a little bit, we
| | 04:36 | should be able to drag him right
into place so that we no longer have to
| | 04:40 | force our player to jump.
| | 04:41 | Feel free to move it
wherever it works best for you.
| | 04:44 | Now the problem is those
pesky doors and the barriers.
| | 04:48 | We haven't seen them yet, but before we
even get there, we may as well turn them off.
| | 04:53 | Open barrier 1, select sliding door
left, and uncheck it in the Inspector.
| | 05:00 | This deactivates the door. And the same
with door right, we'll deactivate it.
| | 05:07 | And in Barrier 2, we'll do the same with solid door.
| | 05:13 | So now if we click play and head out,
hitting my W key here, this time I
| | 05:20 | don't have to jump.
| | 05:21 | I can drive over my plank, and the
doors are open, and I can go ahead and drive
| | 05:28 | into my little nature area.
| | 05:30 | Okay, now we're all set to go.
| | 05:32 | So those were some of the
obstacles you might face when setting up a
| | 05:36 | first-person controller.
| | Collapse this transcript |
|
|
4. Introducing Unity ScriptingExploring Unity scripting| 00:00 | Now that we've got a nice little
environment to run around in, it's time to
| | 00:04 | start making it interactive.
| | 00:05 | Interactivity is, after all, what sets
our games or real-time simulations apart
| | 00:10 | from passive media such as movies.
| | 00:12 | If we had to break them down, we could
say there are two types of interactivity:
| | 00:17 | physical, where an object might move or
fall over when hit by a projectile; and
| | 00:23 | logical, where we wouldn't be able
to open a door if it was "locked."
| | 00:28 | In the latter, there's no physical
locking mechanism so we would need to keep
| | 00:32 | track of its state, a sort of virtual
lock, and then trigger the appropriate
| | 00:36 | response when the player interacts with it.
| | 00:39 | You might think that the former
example, the projectile, would seem easier.
| | 00:43 | But even there we're going to have to
make decisions about what happens to both
| | 00:47 | the projectile and its target on impact.
| | 00:50 | To do this, we will need to write
scripts to tell the Unity engine how to behave
| | 00:55 | in any given situation throughout the game.
| | 00:57 | Let's take a projectile, for example.
| | 00:59 | The projectile would have a script
that would tell it how to behave when it
| | 01:03 | hit another object,
| | 01:04 | while the locked door would have a
script that kept track of its state so it
| | 01:08 | would know what to do when
the player interacted with it.
| | 01:11 | In case you are feeling a bit
spooked at this point, don't panic.
| | 01:15 | Unlike traditional programming, which
might have thousands of lines of code
| | 01:18 | in one spot, in Unity you'll have
separate scripts that are put on objects
| | 01:23 | to do specific things.
| | 01:25 | Some may only be a few lines long.
| | 01:27 | So, what's involved with scripting?
| | 01:29 | Well, to start, a language.
| | 01:32 | Unity supports several languages:
| | 01:34 | Python, Boo, C# and JavaScript.
| | 01:39 | But we will only be using JavaScript
since most of the examples in the Unity
| | 01:42 | Help files and most of the
tutorials are written using it.
| | 01:46 | It's also a lot more forgiving.
| | 01:48 | If you're already familiar with
JavaScript from web programming, you're off to
| | 01:52 | a good start.
| | 01:53 | But be warned, Unity's version of
JavaScript is slightly different than the
| | 01:57 | JavaScript you may be used to.
| | 02:00 | If you've never done any
kind of scripting, don't worry.
| | 02:03 | There are some syntax rules to follow,
but unless we're using some obscure
| | 02:06 | functions, it's usually pretty readable.
| | 02:09 | Best of all, there are lots and lots
of examples and sample code in both the
| | 02:13 | Unity docs and from the Unity community.
| | 02:16 | A large portion of the scripting
concerns specific Unity game functionality and
| | 02:20 | can be accessed from the
Help menu > Scripting Reference.
| | 02:25 | The Unity docs are also available
online, which is usually a lot quicker way to
| | 02:29 | find what you're looking for.
| | 02:31 | For the basics of JavaScript in general,
you will need to do a search on the
| | 02:34 | web to find out about particular topics,
get yourself a good reference book to
| | 02:38 | keep handy, or both.
| | 02:41 | Another worry you may have
is about your math skills.
| | 02:44 | Most of the scripting we will be
doing will not go beyond high school math.
| | 02:48 | We will be using code from other
sources occasionally that gets in to the scary
| | 02:52 | math category, but just like driving a
car, you don't need to know how it works
| | 02:57 | to make good use of it.
| | 02:58 | The last thing we'll need is a script editor.
| | 03:01 | Theoretically we could write all our
script in a simple text application like
| | 03:04 | Notepad and save the files
with a JavaScript extension,
| | 03:08 | but script editors have a lot of
features that will make scripting much easier.
| | 03:12 | Unity ships with a few different
editors, but now the default is the Mono
| | 03:16 | Develop, so that's what I'll be using.
| | 03:19 | If you prefer something different,
you can set it up as the default editor
| | 03:23 | through Edit > Preferences > External tools.
| | 03:28 | So let's go ahead now and jump right in.
| | Collapse this transcript |
| Using variables| 00:00 | Since a good part of scripting is
about keeping track of our logic, we will
| | 00:04 | need a way to manage or store all
those pesky bits of information. Enter the variable.
| | 00:10 | Variables hold values--usually just
one: the state of a door, the current
| | 00:15 | color of your shirt, the number of
rounds of ammunition you have left, just
| | 00:18 | about anything.
| | 00:20 | It might be a value that will change
regularly or it maybe something that
| | 00:24 | doesn't change but that
different scripts will need access to.
| | 00:27 | Let's try making a few just for practice.
| | 00:31 | First though, let's create a new
scene in our Unity Sampler Project. File >
| | 00:36 | New Scene, and then we'll save the scene
as, and we'll do it just in the default
| | 00:41 | area right now.
| | 00:42 | We'll save it as Scripting Tests.
| | 00:46 | In the interest of trying to keep
organized, let's also make a folder to hold
| | 00:50 | our practice scripts.
| | 00:52 | Right-click in the
Project view, Create > Folder.
| | 00:57 | And we'll name this folder Practice Scripts.
| | 01:01 | And then we can go ahead
and create our first script.
| | 01:05 | With the new folder selected,
right-click again, but this time
| | 01:09 | select Javascript.
| | 01:12 | That creates a new
JavaScript named NewBehaviorScript.
| | 01:16 | And it's immediately put into
rename mode, so we are going to name
| | 01:20 | ours VariablesTest.
| | 01:22 | Notice there is no spaces in the name.
| | 01:25 | When naming scripts, we need to avoid spaces.
| | 01:28 | So you can separate your words with
underscores or as you'll see most often in
| | 01:32 | Unity, no space, but capitalize
the first letter of each word.
| | 01:38 | If you look in the Standard Assets
folder and find a folder named Scripts,
| | 01:42 | you'll see that this is
the convention most used.
| | 01:46 | You can still be descriptive with
meaning and it's still easy to read.
| | 01:49 | Back to our first script. Now that
it's properly named, we can go ahead and open it.
| | 01:55 | When it's selected, we can see its
contents in the Inspector and we can open it
| | 02:01 | from there by clicking the Open button.
| | 02:04 | We can also open it just by
double-clicking it in the Project view.
| | 02:08 | Either way, it opens up on the
Script Editor, in this case MonoDevelop.
| | 02:13 | In it, we see something cryptic at
the top, #pragma strict. We'll come back
| | 02:19 | to him later.
| | 02:20 | We see two empty functions.
| | 02:23 | We'll delve into functions in the next video.
| | 02:25 | Variables are usually declared at
the top of the script, just beneath the
| | 02:30 | pragma strict declaration.
| | 02:32 | I am going to give myself a little bit
room here by clicking Return a couple of times.
| | 02:38 | We have to start by telling Unity it's
a variable, and that is var, and we give a space.
| | 02:48 | Then we add the name of our
variable. We'll call this one health.
| | 02:52 | And let's pause a second and talk about
naming variables, because there is lots
| | 02:57 | of rules and conventions to follow.
| | 03:00 | Number one: variable names can't
start with numbers or several specialty
| | 03:05 | characters like exclamation
points, backslashes, et cetera.
| | 03:08 | There are a few exceptions,
but better to keep to letters.
| | 03:12 | Two: do not capitalize the first
letter; we save that convention for
| | 03:17 | naming functions.
| | 03:19 | And three: no spaces are allowed in
the variable name, so use underscores or
| | 03:25 | better yet, capitalize the first
letter of the rest of the words.
| | 03:28 | You'll see why we want to use
that method in just a few minutes.
| | 03:32 | Then we need to tell it what
type of variable it will be storing.
| | 03:36 | So we'll add a colon.
| | 03:38 | I am going to click space
first and then add my colon.
| | 03:42 | Then the type. In this case it's going
to be an int, so I type in I-N-T. Then
| | 03:49 | I'll finish my line with a semicolon.
| | 03:52 | Before we go any further,
let's talk about types.
| | 03:55 | Typically, these are things like
integers, and that's shorten to int as we
| | 04:00 | just saw. Integers are whole numbers
like 1, 50, 0, -25, and then we have
| | 04:07 | floating-point numbers.
| | 04:09 | Those are numbers with decimal
points like 3.745, -0.62, things like that.
| | 04:17 | And then strings of characters,
these are always put between quotation marks.
| | 04:23 | In case you like to cut and paste from
your favorite text editor, they need to
| | 04:26 | be the plain vanilla upright quotation
marks, not the fancy slanted characters.
| | 04:31 | So let's get back to types.
| | 04:34 | Boolean is a two-state variable type.
| | 04:36 | It either uses true or false, both
lowercase. Checkboxes always use Booleans.
| | 04:42 | And then Unity also has several
types that are unique to it. They are
| | 04:46 | always capitalized.
| | 04:48 | You'll rarely ever see them
initialized in the declaration.
| | 04:51 | We'll hold off on those for a while.
| | 04:54 | So what's initialized? We go ahead and
assign a value to the variable at the
| | 04:59 | same time we declare it.
| | 05:01 | I have made code snippets available,
so we can just copy and paste our code
| | 05:05 | into the editor.
| | 05:06 | I am going to go out to the desktop now
and grab my first one, from my exercise
| | 05:11 | files folder, Ch04/04-02,
and there is my Code_Snippets.
| | 05:18 | I have also made them available for
everybody in the free exercise file.
| | 05:23 | Let's go ahead and open this one now.
| | 05:24 | So I have given us a whole bunch of
examples of variables with different types.
| | 05:30 | Let's go ahead and copy them and
then we'll open up Unity again and the Script Editor.
| | 05:37 | In the Script Editor, we are at the end
of the health of type int line. Let's go
| | 05:42 | ahead and hit Enter and then I am going
to Ctrl+V to paste in all my new ones.
| | 05:48 | Some of them already have values
assigned to them and some of them don't. Most
| | 05:54 | importantly, you can see each
declaration has the semicolon at the end.
| | 05:58 | This is really important.
| | 05:59 | It tells us when the end of the declaration is.
| | 06:02 | If you forget the semicolon,
Unity will throw an error.
| | 06:05 | So now that you've seen how to
declare a variable, let's solve the pragma strict mystery.
| | 06:11 | Remember I said that
JavaScript is pretty forgiving?
| | 06:15 | It turns out it's pretty good at
figuring out what type your variable is, as
| | 06:19 | long as you initialize it.
| | 06:21 | If you are developing for mobile,
you must declare your variable types. pragma
| | 06:27 | strict forces a check to make sure
that all variables are typed when the code is compiled.
| | 06:32 | In Unity's JavaScript it won't
necessarily throw an error, but it does force
| | 06:37 | the type to be found.
| | 06:39 | Let's save our little
script and test it in our scene.
| | 06:43 | To save it, I am going to go up to
the icon on the toolbar and click Save.
| | 06:48 | Now we can minimize the Script
Editor and go back into Unity.
| | 06:52 | We can see that the script
is updated in the Inspector.
| | 06:56 | Here comes the fun part.
| | 06:58 | Let's add a cube to the scene.
| | 07:00 | So GameObject > Create Other > Cube,
and now we are going to drop our little
| | 07:06 | script onto it and see what happens.
| | 07:09 | Here is our script, VariablesTest,
and we are going to click and drag and
| | 07:14 | drop it on the Cube.
| | 07:16 | Now when we select the Cube over
in the Inspector, we can see our new
| | 07:21 | script, VariablesTest.
| | 07:24 | Our variables all show up in the Inspector.
| | 07:26 | They look a little different though.
| | 07:28 | The words are all capitalized and
separated, except for the one with
| | 07:32 | the underscore.
| | 07:33 | Let's do a little test.
| | 07:35 | Let's change the My Speed parameter to 25.5.
| | 07:40 | So My Speed is 10, and we are going to
change it to 25.5. Then we are going to
| | 07:48 | open the script again by double-
clicking on the script in the Project view and
| | 07:53 | when we look at it, we see that the
value for My Speed hasn't changed.
| | 07:58 | It's still 10.
We'll minimize this again.
| | 08:02 | Let's go ahead and make a sphere
and drop our same little script on it.
| | 08:06 | So GameObject > Create Other > Sphere,
and we can move it aside if we want.
| | 08:13 | And we'll drop our same little
VariablesTest script onto it by clicking and
| | 08:18 | dragging. And this time on this one,
we'll change its My Speed parameter to 15.
| | 08:26 | If we go back and look at
our Cube, it's still 25.5.
| | 08:31 | This means we can reuse the script
on any object we want, customizing
| | 08:36 | the variables for each.
| | 08:38 | If we click play and change the
values during runtime--so I've got my Cube
| | 08:44 | selected and I am going to change My
Speed to 1 and click Enter--and then we
| | 08:49 | stop, so we exit Play mode,
note that the value reverts back.
| | 08:56 | So changes made during runtime are
not permanent; they always revert back to
| | 09:01 | whatever we have them set to in Edit mode.
| | 09:04 | So now there is just one other thing we
ought to cover while we are talking about
| | 09:08 | variables and that's how to keep
them from showing up in the Inspector.
| | 09:12 | Let's open our script again and once
again I am going to double-click on it
| | 09:16 | in the Project view.
| | 09:18 | If we put "private" in front of the
var, and save, we'll no longer see the
| | 09:23 | someObject parameter.
| | 09:25 | So in front of someObject,
let's insert and say private, all lowercase, and
| | 09:32 | save. Remember the icon in the upper-
left here, Save the active document, or you
| | 09:38 | can also use Ctrl+S. Then I'll minimize
and get back into Unity. And now as soon
| | 09:45 | as I come back, if I click on an object
to bring the focus back to the editor,
| | 09:50 | now we look over here and we have
Some Setting and Some_Name, Some String, but
| | 09:55 | we no longer have someObject.
| | 09:57 | A few point releases ago, Unity changed
the functionality so that not even other
| | 10:03 | scripts could see private variables.
| | 10:05 | This can cause problems in
older scripts and tutorials.
| | 10:08 | A better solution is to use internal.
| | 10:12 | This way the parameter is only
hidden from the Inspector, but still
| | 10:15 | accessible from other scripts.
| | 10:17 | So let's go back and change that.
| | 10:19 | Once again, double-click on the
VariablesTest script, and this time we are going
| | 10:25 | to change private to internal.
| | 10:29 | Save the script. We'll minimize again,
activate the Cube, and once again there
| | 10:36 | is no Some Other.
| | 10:37 | So that works just as well.
| | 10:40 | So let's do a quick recap
on scripts and variables.
| | 10:43 | When naming scripts, do not use any spaces;
| | 10:46 | use underscore or caps.
| | 10:47 | Let's open up the Script Editor again.
And for variables, no spaces either, plus
| | 10:55 | you must start the variable
name with a lowercase letter.
| | 10:58 | You may not start with numbers or
several of the specialty characters.
| | 11:02 | The syntax for declaring a variable is
var some_Name : type and then semicolon.
| | 11:11 | To declare and initialize, we add
equals and the value and then the semicolon.
| | 11:18 | Commonly used types are int,
float, string, and boolean.
| | 11:23 | Back in the Inspector, variable names
are separated by spaces at each uppercase
| | 11:30 | letter, values typed into the inspector
overwrite values assigned in the script,
| | 11:36 | values changed at runtime are not
permanent, and finally, internal or private
| | 11:42 | keeps the variable from
showing up in the Inspector.
| | Collapse this transcript |
| Discovering functions| 00:00 | Now that we have a way to keep track
of our stuff, we need a way to make
| | 00:04 | things happen.
| | 00:05 | This is where functions come in.
| | 00:07 | There's a few different types of
functions. Some take care of user input and
| | 00:11 | other events, and some, like the two
empty functions we've seen preloaded in the
| | 00:16 | script, take care of system stuff.
| | 00:19 | And then there is the user-defined
functions where we can design whatever we need.
| | 00:23 | If you're new to scripting, let alone
game engines, it can be pretty challenging
| | 00:28 | to find what you're looking for.
| | 00:29 | So this is a good time to
visit the Scripting Reference for a
| | 00:33 | little enlightenment.
| | 00:34 | From the Help menu, we're going to
select Scripting Reference, and we're going to
| | 00:40 | search for "monobehavior" in the upper-
left and click Enter. And it tells us it
| | 00:47 | found one match, so we'll
go ahead and click on it.
| | 00:51 | Remember the default name
assigned to the new script?
| | 00:54 | It was New Behavior Script.
| | 00:56 | That's because all JavaScripts
derived from the MonoBehavior class.
| | 01:01 | We don't really need to worry about
classes, but an example of a class could
| | 01:05 | be a bicycle class.
| | 01:07 | Inside the class we'd have variables
or parameters that help describe the
| | 01:10 | bicycle: type of handle bars, number
of wheels, color, and maybe functions,
| | 01:17 | functions such as go forward,
on crash, cause flat tire.
| | 01:23 | If we had a class called vehicles,
our bicycle class would inherit more generic
| | 01:27 | properties and functions from it.
| | 01:29 | That's sort of what the MonoBehavior class is.
| | 01:32 | And if you've noticed up at the top,
it inherits from another class as well.
| | 01:37 | In the Overridable Functions section--
and we'll just scroll down here a little
| | 01:41 | ways--you will find a lot
of really useful functions.
| | 01:46 | With their handy short descriptions,
it's a good place to start looking for the
| | 01:50 | basics, especially for interaction-type stuff.
| | 01:54 | Let's look at the first two
functions preloaded in the new script.
| | 01:58 | The Update function is called every frame.
| | 02:02 | This is where we put things that need
to happen or be monitored every frame.
| | 02:06 | It's one of the most commonly used functions.
| | 02:09 | But since it's called every frame,
it could cause things to happen at different
| | 02:12 | rates depending on the speed of the
machine the game is running on, or even at
| | 02:16 | different times during the
games since frame rates vary.
| | 02:20 | Things that involve physics are
usually called from FixedUpdate, so the
| | 02:25 | resulting action will be
about the same across platforms.
| | 02:28 | While the Update functions are called
throughout the game, the Start function
| | 02:34 | is called only once: at the start of
the game and before any of the Update functions.
| | 02:39 | This is where we often initialize
variables such as start times that need to be
| | 02:43 | dynamically assigned.
| | 02:44 | Remember that variable of type game object?
| | 02:48 | We can't just type in the object's name
to assign it to a value because its name
| | 02:53 | is just one of its properties.
| | 02:54 | But we can let the engine search for a
game object with the name or some other
| | 02:59 | property and assign the one
it finds to that variable.
| | 03:03 | That's another task we might
think to put in the start function.
| | 03:07 | Here's the catch though:
| | 03:08 | the start function is only
called when the object is activated.
| | 03:12 | So the start functions in the scripts
on things like projectiles aren't even
| | 03:16 | called when the game starts up,
but when the objects are instantiated or
| | 03:21 | created during the game.
| | 03:23 | To make sure objects can be found
whether they are activated or not, we use
| | 03:27 | the Awake function.
| | 03:29 | It's always called before the Start
function but after all of the objects
| | 03:33 | have been initialized.
| | 03:34 | Getting back to the docs, we can see
that most of the event-triggered functions
| | 03:39 | start with On. We'll be revisiting
several of these throughout the course.
| | 03:43 | We'll take a look at syntax in the next
video, then start making things happen.
| | 03:48 | But first, let's do a quick review.
| | 03:51 | Functions are where we make things happen.
| | 03:53 | They can be system type called on
startup, like the Start function, or
| | 03:58 | every frame, like Update.
| | 04:00 | A list of functions, including the
event-driven function like OnCollisionEnter,
| | 04:06 | can be found in the Scripting
Reference by searching MonoBehavior.
| | Collapse this transcript |
| Using syntax, punctuation, and the console| 00:00 | So we have had a general look at
some of the overall characteristics of a
| | 00:03 | few useful functions,
| | 00:05 | and we know how to declare and
assign values to standard variables.
| | 00:09 | Now that you've been introduced to
the concepts, it's time to learn about
| | 00:13 | syntax, punctuation, and tracking down
errors, because computers are funny about
| | 00:18 | wanting things exactly correct.
| | 00:20 | In the last video, I mentioned
something about Unity throwing an error if you
| | 00:25 | forgot to add the semicolon to the
end of the variable declaration lines.
| | 00:29 | Tracking down mysterious errors is
a large part of scripting, especially
| | 00:34 | if you're new to it,
| | 00:35 | but Unity's compiler is pretty good about
reporting many different mistakes. Let's try a few.
| | 00:42 | As you can see, we're in
the Scripting Tests scene.
| | 00:45 | Let's go ahead and double-click the
VariablesTest script to open it in the Script Editor.
| | 00:49 | So let's delete a semicolon to start.
| | 00:52 | This is an easy thing to forget to
add if you're cutting and pasting code.
| | 00:56 | I'll try this one right here. And delete.
And whenever you make changes in your
| | 01:01 | script, you need to
remember to click over and save.
| | 01:06 | Now if we minimize the Script Editor,
an error appears in the Status line at the bottom.
| | 01:14 | Let's click on that, and that opens
up the Console. The Console is where we
| | 01:19 | will be seeing errors reported, but we can
also send messages out to be printed there.
| | 01:25 | The error message tells us which script
has the error--VariablesTest.js--what row
| | 01:31 | and what column it's at, and if we're
lucky like this time a message that's
| | 01:37 | useful in telling us what the problem is.
| | 01:39 | Here's the nice bit.
| | 01:41 | If we double-click the error message in
the Console, the Script Editor opens up
| | 01:47 | to the exact line, and now we can fix it.
| | 01:50 | We'll add our semicolon back in and save.
| | 01:57 | Let's see what else can go wrong.
| | 01:59 | Let's try a capital T for true.
| | 02:01 | So I'm going to click, turn that into a
capital T. Notice the color changed.
| | 02:08 | And let's not forget to save, minimize the
Script Editor, and now our error message
| | 02:16 | tells us that there is an
unknown identifier called True.
| | 02:21 | Once again, it tells us where
it is, so we can double-click.
| | 02:24 | It opens up the Script Editor, and we can
just set that back to a lowercase t, and save.
| | 02:33 | Well, what happens if string is not capitalized?
| | 02:38 | Let's go to this variable right here,
| | 02:40 | this type, and we'll make this guy a
lowercase s, save the script, and let's minimize.
| | 02:49 | This time the name string
does not denote a valid type.
| | 02:54 | So this time it doesn't even have a clue.
| | 02:56 | So we are not always going to get Unity
telling us what was wrong, but at least
| | 03:01 | it will take us to where the problem is.
| | 03:03 | So we'll double-click on it, and this
time it's up to us to figure out what it
| | 03:07 | is, but fortunately, in this one we know.
| | 03:12 | You may have picked up something else here.
| | 03:14 | Let me move my cursor
away to close the tooltips.
| | 03:17 | So you may have picked
up on something else here.
| | 03:20 | The words are color coded.
| | 03:23 | When we change the S to a lowercase s,
the word String went from blue to black.
| | 03:29 | And all of our variable names that we
made up are black. It turns out reserved
| | 03:35 | words are shown in blue.
| | 03:38 | This is great for people
like me who can't type or spell.
| | 03:41 | If the color is wrong,
double-check the spelling.
| | 03:44 | Okay, let's see what happens if we
forgot to close the string with the second
| | 03:49 | set of quotation marks.
| | 03:50 | And we can go up to either of our String
examples to do that. Highlight, delete. Once
| | 03:57 | again we save and minimize.
| | 04:02 | This time the error is different.
| | 04:04 | It was expecting quotation marks,
but it found a carriage return instead.
| | 04:08 | Let's double-click to open our Script
Editor again, and we'll go ahead and fix
| | 04:13 | this guy, by putting our quotation mark
back. And never forget, you need to save.
| | 04:23 | So, what about spaces?
| | 04:25 | Let's put a few extra ones
in and then maybe delete one.
| | 04:29 | So I'm going to go over here and maybe
I'll delete this space right here and
| | 04:34 | maybe an extra one here, and let's
save and see if we get any errors.
| | 04:38 | Save, minimize, and no,
no errors. So guess what?
| | 04:46 | Spaces aren't crucial.
| | 04:49 | Let's open the VariablesTest again or
bring up the editor. And I do want to
| | 04:56 | show you one thing here.
| | 04:57 | If we had two spaces in this string that
wouldn't be the same as the string with one space.
| | 05:06 | The reason you will see script editors
using that ugly sort of Courier font is
| | 05:10 | so that you can clearly see
if there was a space or not.
| | 05:14 | This is really important.
| | 05:16 | Spaces and punctuation do
count in strings. Okay.
| | 05:20 | To recap, the Console will report errors,
identify their location in the script,
| | 05:26 | and occasionally make
suggestions about correcting them.
| | 05:29 | In the Script Editor, reserved words
are shown in blue and finally, spaces are
| | 05:35 | not crucial unless they're part of the string.
| | Collapse this transcript |
| Looking at function syntax| 00:01 | Let's go ahead and look at function syntax next.
| | 00:04 | Opening our VariablesTest script by
double-clicking on it, we can check out the
| | 00:10 | two functions that are already there.
| | 00:12 | The word "function" tells us what's coming
up, and then we have the name, and opened
| | 00:17 | and closed parentheses.
| | 00:18 | Occasionally, you will want to
pass an argument into a function.
| | 00:23 | In the case of an object that just got
hit by a projectile, we might need to
| | 00:27 | know if it was a bullet from a machine
gun or a rocket from a rocket launcher.
| | 00:32 | So, a function that calculates
damage knows how much to add.
| | 00:35 | Inside the parentheses is where
we pass that kind of a variable.
| | 00:39 | After the parentheses, we see an open
curly bracket and then further down, a
| | 00:45 | closed curly bracket.
| | 00:47 | Everything inside them belongs to that function.
| | 00:50 | If you click right behind the opening
one, you can see that the closing one
| | 00:56 | will be highlighted.
| | 00:57 | Deleting one of those
generates a bunch of errors.
| | 01:00 | Let's try it and see.
| | 01:01 | I am going to highlight and delete this
one. And of course I will save, and then we
| | 01:08 | will minimize and see what the Console tells us.
| | 01:12 | I'll click it to open, and now it's
giving us an Unexpected token message.
| | 01:17 | So, double-click on it to bring our
script back up, and we can put it right
| | 01:22 | back. Open curly bracket.
| | 01:25 | Because of the errors that can cause,
when we start writing new functions, we
| | 01:30 | usually create it empty, but fully
correct to start with, just like the Start
| | 01:35 | and Update functions.
| | 01:36 | Let's go ahead and try one of our own.
| | 01:39 | Down below the function Update,
I am going to click and do a couple of line
| | 01:44 | feeds with enter, and then I will type
"function." And notice that in a Document
| | 01:52 | Outline, as soon as we start typing, it
goes blank; as soon as it's correct again,
| | 01:58 | that's going to come back.
| | 01:59 | So a function--and I am going to name
this function JustATest. And remember, the
| | 02:05 | first letter of your function
name needs to be capitalized.
| | 02:09 | After the name of the function, I am
going to give myself a space, although
| | 02:14 | that's not totally necessary, and I
am going to make my opened and closed
| | 02:18 | parentheses, my open curly bracket,
couple of enters for line feeds, and I will
| | 02:27 | go ahead and put closed curly bracket.
| | 02:29 | So, let's go ahead and click Save and
minimize and make sure that the Console
| | 02:34 | is happy. It is; there's no errors reported.
| | 02:38 | So we'll go back into that, and now we
are going to try something different.
| | 02:42 | So far, we have seen a starting
curly bracket up on the same top line.
| | 02:47 | This time I am going to
click Enter and drop it down.
| | 02:51 | Now let's save and see if that's still okay.
| | 02:55 | Click Save, minimize, check out our
Console, give it a second to refresh if it
| | 03:00 | needs to, and guess what? That still good.
| | 03:03 | We'll open this again.
| | 03:04 | So believe it or not, this is a serious issue.
| | 03:08 | It's correct either way, but many
companies will have strict conventions for
| | 03:13 | using one way or the other,
| | 03:14 | even to the point of fines. The issue
is readability and continuity of style,
| | 03:19 | so don't even try to win an
argument about why your way is better.
| | 03:22 | But you'll see it both ways.
| | 03:25 | To recap, the syntax for functions is,
function, the function name, open
| | 03:31 | and closed parentheses, where the argument is
optional, and open and closing curly brackets.
| | 03:38 | And finally, remember the
position of the curly brackets can vary.
| | Collapse this transcript |
| Printing to the console| 00:00 | Okay, I think it's time
to make something happen.
| | 00:03 | We are going to add a command to
print something out to the Console.
| | 00:07 | So let's open our VariablesTest script
again, and we can double-click it from the
| | 00:12 | Project view or we could
open it from the Inspector.
| | 00:17 | In the Start function between the curly
brackets, give yourself a couple of line
| | 00:21 | feeds, and this is just for cosmetic purposes.
| | 00:24 | And now I am going to go out to my
Snippets file and copy the first line
| | 00:30 | Exercise Files/Ch04/04-06, and I
am going to open the Code_Snippets.
| | 00:39 | And here is my first line, so I'll
copy it, and we'll pop back into the Script Editor.
| | 00:49 | Now I can paste it inside my Start function.
| | 00:52 | This line prints a message to the
Unity Console. Let's go ahead and try it.
| | 00:57 | Save the script and we'll minimize.
And we've already got our script on two
| | 01:05 | objects, so I am going to click
play and watch down at the bottom.
| | 01:12 | On our Status line, we can see the message.
| | 01:15 | If we click it, we can open
the Console, and we see it twice.
| | 01:20 | That's because we have the same
script on both the Cube and the Sphere.
| | 01:26 | Let's close this for a minute, get back
to our Script Editor, and we are going to
| | 01:32 | look at another way to do this.
That's the proper way to print to the Console.
| | 01:36 | But you'll also see people using this method.
| | 01:39 | Print, parentheses, and I am going to
write "ditto" in here, close my quotation
| | 01:50 | mark, close the parenthesis, end the line.
| | 01:55 | So you'll also see this used.
| | 01:57 | It doesn't follow the usual rules of
function names being capitalized, and it
| | 02:02 | doesn't turn blue like a reserved word should.
| | 02:05 | But remember our friend Mono?
| | 02:07 | Well, that's the framework Unity is built
on, and that's where this guy comes from.
| | 02:12 | Let's try it and see if it works.
| | 02:14 | Save, minimize, and let's get out of play
mode and start again, and there we can see ditto.
| | 02:28 | If we open the Console, we can
see that it worked for both objects.
| | 02:33 | Here is our Debug Log and here is our print.
| | 02:37 | Here is the other Debut Log
and here is the other print.
| | 02:40 | Now let's go ahead and put a
message in the Update function.
| | 02:43 | So let's close this. We can turn this off
for now, bring up our Script Editor again.
| | 02:50 | Now let's put a message in the Update function.
| | 02:53 | We can just copy this guy, paste him
in the Update function and instead of
| | 03:01 | Start, we'll go ahead and tell
ourselves that it's Update. But we need to
| | 03:07 | remember that Update is called every frame.
| | 03:10 | So it won't be surprising that after we
save and click Play, then open the Console,
| | 03:22 | that that message is repeated over and over.
| | 03:25 | Okay, that's probably enough of that.
| | 03:27 | But rather than delete it,
let's try something new.
| | 03:30 | Let's comment it out.
| | 03:33 | So we'll turn off Play mode.
We'll go back to our VariablesTest.
| | 03:39 | The two forward slashes tell the engine
to ignore everything after them on that
| | 03:43 | line--in other words, all the green stuff.
| | 03:47 | If you save and run, you can see that
the message from the Update function will
| | 03:51 | no longer be printed, so let's try that.
| | 03:53 | Save, minimize, and we'll leave the
Console open this time, and we'll click Run.
| | 04:02 | And there we go. We still have our two
print message from the Start function,
| | 04:07 | but nothing from Update.
| | 04:08 | While this works great for temporarily
hiding code, its main use is to enable
| | 04:14 | you to make comments to your code to
remind you, or anyone else who might see
| | 04:18 | your code, what it does.
| | 04:20 | So let's add a real comment after
one of those variable declarations.
| | 04:23 | I am going to go out to my
Code_Snippets and find a nice handy one. //test
| | 04:30 | string to see how they work,
| | 04:32 | that's a good one. So copy it, get
back to our Script Editor, and after one of
| | 04:41 | our strings, I am going to paste it in.
| | 04:44 | I won't be adding comments onscreen
to the code very often because of the
| | 04:49 | limited resolution, but the scripts that
are included in the exercise files will
| | 04:54 | have plenty for you.
| | 04:55 | The next thing to try is a
message in the JustATest function.
| | 05:00 | So let's go out and cut
one of those and paste it in.
| | 05:04 | This is a good one, print
message from the JustATest function.
| | 05:09 | So I'll copy and I am
going to paste it into here.
| | 05:16 | When we save, minimize, stop, and then
click Play again--by the way notice we
| | 05:25 | have Clear on play here.
We could also clear it before we start.
| | 05:29 | We'll click Play. The Start message has
printed again, but not the JustATest message.
| | 05:37 | It turns out we need to call
the function for it to be run.
| | 05:43 | Let's call it from the Start function.
| | 05:45 | So we'll exit, get back to our Script
Editor, and here is how you call a function.
| | 05:51 | This is the one we want to call,
so we can just copy its name. And we need
| | 05:57 | the two parentheses.
| | 06:00 | So we'll copy and in the Start function,
I am going to make myself a little bit
| | 06:05 | more space and paste.
| | 06:08 | We are missing one thing, the semicolon.
| | 06:13 | Now we can save, minimize, Clear, and click play.
| | 06:24 | And now there it is,
Message from the JustATest function.
| | 06:28 | And finally, as a little review of
variables and bit more fun, let's use the
| | 06:34 | variable called some_Name.
| | 06:37 | So we'll go back into our Script Editor,
and we'll change our message from JustATest.
| | 06:43 | I am going to pick up my last bit of
code here, copy it, and let's just exchange
| | 06:53 | the original message in
JustATest for the new one.
| | 06:57 | Strings can be added or
concatenated together with a plus sign.
| | 07:03 | Let's go ahead and save our
script and see what happens.
| | 07:09 | Minimize. We'll start over again. And now
we see our new message: Hi, Fred, glad
| | 07:18 | to have you aboard.
| | 07:19 | Fred, if you'll remember,
was the value for our some_Name string.
| | 07:26 | Back in the Inspector,
we can go one step further.
| | 07:30 | Let's turn off play mode and on the Cube,
let's name this guy to somebody else.
| | 07:40 | We'll call this one Alice.
| | 07:45 | And over on the Sphere,
let's change it to, how about Floyd?
| | 07:54 | Now when we click Play, if we open the Console,
you'll see that we don't have Fred anymore.
| | 08:04 | One of the scripts is saying hi to Alice
and the other one is saying hi to Floyd.
| | 08:09 | So the same script is used on both
objects, but the variable, some_Name, loaded
| | 08:15 | in the Inspector is unique to each and
overwrites the name we initialize the variable with.
| | 08:21 | Test messages are useful for tracking
what our program does, especially when it
| | 08:26 | isn't doing what we expect.
| | Collapse this transcript |
| Exploring rotation and time functions| 00:00 | You are probably ready to
see a bit more action by now.
| | 00:04 | Transforms, move, rotate and scale
are the basis of a lot of game action,
| | 00:09 | so we'll start there.
| | 00:11 | Since we'll finally be interacting
with the Game window, make sure you're
| | 00:14 | already in the 2 x 3 layout.
| | 00:16 | Now we'll go ahead and set the Cube at 0, 0, 0.
| | 00:22 | So we'll select the Cube and in the Inspector,
click, type 0, click, type 0, and one more 0.
| | 00:34 | Now let's focus in on the Cube, and we
can double-click it to bring it into the
| | 00:38 | view. And then we need to get the Main
Camera looking at it by selecting the
| | 00:43 | Camera and from the GameObject
view clicking Align With View.
| | 00:49 | With only ambient lighting,
it's pretty hard to see our cube,
| | 00:53 | so let's go ahead and add a
directional light while we're at it: GameObject >
| | 00:58 | Create Other > Directional Light.
| | 01:03 | We can rotate the light until our
cube shows up nicely in the Game view.
| | 01:12 | Now let's make a new JavaScript.
| | 01:14 | Remember to select the Practice Scripts
folder first, then right-click, Create > Javascript.
| | 01:24 | And we'll name it TransformTest and click Enter.
| | 01:35 | Open it by double-clicking. And in the
Update function, we are going to cut and
| | 01:41 | paste a little bit more code.
| | 01:43 | So I am going to go out to find
my Code_Snippets, Ch04/04-07/ 04-07Code_Snippets.
| | 01:54 | I am going to copy and paste my first
line and then go back to my Script Editor,
| | 02:03 | and I am going to paste
it into my Update function.
| | 02:07 | If you want, you can give it a little
more space. And usually we end up indenting
| | 02:15 | everything inside a function,
| | 02:17 | so I have just tapped that over one.
| | 02:20 | Let's go ahead and hit Save and back
in the Unity Editor, we'll go ahead and
| | 02:27 | drag our TransformTest script onto the Cube.
| | 02:31 | When we click play, the cube rotates.
| | 02:37 | So we might want to change the speed.
| | 02:40 | If we hard code it in the script,
we'll see the change after we save the script
| | 02:45 | and return focus to the editor. Let's try that.
| | 02:48 | I am going to stop, and this time
let's set it to, let's try 0.6.
| | 02:56 | Save the script, minimize, click play
again, and this time the cube is rotating, well,
| | 03:05 | about twice as fast.
| | 03:06 | Usually though, we are going to use
variables that can be changed in the
| | 03:12 | Inspector when we want to be changing values.
| | 03:15 | So let's do that this time.
| | 03:17 | Stop. We'll get back into the editor.
And now I am going to go over and pick up
| | 03:25 | my next bit of code.
| | 03:27 | I want this one. Copy, and I am
going to right-click and copy.
| | 03:33 | Then we'll go back to the Script Editor.
And let's give ourselves a little bit of
| | 03:38 | space here using Enter, and we'll paste
our new variable here. var rotationSpeed
| | 03:46 | of type float, and we are initializing it to 20.
| | 03:50 | Now because we have a variable,
we are going to copy that variable name,
| | 03:55 | copy--that's a right-click--and we
are going to paste it in the Y position
| | 04:03 | where the 0.6 used to be.
| | 04:07 | Let's save our script, minimize, and click Play.
| | 04:12 | The cube is spinning pretty fast.
| | 04:16 | If we click on it in the Hierarchy view,
we can see the value we first gave it: 20.
| | 04:22 | Let's go ahead and exit Play mode.
| | 04:25 | So this works fine except for one thing.
| | 04:28 | The Update function is called every
frame. That means if your machine is faster
| | 04:33 | than mine, your cube will be spinning faster.
| | 04:37 | Now, it might seem logical to move the
code into the fixed update, but Unity
| | 04:41 | has a better solution.
| | 04:43 | Let's get back into the
Script Editor and have a look.
| | 04:48 | Let's go get our next bit of code,
and we want this one right here.
| | 04:54 | And we'll right-click, copy, and we are
going to replace the original transform
| | 05:01 | line with a new one, using Ctrl+V.
Notice we are now multiplying our
| | 05:08 | rotationSpeed by Time.deltaTime.
| | 05:13 | By multiplying by Time.deltaTime,
Unity ensures that now the objects with this
| | 05:18 | script will be rotating the
specified amount per second.
| | 05:24 | Let's make the change, save,
minimize, and we'll click Play.
| | 05:30 | Now with the same
rotationSpeed it's rotating much slower.
| | 05:35 | In case you are wondering what's
happening, remember, before we were rotating
| | 05:40 | every frame, and if we look at the Stats in the
Game window, it's about 70 frames per second.
| | 05:48 | So before, our rotationSpeed
of 20 was happening every frame;
| | 05:54 | now it's happening every second.
| | 05:57 | Let's go ahead and exit Play mode.
| | 06:00 | So why use Time.deltaTime
instead of fixed update?
| | 06:04 | Chances are the frame rate will be
better than the fixed update, which must be
| | 06:09 | less than the fastest rate,
| | 06:11 | so the action will be smoother.
| | 06:13 | If you happen to have changed your
speed during runtime, as soon as you stop,
| | 06:18 | it will revert back.
| | 06:20 | That's kind of a double-edged sword.
| | 06:22 | You have to remember the settings you
want to keep, but at least you won't mess
| | 06:26 | up something and not remember
what it was before you tweaked it.
| | 06:29 | Let's try one more test while we're here.
| | 06:32 | So far, we've been able to change the
value of our variable during runtime
| | 06:36 | through the Inspector and see the changes.
| | 06:39 | That's because the rotation
code is in the Update function.
| | 06:43 | It gets read every frame.
| | 06:45 | Let's see what happens if we make the
variable internal and change the value
| | 06:50 | of script at runtime.
| | 06:52 | So we'll go back to our script and
we'll make our rotationSpeed an internal
| | 06:59 | variable. Let's go ahead and hit Save
and click play. The speed is reverted to
| | 07:12 | the value we originally assigned in the script.
| | 07:15 | If we go back to the Script Editor and
change the speed here, save, and go back
| | 07:25 | to the editor again, there is no
change in the speed in the viewport.
| | 07:31 | That makes perfect sense because the
variables are declared and initialized when
| | 07:35 | the game is started.
| | 07:37 | Any changes made to them in the
Start function are added afterwards.
| | 07:41 | Those two procedures
happen only once, on startup.
| | 07:44 | So any time we change values assigned
to variables or assigned in the Start
| | 07:49 | function and not exposed in the
Inspector, we will need to restart Play mode
| | 07:55 | to see the changes.
| | 07:57 | Okay that's a lot of things
to remember, so let's review.
| | 08:02 | Transform.rotate rotates an object;
Time.deltaTime converts the code to per
| | 08:09 | second instead of per frame; and
changing values in the Start function during
| | 08:16 | runtime will only show the change
when the scene has been restarted.
| | Collapse this transcript |
| Scripting basic functions| 00:00 | Let's see if we can get the cube
moving the same way we got it rotating.
| | 00:05 | First though let's deactivate
the Sphere over in the Inspector.
| | 00:09 | So we're going to select this Sphere.
We can't see him in the viewport, but he
| | 00:13 | is still there, and in the Inspector
we're going to uncheck the Activate button.
| | 00:20 | Now let's go ahead and open the
TransformTest script again. And we're
| | 00:25 | double-clicking on it as usual.
| | 00:28 | To start, we're going to comment out the
rotation line with our forward slashes,
| | 00:36 | and then I'm going to go out and grab a
new bit of code from the exercise files:
| | 00:40 | Ch04/04-08/Code_Snippets.
| | 00:48 | And we're going to start with this one.
Right-click, Copy, and then I'm going
| | 00:58 | to tab back to the Scripting Editor.
And I want to add this line of code just
| | 01:03 | below the first one.
| | 01:04 | I'll go ahead and Tab over
first, paste, Ctrl+V. And we've got
| | 01:10 | transform.Translate(speed * Time.
deltaTime, and then the usual zeros.
| | 01:18 | So it's pretty much like our first line.
| | 01:21 | We've got Translate instead of Rotate,
and we've also got a different variable.
| | 01:26 | So let's pop over and get that one as well.
| | 01:28 | Here is our speed variable, right-click,
Copy, and we'll tab back over to the
| | 01:38 | Script Editor, and we'll add this guy
up at the top, or near the top, and paste.
| | 01:45 | We can go ahead and click Save now,
minimize, and when we click Play, the cube
| | 01:53 | will probably scoot out of the view pretty
quickly. And we'll try that. And there it goes.
| | 01:59 | So we'll exit Play mode and in the
Inspector we'll reduce the speed, and we have
| | 02:06 | to select the cube to see the
TransformTest script in here, in the Inspector.
| | 02:12 | And so we are going to reduce the speed.
| | 02:14 | I'm going to reduce it to about 5.
| | 02:17 | And then we also should use the middle-
mouse roller to zoom back in the viewport
| | 02:24 | so we'll have a better chance of
seeing it when it starts moving.
| | 02:28 | Now we can click Play
again and it moves slowly off.
| | 02:35 | Now in case you are wondering what
would happen with both lines of code active,
| | 02:41 | we better check that out.
| | 02:43 | So let's back into the Script Editor and
uncomment or remove our forward slashes.
| | 02:51 | We can save again. Back in the
Unity editor if you click on the cube,
| | 02:57 | over in the Inspector we
don't see the Rotation Speed.
| | 03:01 | If you remember, we left it as an
internal variable. It looks like we'll have to go
| | 03:06 | back out and fix that.
| | 03:08 | I'm going to tab over to the Script
Editor and remove internal. Delete
| | 03:17 | and remember to save.
| | 03:19 | Now we can go back to the Unity Editor
and as soon as the focus is changed, our
| | 03:24 | Rotation Speed variable turns up again.
| | 03:28 | And I want to set that to about 50.
| | 03:32 | Now let's click play and see what
happens. We should have both the rotation and
| | 03:37 | the transform happening.
| | 03:38 | And sure enough, our cube is
rotating and moving at the same time.
| | 03:46 | Now if you're a little bit unsure
of what's happening here, there's two
| | 03:51 | things you need to do.
| | 03:52 | First make sure the cube is selected,
which it is. We can see our Transform
| | 03:57 | gizmo, but here is the trick.
Instead of Global we want to see Local.
| | 04:06 | With Local turned on, now you can
see wherever the X axis is pointed,
| | 04:12 | that's where our cube is moving.
| | 04:15 | Now we can see that the Translate
function moves an object along the
| | 04:21 | object's local axis.
| | 04:24 | Wherever the cube is rotated to face,
the cube moves forward in that direction.
| | 04:30 | Let's go ahead and exit
Play mode. So far so good.
| | 04:37 | We can animate an object to move
or rotate using transform.Rotate and
| | 04:42 | transform.Translate.
| | 04:45 | And in case something about those looks
familiar, yes, they are functions and they
| | 04:50 | belong to transform.
| | 04:52 | But what if we just wanted to put an
object in a different location, not animate it?
| | 04:57 | For that we will need to change
the object's transform parameters.
| | 05:04 | Take a look at the cube's Transform
values in the Inspector as it animates.
| | 05:08 | So we'll turn it on for a second again.
We can see the object's Transform is
| | 05:13 | moving in the Inspector.
| | 05:16 | Let's exit Play mode again.
| | 05:17 | All the Transform values are
variables: Position, Rotation, and Scale.
| | 05:24 | The parameter names are capitalized in
the Inspector, just like our own variable
| | 05:28 | names were, but since they're really
just variables, they won't be capitalized
| | 05:33 | when we assign our own values to them.
| | 05:36 | Let's have our own script give us
the position of the cube this time.
| | 05:41 | So let's open up the Script Editor again.
| | 05:44 | This time we'll comment out both of the
transform lines. And here is something
| | 05:50 | that's a little new:
| | 05:52 | if we right-click, in the right-
click menu we can Toggle Line Comments.
| | 05:57 | That way we get them both at once.
| | 06:01 | Now in the Update function, let's add
another bit of code that we'll go out and grab.
| | 06:08 | This time I'm going to copy, tab back
into my Script Editor, and paste, and this
| | 06:18 | time we're going to have it
print (transform.Position).
| | 06:24 | So now we can go ahead and
save, get back into the Editor,
| | 06:29 | and now when we click play, if we move
the cube around, we should be able to see
| | 06:37 | its position being reported in the
status line. And sure enough, there it is.
| | 06:46 | The position is reported as a
three-part variable, a Vector3 type.
| | 06:52 | We'll go about setting
position in the next video.
| | 06:55 | So to recap, transform.Translate moves an
object using its local coordinate system.
| | 07:02 | Vector3 type contains three values--
x, y,z--and transform.Position will report
| | 07:09 | the location of an object.
| | Collapse this transcript |
| Combining transforms| 00:00 | In the last video we found that
translate.position was a three-part variable, a vector3 type.
| | 00:08 | So how do we assign a value
to a particular transform?
| | 00:11 | Easy, transform.position.x.
This is called dot notation.
| | 00:18 | It's a way of referencing where
functions and variable definitions come from.
| | 00:22 | So transform has a variable called
position and position in turn has a
| | 00:28 | variable called x. If we look up
transform in the scripting reference--Help >
| | 00:35 | Scripting Reference--and we choose
Transform, we can see both the functions
| | 00:45 | and variables we've been
using. Here is position.
| | 00:51 | Under Functions we can
find Translate and Rotate.
| | 00:56 | Also note the first line: "Every
object in a scene has a Transform."
| | 01:02 | This means we can put our script on any
object and get or set its transforms, or
| | 01:09 | if we wanted, use the Rotate
or Translate functions on it.
| | 01:14 | Let's test the position.
| | 01:16 | Let's get back into Unity, open our
TransformTest script, and I'm going to go out
| | 01:24 | to the exercise files again
to copy our next bit of code.
| | 01:27 | In exercise files, Ch04/04-09/Code
_Snippets, and let's go ahead and take
| | 01:38 | the first two lines.
| | 01:41 | Right-click and copy and tab back to
our Script Editor, and we want to add these
| | 01:48 | guys in the start function.
| | 01:50 | I'm going to press Enter a couple of
times to give myself more space and then
| | 01:55 | Ctrl+V to paste them in.
| | 01:57 | Since they are already defined by Unity,
we don't need to tell Unity that
| | 02:01 | they are variables or even what type they are.
| | 02:04 | So now if we save the script and head
back to the editor and then hit play, we
| | 02:11 | will eventually be able to find
the cube off of its new location.
| | 02:16 | And there it goes. We might have to
look for it, but it's definitely moved.
| | 02:24 | If we double-click, we can find it.
| | 02:28 | As soon as we exit Play mode, it's
going to return to where it originally was.
| | 02:33 | I'll double-click again to
locate it in the Scene view.
| | 02:37 | So this is worth noting.
| | 02:38 | As soon as we exit Play mode,
it reverts back to the original location.
| | 02:44 | So just like translating, transforming an
object with position during runtime is not permanent.
| | 02:52 | Let's try one more experiment while we're here.
| | 02:55 | We still haven't actually
interacted with the cube in the Game view.
| | 02:58 | Traditionally, we have interacted with
objects in our games using the mouse for
| | 03:03 | part of the navigation, and for firing weapons--
| | 03:06 | well, along with the keyboard.
| | 03:08 | With today's move towards mobile where
there is no mouse or keyboard, it's more
| | 03:13 | likely we will be using touch to
trigger events for interaction.
| | 03:16 | Since you may not have a touch-enabled
monitor, we'll do a simple test using the
| | 03:21 | mouse button and the OnMouseDown function.
| | 03:25 | So back in the Script Editor, let's go
ahead and comment out all of the code in
| | 03:31 | our Start and Update functions, and
then we'll head over to the snippets and
| | 03:40 | grab the entire function here.
| | 03:44 | Highlight, right-click to Copy, and then
we'll tab back to our Script Editor.
| | 03:53 | And this one we're going to add
underneath the Update function.
| | 03:57 | So Ctrl+Paste, and we have our new function.
| | 04:01 | This one, OnMouseDown, we saw
briefly when we were looking at the
| | 04:05 | original MonoBehaviour.
| | 04:07 | We've put in it transform.position.z = 1;
| | 04:11 | and transfor.position.x = 5, so when we
click on our mouse button, that's where
| | 04:19 | the cube will be moved.
| | 04:21 | Let's go ahead and save our script,
tab back to the Unity Editor, and give it a try.
| | 04:29 | I'm going to go ahead and zoom back
first though, on the off chance that I might
| | 04:34 | find it after it's moved.
| | 04:36 | Now we can go ahead and click Play.
| | 04:39 | This won't move until we actually
click on the cube in the Game window and as
| | 04:44 | soon as I click,
it's transformed off to its new location.
| | 04:49 | Let's go ahead and exit Play mode.
| | 04:52 | In Unity, MouseDown is set to
work off of a left-mouse click.
| | 04:56 | If we created variables for x and z,
then you could change their values in the
| | 05:02 | inspector, and each time you click the
cube, it would move to the new location.
| | 05:08 | So to recap, dot notation allows us to
access functions and parameters; we can
| | 05:14 | set location by assigning a value to
an object's position parameter; and we
| | 05:19 | were introduced to the OnMouseDown
function as a means to interact with an
| | 05:24 | object in runtime.
| | Collapse this transcript |
| Setting transforms| 00:00 | So we've seen a little about how to
transform objects, both by setting their
| | 00:04 | transforms and animating them.
| | 00:07 | But even using the OnMouseDown function, we
aren't really doing anything game-ish yet.
| | 00:12 | So what's missing?
| | 00:14 | What makes a game different than,
say, an architectural walkthrough?
| | 00:18 | The answer is conditionals.
| | 00:20 | If the door is locked, rattle it;
else it is unlocked, so open it.
| | 00:26 | If the monster's health
is less than 25, kill it;
| | 00:30 | else reduce its health by 30.
| | 00:33 | The if statement is the most
important of the conditionals.
| | 00:37 | We might be evaluating an amount
like health or strength, or we might be
| | 00:41 | evaluating a state like locked or unlocked.
| | 00:45 | Let's try controlling the
rotation of our cube with a MouseDown.
| | 00:49 | So let's create a new JavaScript and
then we'll name it RotationController.
| | 00:54 | Remember to highlight your Practice
Scripts folder first, right-click, Create >
| | 01:01 | JavaScript. And we're going to
name this guy RotationController.
| | 01:14 | We'll go ahead and open it in the
Script Editor, and then we're going to need to
| | 01:20 | create a variable to keep track
of its state, its rotation state.
| | 01:26 | I'm going to head out to the snippets
folder and pick up the new bit of code.
| | 01:29 | Ch04/04-10, and here is our Code_Snippet.
| | 01:41 | So this is the one we're
going to want right here.
| | 01:44 | Highlight, right-click, Copy, and then
we'll tab back over to the Script Editor.
| | 01:54 | And this is a var, a variable, so I'm
going to give it a little more room up
| | 01:59 | here by clicking Enter. And I'll paste it
into that area using Ctrl+V. Since it'll
| | 02:05 | either be rotating or not, we're going
to use a Boolean type for the variable.
| | 02:11 | It only takes a byte's worth of memory
for storage, as opposed to an integer
| | 02:15 | that takes a lot more.
| | 02:16 | And then we're going to need a variable
for speed, so I'm going to tab out and
| | 02:23 | collect that one as well.
| | 02:26 | Highlight, right-click, Copy, and then
we'll tab back to our Script Editor, and
| | 02:34 | we'll add it just
underneath the first one. Paste.
| | 02:38 | We already have one named rotationSpeed,
but since it's on a different script, we can reuse it.
| | 02:45 | It's sort of like two guys named Bob
Smith: same name but different people.
| | 02:50 | If we do ever need to refer to them in
the same script, we just specify where
| | 02:54 | they came from: Maple Street.Bob
Smith and Shady Lane.Bob Smith, where the
| | 03:01 | scripts would be Maple Street and Shady Lane.
| | 03:04 | Now in the Update function, we'll need to
tell it rotate the object that the script is on,
| | 03:10 | but only if the rotation state is true.
Let's go out and grab that bit of code.
| | 03:16 | This is the one we want right here.
| | 03:20 | Right-click and Copy, tab over, and
since that's the Update function, I can just
| | 03:28 | paste it on top of the one that's
already there, with Ctrl+V. So now we're seeing
| | 03:34 | the if statement for the first time.
| | 03:36 | If is the reserved word, and after that
we have the clause that gets evaluated to
| | 03:42 | see if it's true or false.
| | 03:44 | Inside the curly brackets are the
instructions for what to do if the condition is met.
| | 03:50 | Now there's something new
inside the conditional clause.
| | 03:53 | A single equals sign is the assignment
operator, but the double equals sign is
| | 04:00 | the equivalency test.
| | 04:02 | That's the one we use in the
conditional, and we can see it right here.
| | 04:07 | There are other tests we can do,
depending on what we're checking.
| | 04:11 | We could use not equals, where we use
an exclamation point next to the equals
| | 04:15 | sign, we can use less than, greater than, less
than and equal to, or greater than and equal to.
| | 04:25 | All these return true or false
results when the code is evaluated.
| | 04:30 | Now we need a way to set the rotation flag.
| | 04:32 | A flag is just another name for a
variable. So out in the snippets file we'll
| | 04:38 | select our next bit of code, and as you
can see, it's an OnMouseDown function, so
| | 04:48 | let's right-click and Copy, tab back
over to the Script Editor, and we'll add it
| | 04:55 | beneath the Update function.
| | 04:58 | Order isn't really important in the
scripts, but conventionally we always add
| | 05:02 | the rest of our functions below
the Start and Update functions.
| | 05:07 | Let's go ahead and save the
script and head back to the Editor.
| | 05:10 | Our cube already has all of the
earlier scripts on it, so let's delete it and
| | 05:15 | make a new one for our new script.
| | 05:17 | First I'll double-click on
it to bring it into focus.
| | 05:20 | Then I can right-click and chose Delete.
| | 05:25 | Now from GameObject > Create Other, I'll add
a new cube, and it's added in the same spot.
| | 05:34 | This one is nice and clean though.
| | 05:36 | So let's add our new script to it
and then we'll click play and test it.
| | 05:40 | RotationController, and you can either
drag it onto the cube in the hierarchy or
| | 05:46 | you can drag it onto
the cube in the scene view.
| | 05:49 | Either way it turns up here in the inspector.
| | 05:53 | So let's click play and see if it works.
| | 05:55 | I click play and it's rotating and
according to our script, if it's rotating and
| | 06:03 | we have a MouseDown, it should stop.
| | 06:06 | And sure enough I click and it stops.
| | 06:09 | If I click again, it starts up again.
| | 06:14 | So let's go back into the Script
Editor and really look at our code.
| | 06:18 | I'll exit Play mode first.
| | 06:20 | Right now the code in our
OnMouseDown function is pretty easy to read: if
| | 06:25 | rotationState equals or is equivalent
to true, set rotationState to false; else
| | 06:33 | if rotationState is false,
set rotationState to true.
| | 06:38 | We've also got a print statement in
there so you could watch the state as it
| | 06:41 | changes, down in the status line.
| | 06:43 | But this is kind of a
long-hand way of writing this.
| | 06:47 | While this is considered good
practice, you'll also see it in its more
| | 06:50 | abbreviated form. And let's sort of look
through it and see what we could do to it.
| | 06:55 | First off, rotationState is a Boolean;
| | 06:59 | it's either true or false.
| | 07:01 | So we could get rid of this part.
| | 07:07 | And because we only have one thing
to do, if it does evaluate to true, we
| | 07:13 | could get rid of the curly brackets, and even
put it onto the same line. Both curly brackets.
| | 07:23 | And because there is only two
possibilities--it's either going to be true or
| | 07:27 | it's not--we don't even need the second if.
| | 07:33 | And what's more, it's only doing one
thing so we could get rid of the
| | 07:37 | curly brackets as well.
| | 07:39 | So this function, as it stands now, if we
click play and tried it out, would work
| | 07:45 | just as well as the original.
| | 07:48 | But to keep things more readable,
we're going to go ahead and use Ctrl+Z to bring
| | 07:54 | our OnMouseDown function back to
its original state. And there we go.
| | 08:02 | So save and then we can tab back to Unity.
| | 08:08 | Okay, that's a lot to think about,
so let's have a quick review.
| | 08:12 | The if statement evaluates the contents
of its conditional to see if it returns
| | 08:17 | true or false; if true it will do
whatever instructions follow it.
| | 08:22 | If there is more than one instruction,
they must be inside curly brackets.
| | 08:26 | If the condition evaluates to false,
we need to use an else to tell it what
| | 08:31 | instructions to carry out in that case.
| | Collapse this transcript |
| Using conditionals to create gameplay| 00:00 | Let's carry on with conditionals.
| | 00:02 | It turns out we can get pretty selective
about what goes on inside our conditionals.
| | 00:07 | Open the RotationController script
again, and we'll double-click it to bring it
| | 00:12 | up in the Script Editor. And we are
going to start by decreasing the speed each
| | 00:17 | time the cube is clicked.
| | 00:19 | We'll do this in the OnMouseDown
function by doing a little bit of math.
| | 00:23 | In the OnMouseDown function I am going
to comment out the print statement, and
| | 00:29 | underneath that I am going to go
ahead and reduce the rotation speed.
| | 00:37 | I can right-click and copy my variable
and then down inside the OnMouseDown, I'll
| | 00:44 | paste it, Ctrl+V. And I want to set
rotationSpeed equal to rotationSpeed, and I'll
| | 00:54 | paste it again, -.5, or we
could put 0.5. Either way works.
| | 01:02 | And we need to use a
semicolon to finish the line.
| | 01:08 | Notice that we don't have
to declare its type again.
| | 01:11 | In fact, if we tried, we'd get an error.
| | 01:15 | Variables only get declared once in a script.
| | 01:19 | And here is something else you'll see
too: you can abbreviate this one and make
| | 01:23 | it pretty minimal.
Sometimes you'll see it like this:
| | 01:26 | -=0.5. And that does the exact same thing,
but it's pretty cryptic, so I am going to
| | 01:40 | Ctrl+Z to get back to our original version.
| | 01:45 | Let's go ahead and click Save and we'll
switch back to the Unity Editor and give it a try.
| | 01:51 | We'll click play and each time we click
our cube, the rotation speed will slow
| | 01:58 | down so that the next time I click
and start it up again, it's slower.
| | 02:03 | Click to stop, click again to start,
and I'll just click it a few times here
| | 02:10 | and you can see each time it starts
up again, it gets slower and slower.
| | 02:19 | And we'll exit Play mode.
| | 02:20 | So once the speed gets below
about five, the rotation hardly shows.
| | 02:26 | So let's go ahead and turn it off.
| | 02:29 | Here is how to add the additional condition.
| | 02:32 | So we'll go back into our Script
Editor and in our condition rotationState =
| | 02:38 | true, we also want to stipulate that
the rotationSpeed has to be greater than
| | 02:44 | five, and here is how that's done.
| | 02:47 | Two ampersands and then we want to
make sure that rotationSpeed--and I'll
| | 02:56 | double-click and Copy and paste it
into here with Ctrl+V. So we are going to
| | 03:03 | check that the rotationState is true
and--this is our ampersand, our double
| | 03:09 | ampersand--the rotationSpeed is greater than five.
| | 03:16 | And now we can save the script, go back
into Unity, and click Play. And this time
| | 03:23 | I'll click the cube several times
quickly, and at some point it quits rotating
| | 03:35 | at all, and I am clicking
several times now. So, that works.
| | 03:39 | Let's exit Play mode.
| | 03:42 | Next let's reward the
player for being tenacious.
| | 03:45 | If the speed gets down below zero,
we'll reset it to the starting speed.
| | 03:51 | The only problem is, what if the speed we set
in the script was overridden in the Inspector?
| | 03:57 | If we look in the cube, our rotation
speed starts at 20, but maybe someone came
| | 04:03 | in and changed it to 10.
| | 04:07 | So we are going to need a way to make sure that
we get the latest value for the rotationSpeed.
| | 04:13 | By the time the Start function has
been called though, the override number
| | 04:17 | will have been read in.
| | 04:19 | So we can grab it from the
start function and store it then.
| | 04:23 | Let's open our script again, and now
we are going to need a new variable.
| | 04:28 | Let's call this one startSpeed, of type float.
| | 04:32 | So var startSpeed and that is of type
float. And let's not forget our semicolon.
| | 04:46 | But it shouldn't really be visible in
the Inspector, so I am going to go ahead
| | 04:51 | and go back here and make
it an internal variable.
| | 04:58 | And finally, we'll add the
conditional that brings the speed back up.
| | 05:02 | So let's go out and get that
one from the snippets file.
| | 05:05 | Ch04/Code_Snippets. And our last
conditional is, if the rotation speed is less
| | 05:21 | than 0, well, then we are going
to reset it to the startSpeed.
| | 05:27 | We also need to set the
startSpeed in the start function,
| | 05:32 | so let's go ahead and copy that one first,
tab back over to our scripting editor.
| | 05:43 | So we want to add that one in the start
function so it sets the startSpeed to
| | 05:49 | whatever was left in the Inspector, and now
we'll tab back over and get our final condition.
| | 05:58 | If the rotationSpeed is less than
zero, we are going to set it to the
| | 06:03 | startSpeed. Right-click and Copy, tab
over, and that one we are going to add
| | 06:12 | after the rotationSpeed has been
changed. And I am going to pop it in here,
| | 06:18 | Ctrl+V, and there it is.
| | 06:23 | So we'll click Save and see what happens.
| | 06:27 | Back to the Unity Editor. We click Play.
| | 06:31 | I'll click my cube a bunch of times.
And now it's almost at a dead stop, so
| | 06:39 | pretty soon--if we watch over here Rotation
Speed, it just got reset to 10. So there we go.
| | 06:51 | It reduces and you can watch it over
there in the Inspector, but when it gets
| | 06:56 | down to zero, the next time I click, it
goes back up, so our player is rewarded.
| | 07:03 | Let's exit Play mode.
| | 07:05 | So there go, a bunch of logic used to
control not only speed but whether the
| | 07:10 | object is even allowed to rotate.
| | 07:12 | A good part of gameplay will depend
on how thorough you are when working
| | 07:17 | out this kind of logic.
| | 07:19 | And that's when variables and if
statements come in extremely handy.
| | 07:22 | Enough of this theoretical scripting.
In the next chapter we'll start working
| | 07:27 | on our actual game.
| | 07:30 | So a quick recap. Math functions are
often abbreviated by putting the operator
| | 07:35 | before the equals sign, and to increase
the conditions that must be met in an
| | 07:40 | if statement, we can use double
ampersand for "and," and we can also use the
| | 07:46 | double bars for "or."
| | Collapse this transcript |
|
|
5. In-Game ScriptingExploring distance and local variables| 00:00 | Mouse picks and screen touches may be okay for
some situations, but a lot of things, especially
| | 00:05 | in first-person shooters, happen by
collision or even directional proximity.
| | 00:10 | The code for this stuff gets a little
more complicated, but it will be worth it.
| | 00:15 | The tradeoff is we won't have to worry about
logic and states so much; we'll be letting
| | 00:20 | the games physical world do
most of the work for us.
| | 00:23 | We'll need more than the cube to test the
stuff out on, so this time we'll be going
| | 00:28 | back to our game scene.
| | 00:30 | Let's go ahead and load the MainLevel scene.
| | 00:33 | We can find it our Project view and
double-click it in, and there we are.
| | 00:38 | We'll also be using the wide layout for this one,
so I am going to switch from 2 by 3 to Wide.
| | 00:46 | Let's start by creating a new script
in there Practice Scripts folder.
| | 00:50 | Let's go over here and find it.
| | 00:52 | Here is our Practice Scripts,
right-click, Create > JavaScript.
| | 00:58 | And this one we are going
to name ReportDistance.
| | 01:03 | And we'll go ahead and open
it in the Script Editor.
| | 01:06 | The first thing we need to do is give it a variable
that will hold the object we are checking on.
| | 01:12 | Notice I said object,
not the name of an object.
| | 01:16 | This is a key concept in Unity.
| | 01:19 | We'll start by calling our variable
targetObject. So I am going to go up here, give myself a
| | 01:24 | little bit of room with the Enter key.
| | 01:27 | We start with var, and we are
naming this one targetObject.
| | 01:34 | And here comes the tricky part. We need to
decide what type our variable needs to be.
| | 01:40 | So let's think about it.
| | 01:41 | We need to know its position to be able to
calculate the distance from the object that
| | 01:47 | has the script on it.
| | 01:48 | A while back when we were looking up transforming the
docs, we found that every object has a transform,
| | 01:55 | and from that we can get
its position information.
| | 01:58 | So for type we are going to choose Transform.
| | 02:03 | :Transform, and we'll finish
our line with a semicolon.
| | 02:10 | Next we need to get the distance.
| | 02:12 | Since distance is something that should be
calculated every frame, we are going to need
| | 02:17 | to put our distance-checking
code in the update function.
| | 02:20 | This one is a little trickier so I am going
to go out and find my code snippets and copy
| | 02:25 | and paste from there.
| | 02:27 | From my exercise files folder Ch05/
05-01, there is our Code_Snippets.
| | 02:35 | Here is our variable.
| | 02:36 | I type that in manually this time,
but this is the line that we want.
| | 02:41 | Highlight, Right-click > Copy,
get back to the Script Editor,
| | 02:47 | and this one, as I said earlier, is
going to go into the update function.
| | 02:51 | Give it some space and Ctrl+V to paste it in.
| | 02:57 | So let's look at what we've just added.
| | 02:58 | We are little short of space here, so I
am going to reduce the other sections.
| | 03:04 | And let's see what we've got.
| | 03:06 | We have our if statement, then our variable name
all alone as the condition, if (targetObject).
| | 03:15 | Before we saw if a variable was a Boolean
type it was true or false, and we are checking
| | 03:20 | the conditional to see if the
expression in it evaluates to true or false.
| | 03:25 | So what's the deal?
| | 03:26 | It turns out that if we try to get the distance from
an object that did not exist, we'd get an error.
| | 03:33 | If we wrote the conditional out
long-hand it would look something like this.
| | 03:38 | targetObject is not equal to null.
| | 03:44 | So if the targetObject wasn't equal
to null, it would evaluate to true.
| | 03:50 | Don't confuse null with zero; null is nothing.
| | 03:54 | If a variable does not have
a value, its value is null.
| | 04:00 | Let's look at the next line.
| | 04:01 | var means we are declaring a variable and its name,
well, in this case is dist, short for distance.
| | 04:09 | Next, we are feeding two positions into the
Vector3.Distance to get the distance, targetObject.position
| | 04:18 | and this.transform.position.
| | 04:22 | Remember that our
targetObject is already a transform.
| | 04:26 | One more thing about our dist variable: because it
was declared inside a function, it is considered
| | 04:34 | to be a local variable.
| | 04:36 | That means it's created each time the function is
entered and destroyed as soon as the function is exited.
| | 04:43 | So this one being in the update function is
created and destroyed every frame. And there
| | 04:50 | is one other thing: because it doesn't exist
outside its own function, a local variable
| | 04:56 | is not accessible to any
other functions in the script.
| | 05:01 | Let's save the script and test it.
| | 05:03 | I'll click Save and back to the Unity Editor.
| | 05:08 | And now we need to figure
out what to do with it.
| | 05:12 | To make it interesting, at least one of our
objects needs to be moving, and the only mobile
| | 05:17 | object we have so far is
the First Person Controller.
| | 05:21 | So let's drag our script, ReportDistance, on
the Bridge Plank and use the First Person
| | 05:27 | Controller as the target object.
| | 05:29 | I'll need to open my structures for
seeing to find the Bridge Plank. Here it is.
| | 05:35 | So I'll drag and drop it
right onto the Bridge Plank.
| | 05:39 | Now if I select it and I look almost at the
bottom--here it is, Report Distance--we notice
| | 05:44 | it is looking for the
targetObject, and it has a None in it,
| | 05:48 | but it's expecting a transform type.
| | 05:51 | Here is how we load it.
| | 05:53 | We just drag the First Person Controller
from the Hierarchy view onto the targetObject
| | 05:59 | value field, and there we go.
| | 06:02 | First Person and if we drag this
out, we can see the whole name here.
| | 06:09 | And we are ready to test. And we are going
to be watching the status line down here as
| | 06:13 | it reports the distance.
| | 06:16 | Let's click play. We are now showing the game
window, and I am going to click W. And watch
| | 06:22 | the target distance down in the status line
and we'll head out towards the Bridge Plank.
| | 06:28 | And the closer we get,
the smaller the number becomes.
| | 06:32 | Its pivot point is on the far side,
so right about there it's almost zero.
| | 06:39 | Let's exit play mode and
look at one more thing.
| | 06:42 | If we have a lot of objects with the same
script that need the same targetObject, it
| | 06:47 | might get tedious dragging and
dropping it onto each one.
| | 06:52 | If the targetObject is always the same for
the script, you can find it and assign it in
| | 06:57 | the Start function.
| | 06:59 | Let's open the script again and
add the next line to our code.
| | 07:04 | Over to my snippets code, and I am going to
grab the entire start function and right-click,
| | 07:10 | Copy, tab back to the Script Editor, and I'll
replace the existing function start with the
| | 07:19 | code that I copied from the
snippets. And Ctlr+V to paste.
| | 07:26 | So now what's going to happen is, we have
our targetObject variable, but in the start
| | 07:31 | function, it's going to go out and it's going
to search the entire game to see if it can
| | 07:38 | find something called First Person Controller.
| | 07:41 | And then it's going to get its transform and it's
going to feed all of that back into our variable.
| | 07:47 | Theoretically, we don't need the variable
to show up in the Inspector anymore, but I
| | 07:53 | am going to leave it here just so we can
check and make sure it actually did find it.
| | 07:57 | We'll go ahead and save our script,
tab back to the Unity Editor,
| | 08:03 | and just to make sure we can see that it's
doing its job, over here in the targetObject--
| | 08:09 | remember, we have the Bridge Plank selected--
| | 08:12 | I am going to open the
browser and set this to None.
| | 08:17 | When we click play, keep an eye out over here
and as soon as it starts, it should find the
| | 08:23 | First Person Controller.
| | 08:25 | So let's click play and there you go;
| | 08:28 | it found our First Person Controller.
| | 08:31 | So we can go ahead and exit Play mode now.
| | 08:34 | In this video we found out how to both load
and find a game object for use in a script,
| | 08:40 | which is a mainstay of Unity game authoring.
| | Collapse this transcript |
| Raycasting| 00:00 | So we have been experimenting with
distance checking, but there will be times
| | 00:04 | when the only thing we care about is
what is in front of the player or in the
| | 00:07 | case of a mouse pick or touch event,
what is under the cursor or finger.
| | 00:12 | To do that, we need to cast a ray into the scene.
| | 00:15 | If you think that sounds
suspiciously like vector math, you'd be right.
| | 00:19 | But don't panic; Unity will take
care of the calculations for us.
| | 00:22 | The cool thing about ray casting is
that we get a bunch of useful information
| | 00:27 | back when something is detected.
| | 00:30 | You may wish to double-click the First Person
Controller to get a better view in the Scene view.
| | 00:34 | This time, in the Practice Scripts folder,
let's create a new script and call it RayCaster.
| | 00:41 | Practice Scripts, right-click >
Create > Javascript, and we're going to
| | 00:47 | name this guy RayCaster. And we'll open him
up in the Script Editor by double-clicking.
| | 00:54 | Let's make sure we're over in the
RayCaster script, and in the update function
| | 00:59 | we're going to need lots of code,
| | 01:01 | so I'm going to copy it from the snippets file.
| | 01:04 | I'll tab out. From the exercise files
folder, Ch05/05-02, I'll open my Code
| | 01:13 | Snippets, and we want to take the
whole first section here. Right-click and
| | 01:19 | Copy, and then we'll tab back over to
the Script Editor, give ourselves a little
| | 01:24 | room, and paste it in.
| | 01:27 | Let's see what we've got this time.
| | 01:30 | The first line uses the RayCaster
function from the physics class to see if
| | 01:34 | there is anything straight ahead and within
ten meters of the object the script is on.
| | 01:38 | And since the whole kit and kaboodle is
in the if statements condition, we're
| | 01:42 | having it tell us when it evaluates as
true--in other words if it has detected
| | 01:47 | something ten meters.
| | 01:49 | Let's go ahead and save our script,
head back to the Editor, and then we can
| | 01:54 | apply it to the First Person Controller.
| | 01:57 | RayCaster, we'll drag and drop them
right onto the First Person Controller.
| | 02:01 | Now before we hit play, let's go back
into the Script Editor, and if we look,
| | 02:07 | we can see that the Unity Script Editor has
been tabbing scripts that we've already had open.
| | 02:13 | I remember that in report distance we
were having it print out to the console,
| | 02:19 | and I think we need to suppress that.
| | 02:21 | And we'll use the double
forward slashes to comment it out.
| | 02:26 | That way the message we're sending out
from the RayCaster script will be easily
| | 02:30 | seen in the status line.
| | 02:32 | So save. Now we can go back to the
Editor, click play, and drive our First
| | 02:39 | Person Controller around, watching the status
line. There is something in front of the object.
| | 02:45 | Exit Play mode.
| | 02:46 | As you might guess, there is pretty much
always going to be something within ten
| | 02:51 | meters of the First Person Controller.
Even if there wasn't, there is no message
| | 02:55 | to tell us that, so we really ought to add one.
| | 02:58 | Let's go back to the Script Editor,
and we're going to add an else clause.
| | 03:03 | Let's go ahead and close out the other
two scripts so we won't get confused.
| | 03:08 | Now that we're in the RayCaster
script, we're ready to add our else clause.
| | 03:12 | I'm going to tab over, and we're
going to add else print, "There's nothing
| | 03:18 | directly ahead," and we end
our line with a semicolon.
| | 03:23 | So we can go ahead and save, toggle
back to the Editor, click play, and this
| | 03:29 | time our message in the status line
should change as we move around the scene.
| | 03:34 | Using my W key and we can see it changing.
| | 03:39 | This is marginally more helpful, but it
would be even better if it could report
| | 03:42 | what the object was within ten meters.
| | 03:45 | Let's exit Play mode. It turns out that
many functions are capable of taking
| | 03:50 | different arguments.
| | 03:52 | For the Physics.Raycast we just used,
we fed it an origin, a direction, and a
| | 03:57 | distance--the length of the ray.
| | 04:00 | If we want to know about the object the
ray cast found or hit, we need to add a
| | 04:05 | new variable. So let's get back to our
Script Editor, and at the top we're going
| | 04:11 | to add var of type RaycastHit.
| | 04:15 | So colon, space, and that's a capital R,
RaycastHit, and the closing semicolon.
| | 04:24 | You might also want to add a comment,
something like "holds some of the properties
| | 04:28 | of the object that is detected."
| | 04:31 | And now we need to add the hit
variable inside the Physics.Raycast.
| | 04:37 | And that goes right before the ten
meters. Give them a space, type "hit," and
| | 04:44 | another comma so it knows
it's a different parameter,
| | 04:47 | and we should be good to go.
| | 04:49 | It's worthwhile looking at both
Physics.Raycast and RaycastHit. They may not
| | 04:55 | make a whole lot of sense yet,
but it won't hurt to check them out.
| | 04:58 | I'm going to go ahead and save my
script, tab back into the editor, and from
| | 05:03 | the Help window, this time in the
Scripting Reference, in the search field,
| | 05:09 | let's go ahead and type "RaycastHit" and
hit Enter, and the first one at the top
| | 05:14 | of the list is RaycastHit.
| | 05:17 | We can see that it automatically can
return a distance. And we can also get a
| | 05:23 | transform of the object we hit, and if it's
got a transform, we can get its name property.
| | 05:29 | So now let's change the print line in
our script so that we can see what we hit.
| | 05:35 | I'm going to tab back over to the
Script Editor, and in my print statement I'm
| | 05:40 | going to change it to "there is a," and
then I'll add the quotation marks, give
| | 05:45 | myself a space before them, and then
we're going to put hit.transform.name.
| | 05:53 | And let's not forget the plus marks to
concatenate our strings together.
| | 05:59 | For the last part, we can
just say space directly ahead.
| | 06:02 | That looks pretty good.
| | 06:04 | Let's save the script, head back to
the editor, and now if we hit play, we'll
| | 06:11 | see a lot more information down there.
| | 06:14 | Nothing directly ahead, terrain,
building outer. So there we go.
| | 06:20 | It works. Let's exit Play mode.
| | 06:23 | If you drove your First Person
Controller as far as the bridge plank, you may
| | 06:27 | have noticed that it's never detected.
| | 06:29 | That's because we put the script
on the First Person Controller.
| | 06:34 | If we did go out there and we looked up
and down, we'd notice that only the camera is
| | 06:39 | looking at the bridge.
| | 06:40 | If we wanted to see what the ray cast
is looking at rather than what's directly
| | 06:45 | ahead, we would have needed to
put the script on the camera.
| | 06:49 | So with Physics.Raycast, you can
see that we can get a bunch of useful
| | 06:53 | information back when something is detected.
| | Collapse this transcript |
| Building timers| 00:00 | Another thing that is going to be
useful in many games is the timer.
| | 00:04 | For that we'll start by getting the
time in seconds since the game started.
| | 00:08 | We'll do that with Time.time.
| | 00:12 | To check it out, we'll just borrow our
RayCaster script and we'll test the code that way.
| | 00:17 | So let's open our RayCaster script,
and I'm going to start by commenting out our
| | 00:23 | two print statements, forward slash, two of them.
| | 00:27 | And below the else I'm going to add our new
little bit of code, and this one is pretty simple.
| | 00:34 | We're going to print Time.time,
and that's a T on the first one. (Time.time);,
| | 00:48 | and then we'll go ahead and save this
guy, and we'll tab back to the editor.
| | 00:53 | Now watching the status line, as soon
as we click play, you'll be able to see
| | 00:58 | the time ticking away.
| | 01:00 | Let's go ahead and exit Play mode.
| | 01:02 | We really need a way to show the time in
the viewport so the player can see it too.
| | 01:08 | When we cover Unity GUI elements we'll
use only scripting for onscreen displays.
| | 01:14 | For now though, because many of you are
new to scripting, we're going to use a
| | 01:18 | Unity object, the Unity GUI
Text Object. Let's create one now.
| | 01:24 | From GameObject > Create Other,
we're going to select GUI text.
| | 01:30 | It comes in in the middle of the
viewport, and we can see it in the Hierarchy
| | 01:34 | view. Let's name it Timer Text.
| | 01:38 | Over in the Inspector we
have access to its parameters.
| | 01:41 | Let's set the Text field to zero
and change the Anchor to lower-right.
| | 01:47 | Here is our text field, we're going to
set that to zero, and we'll change our
| | 01:52 | anchor to lower-right.
| | 01:54 | Arial is the default font in Unity, and
font size, if set to zero, is its default size.
| | 02:01 | System fonts such as Arial can be
dynamically sized since the operating system
| | 02:05 | already has, or can generate,
them in the different sizes.
| | 02:10 | Our text is a little small,
so let's go ahead and set it to about 28.
| | 02:14 | We'll turn on Maximize on Play in our
Game window, and when we click play we can
| | 02:23 | see the text right in the middle of the window.
| | 02:26 | Let's exit Play mode and position it.
| | 02:29 | To position a GUI text object
we need to use the transform.
| | 02:34 | I can move my text object by moving my
cursor over the label in the transform
| | 02:40 | and clicking and dragging, or I
can type directly in the text field.
| | 02:44 | So now that we've got our little heads-up
display, it's time to make a new script for it.
| | 02:51 | In the Practice Scripts folder,
let's create a new script.
| | 02:55 | So we right-click, Create > Javascript,
and we'll name this one simply Timer, and click Enter.
| | 03:03 | You'd think that scripting the time
to show would be as easy as text =
| | 03:09 | Time.time, but it's not.
| | 03:12 | If we check the Inspector for the timer
text, we can see that the Text parameter
| | 03:18 | is in the GUI Text component.
| | 03:21 | To access that, we'll need
to get the component first.
| | 03:25 | Let's open our Timer script, and then I'm
going to head over to my snippets to grab the code.
| | 03:32 | exercise files, 05-03/Code Snippets,
we've already tried this one, so we want
| | 03:41 | this line right here.
| | 03:42 | GetComponent, right-click > Copy, and
then we'll Tab back to the Script Editor.
| | 03:50 | And since this is something that
happens every frame, we're going to paste it
| | 03:53 | into the Update function.
| | 03:55 | And if we're going to be nice and tidy,
we'll go ahead and give it a tab here.
| | 04:00 | I've got GetComponent and it's going
to get the GUI Text component, and it's
| | 04:05 | going to get its text parameter, and then
it's going to assign Time.time to that parameter.
| | 04:12 | We'll save. But when I go back to the Editor, the
console--let's click it open here--
| | 04:19 | is giving me an error.
| | 04:21 | It says, "Cannot convert float to string."
| | 04:25 | The time parameter can only
take a string-type variable.
| | 04:28 | So now we need to wait to cast a float to a
string. Let's get back to our Script Editor.
| | 04:36 | The normal JavaScript use would be ToString
and then in parentheses you'd have Time.time,
| | 04:43 | but that gives us an error in Unity.
| | 04:45 | So a search of the Unity community
will turn up what we need. In this case
| | 04:50 | we need to use some number here
.ToString() with empty parentheses, so let's
| | 04:57 | try that right now.
| | 04:58 | Here is our number, Time.time. We need to
add .ToString and then empty parentheses.
| | 05:08 | Let's save the change and check back
in the console. Give it a chance to
| | 05:13 | update and it's happy now.
| | 05:16 | And now we can go ahead and add our
new script to our GUI text object.
| | 05:20 | I'll just close the console first.
| | 05:22 | Here is our Timer script, and we'll add
it to our Timer Text, and when we click
| | 05:28 | play, we see the results.
| | 05:30 | There is nothing like fractions of a
second ticking over to pressure our player.
| | 05:35 | Let's exit play mode.
| | 05:37 | To lower the pressure, why don't we try
converting the float to an integer first?
| | 05:43 | It turns out this is another of those
oddballs that doesn't follow the usually
| | 05:47 | Unity JavaScript rules.
| | 05:49 | Let's go back over to our Script
Editor and see what we need to do.
| | 05:54 | This time it gets an argument, the float,
| | 05:56 | but the function name is not capitalized.
| | 06:00 | So first we need to
convert the float to an integer.
| | 06:03 | That's going to look like this.
| | 06:05 | parseInt and then we put our
Time.time in between the parentheses as the
| | 06:13 | argument, and then we
finish up with our ToString.
| | 06:18 | Let's go ahead and save the
script and see what we've got now.
| | 06:22 | Tab to the editor and click play.
| | 06:25 | And now it's much better.
| | 06:28 | Let's exit Play mode.
| | 06:30 | Our little timer is working nicely,
but if we need to make a regular timer, we
| | 06:35 | will be able to start the timer by
storing the current Time.time and the
| | 06:40 | subtracting the end time
to find the elapsed time.
| | 06:43 | Since we really don't a timer at all
for our game, I'm going to go ahead and
| | 06:47 | deactivate the Timer Text
object back in the Hierarchy view.
| | 06:51 | So we select it, and remember,
we can deactivate an object up in the
| | 06:55 | Inspector, like so.
| | 06:57 | We'll be using GetComponent regularly
throughout this course, but you might want
| | 07:03 | to make a note of ToString and
parseInt since they are oddballs.
| | Collapse this transcript |
| Creating a simple projectile| 00:00 | With first-person shooters, a good
portion of the animation is driven by physics,
| | 00:05 | but when we talk about physics and game
engines, you need to understand that the
| | 00:08 | game engine physics are only a
rough approximation of real physics.
| | 00:13 | The calculations involved with the
real thing takes way too long to use in a
| | 00:16 | real-time environment.
| | 00:18 | Bottom line, game physics is not a silver bullet;
| | 00:21 | it won't magically solve everything.
| | 00:24 | On the other hand, it's excellent for
producing the randomness that's lacking
| | 00:28 | in keyframe animation.
| | 00:29 | We'll take a closer look at physics
later on in the course, but since we'll need
| | 00:34 | it for our simple projectile,
we'll go ahead and get a sneak peak now.
| | 00:39 | Let's start by switching to the 2 by 3 layout.
| | 00:42 | Up at the top, 2 by 3. And let's
load the scripting test scene.
| | 00:48 | Here it is right here.
| | 00:50 | Select the cube and rename it
Cube1 or something to differentiate it.
| | 00:54 | So I'm going to put it into Rename mode
and I'll just add a 1 to it. And then
| | 01:00 | we want to focus in on it, double-
click, and we'll create another one,
| | 01:04 | GameObject, > Create Other >
Cube. We'll name this one Ground.
| | 01:12 | And I'm going to scale this one, zoom
out a little and squash it down, so that
| | 01:19 | we have a Ground object. And you may
want to scale it a little bit bigger.
| | 01:23 | Then I'll go ahead and move it down
so that it's just beneath our cube.
| | 01:27 | Now let's create one more cube,
and once again let's focus in our first one,
| | 01:33 | GameObject > Create Other > Cube, and
this one I'm going to use my middle-mouse
| | 01:40 | roller to zoom out, and we want to move
this one up slightly above the other one,
| | 01:45 | by pulling on the Y axis handle.
| | 01:48 | Let's adjust the view using our main camera.
| | 01:51 | We might want to go ahead and use
GameObject > Align With View, and so now we can
| | 01:58 | see them both on our game view.
| | 02:00 | Let's go ahead and click
play and see what happens.
| | 02:03 | Our bottom one that had the script on
it is rotating, but our top one is just
| | 02:07 | hanging there in space.
| | 02:09 | Let's exit Play mode
and see what we need to do.
| | 02:12 | For physics to come into play
objects need a rigid body component.
| | 02:18 | So we'll select our cube--
| | 02:19 | that's the top one--and from the
Components menu, under Physics, we are going
| | 02:25 | to add a Rigidbody.
| | 02:27 | And we'll just leave all the default as is.
| | 02:31 | Now when we click play, the cube drops.
| | 02:35 | Let's exit Play mode again
and make it a little different.
| | 02:39 | I'm going to zoom out slightly in my
scene view. And I want to move my cube over
| | 02:45 | just a little bit, because we want them
to still hit the edge of this cube, and
| | 02:49 | we're going to move them up higher
so he has a longer distance to fall.
| | 02:53 | It looks like I could drag him over a
little bit farther, and I want him to just
| | 02:58 | hit the corner. Now click
play and watch what happens.
| | 03:02 | It hits, tips, falls again wobbles and
settles. And that's a lot of animation for
| | 03:07 | practically no effort.
| | 03:09 | Gravity did most of the work.
| | 03:11 | Best of all, we didn't need to do
anything to any of the other objects. And we
| | 03:16 | can go ahead and exit Play mode.
| | 03:18 | Now that we've seen a little bit of
physics in action let's go ahead and load
| | 03:22 | our main level, double-click it.
| | 03:25 | Yes we can save the scene.
| | 03:28 | And now we're ready to make our projectile.
| | 03:30 | So gravity maybe free with rigid bodies,
but everything else needs to be scripted.
| | 03:35 | So let's start by creating a
new folder called Game Scripts.
| | 03:40 | This time I'm going to go up to Assets.
| | 03:43 | It brings up the same as the right-
click menu. Then I'm going to say Create >
| | 03:47 | Folder, and we're going to name this
guy Game Scripts. And this is going to be
| | 03:54 | our first real script for our game.
| | 03:56 | We want to create a new script, so right-
click > Create > Javascript, and we're
| | 04:02 | going to name this guy Projectile.
| | 04:03 | And we'll go ahead open
him up in the Script Editor.
| | 04:08 | The first thing we're going to need to
add is a variable for our projectile.
| | 04:13 | So I'm going to give myself a little
bit of space here, and that's going to be
| | 04:18 | var. And we'll call it projectile,
lowercase because this is a variable name.
| | 04:24 | And this guy needs to be of
type GameObject, and semicolon.
| | 04:31 | And now we'll need some
code in the Update function.
| | 04:34 | This is a quite bit of new code, so I'm
going to tab out to my desktop and pick
| | 04:39 | up my Code Snippets from 05/05-04.
We'll open these guys up.
| | 04:48 | There is our projectile variable that we
added, and we want everything underneath that.
| | 04:53 | And that's including the Update function.
| | 04:56 | So we'll right-click and Copy, and then
we'll tab back over to our Script Editor,
| | 05:02 | and since we already have the Update
function, we'll just paste it over the whole thing.
| | 05:06 | So let's see what we've got here.
| | 05:09 | Our variable is of type GameObject
because we'll need access to more than
| | 05:13 | just its transforms.
| | 05:15 | Next, we see that our code is in the
Update function, and this is because
| | 05:20 | the engine needs to constantly check to see
if the player has pressed the fire button.
| | 05:25 | So far, nothing new, but now in the
conditional of the if statement, we see
| | 05:30 | something that says Input.
Getbutton and ("Fire1").
| | 05:38 | If that condition is true, do the then clause.
| | 05:42 | We'll cover that in a minute,
but let's go back to that Input.Getbutton.
| | 05:45 | Obviously we are dealing with
a user input button press.
| | 05:50 | The mystery is, which button is Fire1?
| | 05:54 | Fire1 is just a virtual button.
| | 05:57 | We or the player can map anything we
want to it. But let's take a quick peek to
| | 06:02 | see what the default mapping is.
| | 06:04 | We'll need to head back to the editor
for that and from the Edit menu > Project
| | 06:10 | Settings, we're going to
look at the first one, Input.
| | 06:14 | Over in the Inspector, we now see
something called Axes. We'll open that guy up
| | 06:20 | and there it is, Fire1.
| | 06:22 | Well, let's see what it has in it.
| | 06:25 | Fire1 it turns out is using the left
control button and is also using mouse
| | 06:32 | zero, which is also the left mouse button.
| | 06:36 | So let's go back to the Script Editor and add a
comment in the code to remind us what they are.
| | 06:41 | I'll tab back over to the Script Editor,
and then I'm going to make some space
| | 06:46 | up above our conditional and add a comment.
| | 06:49 | Fire1 button is left mouse or left Ctrl key.
| | 06:55 | And now let's see what pressing
the fire button is supposed to do.
| | 06:58 | First, it creates a new variable called clone.
| | 07:02 | Well, this is the tricky part
and another key feature in Unity.
| | 07:06 | It instantiates or creates a new copy
of the object that we will be loading in
| | 07:11 | to the projectile variable, and it
does it at the location and orientation of
| | 07:18 | the object that the script is sitting on.
| | 07:20 | It won't go anywhere yet, but at
least it will be making a projectile.
| | 07:25 | So let's go ahead and save our
script and head back to the editor.
| | 07:30 | Now we could put the script directly on
the First Person Shooter, but that would
| | 07:35 | make it hard to position, so
instead let's focus in on the First Person
| | 07:40 | Shooter's main camera. To do that we'll
need to open this hierarchy up, and we'll
| | 07:46 | double-click to focus in on the main
camera. Use Alt and left mouse button to
| | 07:52 | rotate our view so we actually get to
see him. Double-clicking again to make
| | 07:57 | sure we're focused there, and now
we're going to make an empty GameObject to
| | 08:01 | organize any gear our player may end up with.
| | 08:04 | So GameObject > Create Empty, and we're
going to name this guy Weapon Handler, and
| | 08:12 | hit Enter. And we need to
add that to the main camera,
| | 08:16 | so I'll click and drag it
and drop it on the main camera.
| | 08:20 | And now we'll make a proxy weapon from
a cube to give the projectile a place to
| | 08:25 | be instantiated from.
| | 08:26 | GameObject > Create Other > Cube.
| | 08:31 | Focus in on this guy to get a little closer.
That's much better.
| | 08:35 | And what we want here is we want to
kind of shape it long and narrow, so I'm
| | 08:40 | going to use my uniform skill first.
| | 08:42 | That's by clicking on the center cube.
| | 08:45 | Then I'll go ahead and scale it on
the Z to make it a little bit longer, so
| | 08:49 | it'll look more like a weapon.
| | 08:52 | And maybe I need to scale it down a little more.
| | 08:55 | Now this guy needs to be positioned so
that its Z axis points forward, just like
| | 09:01 | the First Person Controller.
| | 09:03 | So I'm going to switch back over to
position and make sure I know which way
| | 09:07 | my First Person Controller is facing.
It looks like he is facing that direction.
| | 09:12 | So I want to make sure my Cube, which by
the way we want to name Proxy Weapon, is
| | 09:19 | going to be facing the same direction,
which means we're going to have to rotate
| | 09:22 | this one. And I'm going to do it
scrubbing my Y label over in the Inspector.
| | 09:28 | And if I remember correctly, that's which
direction our First Person Controller is.
| | 09:34 | And I got it to 86.28, so I'm just
going to click inside the field and type 90.
| | 09:39 | And we probably don't want it quite as
high as the head, so I'm going to drop it
| | 09:45 | down to about there.
| | 09:46 | Now we can start seeing it in the game
view, so you can do a little bit more
| | 09:50 | adjusting there if you'd like. You might want
to move it to the side and bring it down a little.
| | 09:57 | So this is going to be our proxy weapon,
and this is where the script we're writing is
| | 10:01 | going to be placed, because this is
where the projectile is going to come from.
| | 10:05 | This one also needs to be
put on the weapon handler,
| | 10:10 | so I'll drag it on to the weapon
handler object. And now our hierarchy for the
| | 10:17 | First Person Controller should look like this.
| | 10:20 | Here is the First Person Controller, its Main
Camera, its Weapon Handler, and the Proxy Weapon.
| | 10:27 | Now we're going to need our
projectile. This one is easy.
| | 10:31 | From GameObject > Create Other, we're
going to create a sphere. And you can move
| | 10:38 | it anywhere you want because
we're going to delete it eventually,
| | 10:41 | but I'm going to go ahead and
scale it down to about 0.25.
| | 10:46 | You could make it exact in there if you
wanted, but that's all we need; we just
| | 10:49 | need to get close to it.
| | 10:51 | This guy we want to name Cannonball.
| | 10:54 | And so we can get all that physics,
we need to add a Rigidbody component to it.
| | 10:59 | So Component > Physics > Rigidbody.
| | 11:03 | The Rigidbody is needed for it to
react with physics, including gravity.
| | 11:09 | In order for an object to be
instantiated, or created on the fly, we need to have
| | 11:14 | what is called a prefab
of it in the Project view.
| | 11:18 | We'll get lots of practice with
prefabs later, but for now let's just make
| | 11:22 | one for the sphere.
| | 11:24 | From the right-click menu > Create > Prefab.
| | 11:29 | And it sort of ended up where I don't
want it, so I'm going to just drag it out.
| | 11:34 | It doesn't really matter where you
drag it, as long as you get a bar.
| | 11:37 | Unity is going to alphabetize this
anyway. And there we go, a new prefab.
| | 11:43 | And we're going to call this guy Cannonball.
| | 11:47 | Notice right now the little icon cube is white.
| | 11:51 | As soon as we drag our Hierarchy
Cannonball into it, it's going to turn blue.
| | 11:59 | This means it's ready to go.
| | 12:01 | It also means we can select
our original one and delete it.
| | 12:06 | So now our game has the concept.
| | 12:08 | It has the blueprint, so to speak, to
make a cannonball anytime we ask for it.
| | 12:14 | Let's go ahead and load it into our weapon.
| | 12:16 | If we select our proxy weapon, we see
that first we are going to need to add our
| | 12:21 | projectile script to it.
| | 12:22 | And in the Inspector, under its
Projectile parameter, that is where we need
| | 12:29 | to add our Cannonball.
| | 12:31 | So we drag it from the Project view
right into that field. We're all set.
| | 12:36 | I'm going to double-check on our
Script Editor to make sure that we've saved
| | 12:41 | the latest changes.
| | 12:43 | And yes, we have; it's
grayed out, so we're good to go.
| | 12:46 | So let's get back to the editor.
And it's finally time to test,
| | 12:50 | so let's click play, move the cursor
to the Game window, and either click the
| | 12:56 | left Ctrl button or left mouse button.
| | 13:01 | Nothing is moving much yet, but if you
watch the Hierarchy, you can see there are
| | 13:05 | a lot of Cannonball Clones
being created, every time we click.
| | 13:10 | We'll get our wayward projectile and
virtual fire button under control in
| | 13:14 | the next video.
| | Collapse this transcript |
| Refining the projectile| 00:00 | We made an excellent start on our
projectile in the last video, but now we need
| | 00:04 | to solve the problem of too many projectiles.
| | 00:07 | Open the Projectile script and
we're going to add a new variable.
| | 00:12 | Underneath projectile, we're going to add
var fireRate, of type float, and this one
| | 00:21 | we are going to go ahead initialize
it to 0.5, and we'll add our semicolon.
| | 00:31 | This will be how long before
the next projectile can be fired.
| | 00:34 | Next we're going to need an internal
variable, and we're going to name this guy
| | 00:39 | nextFire to keep track of when the
next projectile can be fired, and that's
| | 00:44 | where Time.time comes in.
| | 00:47 | So our next variable is var nextFire.
| | 00:54 | It's also of type float, and this one
we're not going to initialize. And I said
| | 01:01 | it was going to be internal,
so let me go back and add that.
| | 01:04 | Remember, internal means that it's
not going to show up in the Inspector.
| | 01:08 | Next, we'll need to add the
extra condition to our if clause.
| | 01:13 | This is the part that prevents all
those extra projectiles. And that goes into
| | 01:17 | our if clause, and we're going to use
our && for "and." And the second condition
| | 01:25 | that needs to be met is Time.time > nextFire.
| | 01:32 | Also, we need to update the nextFire
variable each time we do fire it off,
| | 01:38 | so we'll do that even before we
instantiate the current projectile. And we can
| | 01:44 | add that right above the instantiation
line, nextFire = Time.time+fireRate.
| | 01:56 | And of course we need to finish
our line with a semicolon.
| | 02:01 | So this is basically like we're looking
at a clock and saying some event can't
| | 02:06 | happen until it's five minutes
from now, or in our case, 0.5 seconds.
| | 02:12 | Let's save the script and then
we will tab back into the editor.
| | 02:16 | Let's click play and fire it off with either
the left control button or the left mouse button.
| | 02:22 | This time only one is
generated per click or key press.
| | 02:26 | Let's exit Play mode and get
our cannonball going somewhere.
| | 02:30 | We'll be doing that by giving it some velocity.
| | 02:33 | Let's toggle over to the Script Editor again.
| | 02:35 | First, we'll need a variable to control
its speed, so I'm going to add another
| | 02:41 | variable, var speed, of type float,
and we are going to initialize that guy to 5.
| | 02:52 | The last two lines are pretty complicated,
so I'm going to copy them from the Snippets file.
| | 02:57 | I'll just tab out there and find them.
| | 02:59 | exercise file, Ch05/05-05.
| | 03:05 | Here is our Code_Snippet. So we've done
most of these, but these are the two we need.
| | 03:11 | I'm going to grab them
both and right-click and Copy.
| | 03:15 | Then I'll tab back over to my Script
Editor. And these guys go right below
| | 03:21 | the clone line, because we have to have
something to project before we can project it.
| | 03:25 | So I'm going to Ctrl+V and paste.
| | 03:29 | I've got a line here I don't need,
so I'm going to get ride of that guy. And then
| | 03:33 | I'll tab this line over
so it matches up better.
| | 03:37 | So let's see what we've got here.
| | 03:39 | The velocity line is not as bad as it looks.
| | 03:42 | It just sends the
projectile off in the Z direction.
| | 03:45 | That's where we've got our speed variable.
| | 03:47 | But the second line is also important.
| | 03:50 | Remember how our cube reacted with
the other objects in our physics test?
| | 03:55 | This line tells the projectile to
ignore the root object the script is on,
| | 04:00 | the First Person Controller's Collider.
| | 04:02 | In our case, we also have the Proxy Weapon;
| | 04:06 | we're just using it as a placeholder
so we'll need to remove its Collider
| | 04:10 | component when we get back into the editor.
| | 04:13 | For now, let's go ahead and save and
now we can tab back to the editor. And I'm
| | 04:19 | going to open up my First Person
Controller > Main Camera > Weapon Handler, and
| | 04:26 | select the Proxy Weapon.
| | 04:27 | We are going to remove the Box
Collider so the projectile doesn't collide
| | 04:32 | with the Proxy Weapon.
| | 04:34 | We can do that by right-clicking and
choosing Remove Component. That should be it.
| | 04:39 | We've saved the script, we're back in
the editor, and so now we can click play
| | 04:45 | and test our new projectile.
| | 04:47 | Be sure you move your cursor back into the
Game window before you click Fire, and there I go.
| | 04:54 | Well, it looks like 5 is a pretty
paltry speed for our projectile,
| | 04:59 | so I'm going to go back over to our
Projectile script where it's on the Proxy
| | 05:04 | Weapon, and I'm going to change my
Speed until it's something I like.
| | 05:08 | I'm going to try about 20.
| | 05:11 | Now when I get back here in the Game
window, we're getting some better action.
| | 05:17 | Remember though, as soon as we exit
play, we need to go back to the Inspector
| | 05:23 | and reenter the value so it becomes permanent.
| | 05:26 | We are well underway with our
Projectile, but we'll still need to do some
| | 05:30 | cleanup in the next video.
| | Collapse this transcript |
| Exploring the OnCollision variable and tags| 00:00 | Now let's tidy up the projectile
and incorporate it into our game.
| | 00:05 | The first barricade is conveniently open,
but the second won't be so easy to win through;
| | 00:09 | it will need to be bombarded by our cannonballs.
| | 00:12 | Let's move the First Person
Controller to the nature side of the doors.
| | 00:16 | I'm going to click the Y axis in the
Scene view and then zoom out. And I can pan
| | 00:27 | pressing my middle-mouse
roller instead of rolling it.
| | 00:30 | Then I'm going to select the First
Person Controller, make sure I'm in Move
| | 00:36 | mode, and I'll go ahead and
grab this gizmo and drag him over.
| | 00:41 | Now I need to pan a little bit more.
And there is the barricade, and I want to
| | 00:47 | move him over to the other side.
| | 00:49 | And it'd be nice if we go ahead and rotate him
| | 00:54 | so he is looking at it.
| | 00:58 | So go ahead and position the First
Person Controller so he is in a handy area.
| | 01:04 | The first thing we ought to do is get rid of
the cannonball sometime after it's been fired.
| | 01:08 | We'll need a script for that of course.
So in the Game Scripts folder--I'm going
| | 01:13 | to highlight that--let's right-click,
Create > JavaScript, and this one we're
| | 01:21 | going to name ProjectileHandler.
| | 01:25 | Before we jump into the Script
Editor though, let's go ahead and turn our
| | 01:28 | Solid Door back on.
| | 01:29 | He is in Barrier 2 and his name is Solid
Door, and you can see he's been grayed out.
| | 01:37 | So we're going to go up to
the Inspector and activate him.
| | 01:41 | Now we're ready to go to the Script Editor.
| | 01:43 | We'll double-click our
ProjectileHandler, and there we go.
| | 01:50 | At it's simplest, we can get away with
adding inside the start function--after we
| | 01:56 | give ourselves a couple of spaces--
Destroy(gameObject, 5). So I'll tab over.
| | 02:04 | Destroy is the function, and the
arguments are gameObject--that's the object
| | 02:16 | that the script is on--and comma 5.
| | 02:19 | 5 is the number of seconds before the
gameObject is destroyed. And of course we
| | 02:26 | need our semicolon to end the line.
| | 02:29 | We'll save the script, head back over
to the editor, and now we need to add the
| | 02:33 | new script to the Cannonball
prefab in the Project view.
| | 02:38 | So let's locate it.
| | 02:39 | There is our Cannonball.
We'll select it and we're going to drag the
| | 02:43 | ProjectHandler script and drop it
directly onto the Cannonball prefab, like so.
| | 02:50 | Now we can click play and test the script.
| | 02:57 | In the Game view, as soon as I fire an
object, the projectile, it goes out and
| | 03:03 | after five seconds it disappears.
| | 03:06 | And if you're not sure it
disappeared, let's do one in the dark.
| | 03:09 | It might show up better.
Okay, no it's not, we'll hit the door.
| | 03:12 | There it goes and it should pop out right
there, so we know it works. Let's exit play.
| | 03:22 | A time destroy is okay for some things,
like rockets that shoot quickly out of range.
| | 03:27 | But for a projectile it will make more sense
for it to disappear after it's hit something.
| | 03:32 | So back in our Script Editor,
let's comment out the Destroy line, two forward
| | 03:39 | slashes, and we're going to add a new function.
| | 03:44 | I'm going to go out for my
Code_Snippets to find it, Ch05/05-06 and my Code_Snippets.
| | 03:53 | So we're going to take the second one
right here, because we already entered the
| | 03:57 | first one, right-click, Copy, tab back
over to our Script Editor. And this one is
| | 04:07 | a function all on its own, so I'm going
to put it beneath the Update function by
| | 04:12 | Ctrl+V, pasting it in.
| | 04:14 | And let's see what we've got here.
| | 04:16 | This one is pretty easy to read.
| | 04:19 | When it first collides with something,
it will get destroyed after one second.
| | 04:23 | Time, by the way, is optional on destroy.
| | 04:27 | Let's save the script now, head back
into our editor, and click so we can test it
| | 04:32 | by shooting at the door.
| | 04:33 | Play, find the door, and shoot. Ooh and
there it goes; it disappears right away almost.
| | 04:44 | So we know that one works.
| | 04:47 | Now we can exit play.
| | 04:50 | At some point you may want different
reactions depending on what was hit.
| | 04:54 | Lucky for us, OnCollisionEnter passes in
the object that it hits, or at least its
| | 04:59 | collider, and it does that in a
variable named Collision, of type collider.
| | 05:04 | Let's go back and look at our Script Editor.
| | 05:05 | There is the variable
Collision and it's of type Collision.
| | 05:11 | Just like the RayCast, if we wanted,
we could get the name of the hit object
| | 05:15 | with something like print
collision.transform.name. And since we will know
| | 05:21 | it's being hit, we might not want to
destroy the cannonball immediately when
| | 05:25 | it, say, hits the ground.
| | 05:27 | So we can add something like if
collision.transform.name and then it will go
| | 05:33 | ahead and carry out the instructions.
| | 05:36 | That's a little bit of code, so I'm
going to tab over to my snippets and
| | 05:41 | grab the next part.
| | 05:42 | We'll go ahead and substitute our
Destroy line with this whole conditional.
| | 05:49 | Select it, right-click, and Copy, go back over to
our Script Editor, and we'll just replace this.
| | 05:57 | Ctrl+V and now we have our new condition.
| | 06:02 | So as long it's not the terrain,
we're going to get the name of it this time and
| | 06:06 | then we're going to destroy it after one second.
| | 06:10 | Let's save our script and head back to
the editor and click play and try it out.
| | 06:17 | This time, if we shoot at the terrain,
it doesn't destroy it, but if we shoot
| | 06:25 | at the door, it does.
| | 06:27 | If we shoot at the wall, it doesn't.
| | 06:33 | So let's exit Play mode
and look at our next issue.
| | 06:36 | Now that it doesn't get destroyed
when it hits the terrain, we're going to
| | 06:39 | have another problem.
| | 06:40 | Letting rigid bodies wander around the
scene will needlessly suck up resources
| | 06:45 | with physics calculations,
| | 06:46 | so we should really turn off the
rigid body after a few seconds.
| | 06:50 | Let's head back to the Script
Editor and figure out how to do that.
| | 06:54 | We're going to adding an else clause to
do it. And once again, I'll pop out to my
| | 07:00 | Snippets file to grab the code. And here
is our else clause waiting for us. Copy
| | 07:06 | it, right-click, and then we'll tab
back over to the Script Editor. And since
| | 07:13 | it's in else clause, it goes
underneath the if and I'll paste it in with
| | 07:18 | Ctrl+V. So this time what's going to
happen is, if it was the terrain, we're
| | 07:24 | going to destroy the rigid body on the
projectile after five seconds, and we'll
| | 07:29 | even have a message there to
tell us when it stopped it.
| | 07:32 | So let's go ahead and save the script.
| | 07:35 | This time though, before we hit play,
we should shoot it up on the sides of
| | 07:38 | the terrain. When it stops rolling we'll
know that the rigid body has been destroyed.
| | 07:45 | We'll click play, find a convenient
piece of terrain to shoot at, and we'll fire
| | 07:54 | a bunch off and see what happens.
| | 07:58 | Watch this guy right here. Oh and he just
stopped. And the next guy, and he stops.
| | 08:04 | So we can see that's working as well.
| | 08:07 | Now we can exit Play mode.
| | 08:08 | So you can see that that's working okay,
but what if we had lots of things we
| | 08:14 | didn't want destroying the cannonball?
| | 08:15 | We certainly wouldn't want to stuff
all the exceptions into the conditional.
| | 08:18 | Well, we're in luck;
another useful Unity feature is the tag.
| | 08:22 | Tags are identifiers that allow us
to test for certain conditions before
| | 08:27 | carrying out instructions.
| | 08:29 | Up at the top of the Inspector, you'll see
the Tag dropdown, with a bunch of pre-made tags.
| | 08:36 | If I click on it, there they are.
| | 08:40 | We want to make a new one so
we're going to click Add Tag.
| | 08:45 | This opens up the TagManager.
| | 08:47 | Tags and layers are all handled in the
same place, so we need to be sure to open
| | 08:52 | up the Tags array at the top.
| | 08:55 | And we'll make a new tag called Don't Destroy.
| | 08:59 | Click on Element 0
that's waiting for us, and Don't Destroy.
| | 09:06 | Now we can head back to the
Script Editor and change our code.
| | 09:09 | Instead of collision.transform.name != "Terrain",
we're going to say
| | 09:16 | collision.transform.tag != and we
keep the quotation marks, Don't Destroy.
| | 09:27 | So we'll save our script.
| | 09:30 | Now if we select our terrain, we can
put a tag on it by clicking our dropdown,
| | 09:37 | and there is the tag we added,
so we're going to check that.
| | 09:43 | And we can even go as far as going to
the Cannonball and adding one to that so
| | 09:50 | that they won't destroy each other, like so.
| | 09:55 | We can click play and test now.
| | 09:57 | As soon as we fire,
they persist unless we hit the gate.
| | 10:11 | So our little projectile has
gotten a lot more sophisticated.
| | 10:16 | In the next video, we'll be
giving it something to destroy.
| | Collapse this transcript |
| Sending messages| 00:00 | The last thing we'll do with the projectile for
a while is to send a message to the hit object.
| | 00:05 | For that, we'll be using
the SendMessage function.
| | 00:09 | It calls a function on another object's script.
| | 00:13 | This will enable us to go about getting
rid of that door in the second barrier,
| | 00:17 | door solid, and we'll be
doing that using SendMessage.
| | 00:22 | Let's go ahead and open our
ProjectHandler script again.
| | 00:26 | We'll need to add one line inside the if
collision section--two if we count the comment.
| | 00:31 | I'm going to go out and get them from
Code_Snippets. From the exercise files
| | 00:36 | folder/Ch05/05-07, I'll open my Code
_Snippets. We want this whole first
| | 00:44 | section here. Right-click and copy
and tab back to the Script Editor.
| | 00:50 | So this one needs to be inside and
right about here, and we no longer need our
| | 00:55 | print line, so I'm just
going to take it out as well.
| | 00:59 | And I'll Ctrl+V to paste my new code into it.
| | 01:03 | We haven't used this for a while,
but it's an ideal time to click the
| | 01:06 | right-click menu and choose
Indent Selection. It keeps it tidier.
| | 01:12 | I'm also going to comment out my other print
statement with the forward slashes as well.
| | 01:18 | So let's see what we've got.
| | 01:20 | BeenHit is the name of the
function we're sending the message to.
| | 01:25 | When we are talking about function names,
we always need to use quotation marks.
| | 01:30 | And it will be sent to any script on the
Hit object that has a BeenHit function.
| | 01:35 | SendMessageOptions.DontRequireReceiver
prevents an error message in case there
| | 01:42 | is no BeenHit function on the script.
| | 01:45 | And just a note here: the BeenHit function,
| | 01:47 | it can have different contents on
each script; only the name is the same.
| | 01:53 | So now we can save the script
and get back into the editor.
| | 01:57 | Now we'll need a new script
to take care of the damage.
| | 02:01 | In our Game Scripts folder, right-click,
create a new JavaScript, and this one we
| | 02:07 | are going to call DoorDamageController.
| | 02:08 | And we'll open him up in the script
editor. And this one is pretty simple.
| | 02:16 | This is where we put our BeenHit function.
| | 02:19 | So it's a function all on its own,
which actually means we could rid of the Start
| | 02:23 | and the Update. And we
are going to have function.
| | 02:27 | Its name is BeenHit, our open and
closing parentheses, our open curly bracket.
| | 02:35 | When it's BeenHit, we just want
it destroyed after one second,
| | 02:40 | Destroy(gameObject, 1) for one second,
semicolon, and let's not forget to
| | 02:51 | close the curly bracket.
| | 02:53 | And we can save this one.
| | 02:55 | Now everything we put this script on,
as long as it doesn't have a don't destroy
| | 03:00 | tag, will get destroyed.
| | 03:02 | So let's get back to the editor and try it.
| | 03:05 | And we'll begin by putting it on the door.
| | 03:08 | The door is in Barrier 2 and its name is
Solid Door, so we are going to drag the
| | 03:14 | DoorDamageController script from the
Project folder over to the Hierarchy and
| | 03:19 | drop it on Solid Door.
| | 03:21 | Let's click play and see what
happens when our cannonball hits the door.
| | 03:26 | Aim at the door, left-mouse click, and voila!
| | 03:31 | That was too easy, wasn't it? Or rather,
it wasn't very entertaining. We'll be
| | 03:35 | fixing that in the next video.
| | Collapse this transcript |
| Reacting to messages| 00:00 | So we need to be a bit
more creative with the door.
| | 00:03 | I've decided our player will need to
shoot the door a few times with the
| | 00:07 | cannonballs to knock it
over so he can get through it.
| | 00:10 | First, we'll need to add a
rigid body to the Solid Door.
| | 00:14 | And we can find that in Structures > Barrier 2.
| | 00:16 | Here is our Solid Door. And we go up to
Component > Physics, and add our Rigidbody.
| | 00:24 | Let's go ahead and just
click play and see what it did.
| | 00:28 | And as soon as we click play,
it drops down through the terrain.
| | 00:32 | We'll exit our Play mode for a minute.
| | 00:35 | There's something important you
need to know about real-time physics.
| | 00:38 | When checking for intersections or
collisions, only one object can have a
| | 00:44 | mesh type collider.
| | 00:45 | We'll look deeper into colliders in the
next chapter, but what it boils down to
| | 00:50 | is that the terrain must use a
MeshCollider or the First Person Controller
| | 00:55 | wouldn't be able to go up and down it.
| | 00:58 | And imported meshes like the door are
also assigned mesh colliders, or at least
| | 01:04 | the option is there.
| | 01:06 | In the case of the door, it's an easy fix.
| | 01:09 | From Component > Physics,
we'll just choose Box Collider.
| | 01:15 | And since we already had a MeshCollider,
we'll get a dialog that asks us what we
| | 01:19 | want to do about it.
| | 01:21 | We'll choose Replace.
| | 01:22 | Now if we click play,
the door settles right into place.
| | 01:26 | I'm going to exit Play mode
and turn off Maximize on Play.
| | 01:32 | So let's see about knocking it over.
| | 01:35 | Let's open the DamageController script in
the script editor and see what we need to do.
| | 01:40 | To start, let's comment out the Destroy
line with our forward slashes, and then
| | 01:46 | let's see what happens.
| | 01:47 | I'm going to save the script, so
now we should be able to hit it with a
| | 01:51 | projectile and it won't be destroyed.
| | 01:53 | Back in the editor, if I click play
and shoot the door, we can see it wiggle,
| | 02:03 | but it's not going anywhere.
| | 02:04 | While still in Play mode,
let's select the Solid Door and in the Inspector,
| | 02:11 | let's decrease the Mass in
the Rigidbody component to .1.
| | 02:14 | Now we'll go back and try and shoot it again.
| | 02:17 | Well, it's wiggling more, and it's trying
to open, but something is holding it in.
| | 02:24 | Let's exit Play mode.
| | 02:28 | Apparently, it has being held
up by the doorjamb in the wall.
| | 02:31 | Remember that ignore physics line we
added to the projectile so it wouldn't get
| | 02:36 | stuck in the Proxy Weapon?
| | 02:37 | It looks like we need its
help to knock over the door.
| | 02:41 | So let's head back to the Script
Editor and add a couple of variables in the
| | 02:46 | DoorDamageController script. And our
two offending objects are--and we'll name
| | 02:52 | our variables for them--var doorJamb is
of type. Collider is all we really need
| | 02:59 | for this one and a semicolon and var wall.
| | 03:06 | It's also of type Collider.
| | 03:09 | For the rest of the code, I'm going
to go out to my Snippets file again.
| | 03:13 | From the exercise files folder >
Ch05/05-08/05-08Code_Snippets,
| | 03:21 | there's our variables we've already added.
| | 03:23 | And now we are going to take all of this,
highlight it, right-click, and Copy, and
| | 03:30 | then we'll tab over to our Script Editor again.
| | 03:32 | So that's what we need in our BeenHit function.
| | 03:37 | And I'm going to delete the original
line and use Ctrl+V to paste this in.
| | 03:44 | And we'll go ahead and save our script.
| | 03:46 | So now when the door gets hit, its
physics are going to ignore collisions with
| | 03:51 | both the doorjamb and the wall.
| | 03:54 | Let's head back over to the editor.
| | 03:56 | Click play and see what happens.
| | 04:00 | I'm firing on the door, but it's not going down.
| | 04:03 | Let's exit Play mode, and this time
I'll drag BarrierJamb002 into Door Jamb and
| | 04:12 | the Barricade Mid into the field for the wall.
| | 04:16 | Now when we click play,
we should see some results.
| | 04:21 | And there we go: our door is down.
| | 04:24 | Let's exit Play mode.
| | 04:26 | If you wanted to get really fancy, you could
make a damage variable for when the door is hit.
| | 04:31 | At reaching the specified amount,
you could reduce the mass or any number of
| | 04:35 | things to finish it off.
| | 04:37 | With the door, you could even destroy it
and instantiate a dead replacement for it.
| | 04:42 | A mangled lump of metal would be nice.
| | 04:45 | We've got lots more goodies to look
into though, so let's move on to the
| | 04:49 | next video.
| | Collapse this transcript |
| Juggling Play and Edit modes| 00:00 | For the rest of this chapter we'll add
a few niceties that will make authoring
| | 00:04 | easier when use in shooter controls.
| | 00:06 | We'll start by turning the operating
system cursor off during play mode and
| | 00:11 | bringing it back when we need to edit stuff.
| | 00:14 | With the mouse move being used to look
around, the first thing we need to do is
| | 00:18 | turn off the cursor on startup.
| | 00:21 | Since the cursor is not directly related
to any particular object, we'll make an
| | 00:25 | empty game object to manage it
and other generic functionality.
| | 00:29 | Let's name it Game Manager.
| | 00:30 | I am going up to GameObject, and I want to
Create Empty, and I'll name him Game Manager.
| | 00:37 | It will be a master-control
command-center sort of object.
| | 00:42 | And then we'll need to make
a script to do all the work.
| | 00:46 | So in the Game Scripts folder,
let's right-click, Create > Javascript.
| | 00:53 | This one we are going to name
GameManager, only without the space,
| | 00:57 | and Enter and then we'll go ahead and open it.
| | 01:01 | In the Start function we are going to add first,
| | 01:05 | I'll make the comment and this is to
remind us that it's going to Hide Cursor.
| | 01:12 | And then we'll actually
write the code that does it.
| | 01:14 | This one comes from
Screen.showCursor, and we want to make it equal false.
| | 01:23 | And of course we close it with a semicolon.
| | 01:27 | So save the script, get back to the
editor, and now we need to drag our new
| | 01:32 | script onto the new Game Manager object.
| | 01:37 | Now we can click play and see
what's happened to our cursor.
| | 01:41 | If you are in 2x3 mode, you may find that
it's kind of there and it's kind of flickering.
| | 01:48 | I am going to exit play mode, but if you
are in wide or you are using Maximum on
| | 01:54 | Play, then when we click play,
we'll see that indeed the cursor is gone.
| | 02:00 | So I am going to go back
up and get out of play mode.
| | 02:05 | Now we are going to see about
toggling it off and on with a key press.
| | 02:09 | That way we can easily switch
back and forth whenever we want.
| | 02:14 | A key press means we'll need
to check the input every frame.
| | 02:18 | So let's head back to the Script
Editor. And this is a few more lines, so I am
| | 02:23 | going to go out and grab the
code from the snippets file.
| | 02:27 | exercise files/Ch05/05-09,
and we'll open up the snippets.
| | 02:34 | This is the one we want right here.
| | 02:37 | We'll right-click to copy, tab back over
to the Script Editor, and we need to add
| | 02:43 | that one inside the Update function.
| | 02:45 | So I'll give myself a little bit
of space and Ctrl+V to paste it in.
| | 02:51 | In this conditional, we are checking
to see if the Escape key was pressed.
| | 02:55 | Let's save the code and go back to the Editor.
| | 02:59 | When we click play, now I am
hitting Escape, but nothing is happening.
| | 03:06 | Let's get out of Play mode
and see if we can track it down.
| | 03:10 | We expected it to print "Escape was
pressed in the Console," but all we are
| | 03:14 | getting is a bunch of numbers.
| | 03:16 | I think I need to open the Console
and see where they are coming from.
| | 03:20 | So I am clicking it. And remember, if you
double-click on a line, it will take you
| | 03:26 | to the script in the line in the code.
| | 03:28 | And sure enough in the RayCaster
script we see print (Time.time), and we
| | 03:34 | definitely don't want to see that anymore.
| | 03:37 | So I am going to comment it out with my
forward slashes. And remember to click Save.
| | 03:44 | Now we should be able to go back to our
editor, clear the Console, and see if we
| | 03:50 | can click Escape and get
our message printed out.
| | 03:54 | Play mode, click Escape, and there it is
down in the status line: Escape was pressed.
| | 04:00 | So now we can exit Play mode and go ahead
and put our real code into the proper script.
| | 04:07 | Back in the Script Editor, we are
going to switch back over to GameManager.
| | 04:13 | And this is quite a bit of script
here, so I am going to head out to the
| | 04:16 | snippets file again.
| | 04:18 | This time we are going to replace
our print line with the condition.
| | 04:24 | This will toggle the operating system
cursor off and on when we press Escape.
| | 04:30 | Copy, back over to the Script Editor,
and in the GameManager, I am going to
| | 04:35 | replace my print statement with the
contents of the snippets file, using
| | 04:41 | Ctrl+V. If you remember, when we click next to a
curly bracket, we should find its matching one.
| | 04:50 | So it looks like I have got one to many.
| | 04:53 | So I'll delete that curly
bracket and I'll double-check the rest.
| | 04:58 | That one matches to there, this one
matches to here. It should be good to go.
| | 05:05 | Save, tab back over to
the editor, and click play.
| | 05:09 | As you can see, with a great
relief, the status line is empty.
| | 05:15 | So now in my scene if I click my Escape
key, I can toggle my cursor off and on.
| | 05:22 | Let's go ahead and exit Play mode.
| | 05:23 | Now that the cursor is under control,
let's add a radical, or crosshairs, to the game.
| | 05:29 | We'll be controlling it in the same place
as the cursor, so we may as well add it now.
| | 05:35 | Let's start by importing the
crosshairs.target texture from this video's Assets
| | 05:40 | folder and we can do
that using Import New Asset.
| | 05:45 | It's in the same menu as the
Import Package tool we've already used.
| | 05:49 | Since we've only got one object,
we can use Import New Asset instead.
| | 05:55 | Now I need to navigate to my Exercise Folders/
Ch05/05-09/Assets, and here's my image.
| | 06:06 | And all we need to do is click Import.
| | 06:09 | It came in the Game Scripts
folder because I had it highlighted.
| | 06:13 | I'll just go ahead and drag it out and
drop it into the Textures folder instead.
| | 06:18 | So it's not very exciting now,
but as soon as we bring it into the scene,
| | 06:23 | you'll see the difference.
It does have an alpha channel.
| | 06:27 | Since this guy has an alpha channel
and it is image, we're going to need an
| | 06:31 | object to put him on in the game.
| | 06:33 | This time we can use the texture version of
the GUI text object: the GUI Texture object.
| | 06:40 | But instead of making it first and then
assigning the texture, we are going to
| | 06:44 | select the texture first over in the
Project view. Then we are going to go up to
| | 06:50 | GameObject > Create Other > GUI Texture.
| | 06:55 | That way it automatically creates the
GUI Texture object, names it, and puts it
| | 07:02 | at 00 in our screen space.
| | 07:05 | You may need to adjust the height of the
crosshair or you could adjust the speed
| | 07:09 | of the projectile or even
the angle of the Proxy Weapon.
| | 07:14 | As with all GUI objects, in the
Scene view, you can toggle it off and on
| | 07:18 | with the Overlay button.
| | 07:21 | To position it in the Inspector,
you can ingest its X or Y screen position.
| | 07:27 | So now we're ready to finish the
escape functionality. We'll do that in the
| | 07:31 | next video.
| | Collapse this transcript |
| Suppressing input| 00:00 | The final touch for the escape
functionality is to stop the player from moving
| | 00:04 | around the scene with the keyboard
and mouse controls, because it's really
| | 00:08 | annoying to have the view spin when we
are trying to move the cursor out of the
| | 00:12 | Game view when we're still in play mode.
| | 00:14 | We are handling the cursor
functionality from the GameManager script, but the
| | 00:18 | input needs to be suppressed
in the FPSInput Controller.
| | 00:23 | It's the one using the virtual input keys.
| | 00:27 | So let's select the First Person
Controller and in the Inspector, we need to
| | 00:32 | locate the FPSInput
Controller script and open it up.
| | 00:40 | We'll start by testing a very powerful
little function at the top of the Update function.
| | 00:46 | So I am going to go up to the curly
bracket, the opening curly bracket, press
| | 00:51 | Enter a couple of times, and then tab
over. And here is what we are going to
| | 00:57 | add: Input.ResetInputAxes, and an open and
closing parentheses and a semicolon to close the line.
| | 01:14 | And because this is code that I added,
I'm going to use my forward slashes
| | 01:19 | to make the comment and I'm going to use a
bunch of asterisks so I can find it quickly.
| | 01:27 | Let's save our script and get
back to the game editor and test.
| | 01:33 | I'm going to turn off Maximize on Play,
then I'll click play, and now, in the Game
| | 01:41 | window, I'm going to use my arrow keys--
W, A, S, D--and mouse move, and you can see we've
| | 01:51 | suppressed all of the player input,
which is exactly what we want to do.
| | 01:56 | So, let's exit Play mode.
| | 01:57 | The First Person
Controller controls no longer work.
| | 02:02 | This is sort of like
overriding a laser beam with a mirror;
| | 02:06 | it never allows the input to be evaluated.
| | 02:09 | So now we are going to need a flag in
that script to tell it when to suppress
| | 02:14 | the navigation, and then we'll need to
send a message to set the flag true or
| | 02:18 | false from the GameManager script,
because that's what we'll be using the Escape
| | 02:23 | key to toggle it off and on with.
| | 02:25 | So let's open the Script Editor again
and in the FPSInput Control script, we
| | 02:32 | need to add a variable up at the top.
And we can add it beneath the private
| | 02:36 | variable. And this one is going to be
internal var, and we'll name it noInput, and
| | 02:43 | it is of type boolean.
| | 02:48 | And now, we're also going to need a
function to receive the message to toggle
| | 02:53 | that variable, noInput, to true or false.
| | 02:57 | This one is really simple.
| | 02:58 | So down at the very bottom of the
script--not the very bottom; we're going to
| | 03:03 | keep it up above the last three
lines--and we're going to add function
| | 03:11 | ToggleInput, and we're
going to pass it an argument.
| | 03:24 | That variable's name will be state
and it is of type boolean. Open
| | 03:32 | curly bracket, close curly bracket,
and then I'll move up inside, tab over,
| | 03:43 | an add noInput = state;.
| | 03:56 | So we'll be passing at the
state we want it to be directly.
| | 04:00 | Let's go ahead and save and toggle back
into the editor. And finally, we need to
| | 04:07 | open the GameManager script, and we'll
need to add the variable that will give us
| | 04:13 | access to the First Person Controller.
| | 04:16 | So up at the top, we're going to make
a var and we'll call this one fpc for
| | 04:22 | First Person Controller. You'll see
that used quite a bit, and this guy is
| | 04:27 | of type GameObject.
| | 04:32 | And now we can add the
SendMessage code inside the ifs.
| | 04:37 | So let's think about it for a minute.
| | 04:39 | I'm going to clean these up by backspacing.
| | 04:43 | So if we've hit Escape and if the screen
cursor is false--in other words it's not showing--
| | 04:51 | that means we want the cursor to show
again, and it also means we want to send
| | 04:56 | the message to the First Person
Controller to block user input.
| | 05:03 | So this is going to look like
fpc.SendMessage, and we are sending the message to
| | 05:16 | the function we just made called
ToggleInput. And that needs quotation marks.
| | 05:28 | And because we're sending it an
argument, we need a comma, and we want to say
| | 05:34 | true. In other words true, we want no
input. And we can close the parentheses
| | 05:44 | and add the semicolon.
| | 05:46 | In the else, we need just the opposite.
| | 05:48 | So I am going to go ahead and copy this
line--right-click > Copy--and I'll add
| | 05:58 | it under this one. Paste and of
course I need to change my true to false.
| | 06:07 | We've seen message before, but this
time we are also sending an argument to the
| | 06:10 | function we are calling, in
this case a true or false.
| | 06:13 | We are limited to only one argument
though, and the function must always
| | 06:18 | have matching arguments.
| | 06:20 | You can't just send one when it's expecting two.
| | 06:23 | I didn't add the DontRequireReceiver,
because it should always find one since
| | 06:27 | it's on the First Person Controller,
but it wouldn't hurt to have it.
| | 06:31 | Anyway, let's save the
script and get back to our editor.
| | 06:36 | Before we test it, we need to remember
to select the Game Manager and drag the
| | 06:41 | First Person Controller into the Fpc field.
| | 06:46 | Now we can click and play, but I
still can't move around in my Game view.
| | 06:52 | It turns out there is one
more thing I need to do.
| | 06:56 | So, let's exit play, select the First
Person Controller, and open that First
| | 07:04 | Person Input Controller script
again. And this time I need to put the
| | 07:11 | condition in front of my Input.
ResetInputAxes, and that is if (noInput).
| | 07:27 | And that's all it needs.
| | 07:29 | I save the script, toggle back to the
game editor, and now when we click play, we
| | 07:37 | once again have our First Person
Controller controls, but if I click my Escape
| | 07:43 | button, the viewport is frozen, my
operating system cursor returns, and now I can
| | 07:51 | go out and edit in any of the other views.
| | 07:55 | Let's stop Play mode, and there we go.
| | 07:58 | I don't know about you,
but that was well worth the scripting.
| | Collapse this transcript |
|
|
6. Working with GameObjects and ComponentsCreating GameObjects| 00:00 | In this chapter we will be working
with GameObjects and their components.
| | 00:04 | GameObject is Unity's name for, well, an object.
| | 00:08 | If you have a background in 3D content
creation, you may already have a feel
| | 00:12 | for what an object is.
| | 00:14 | An object has a set of
properties that define or describe it.
| | 00:17 | Spheres, cubes, terrains, lights, and
cameras are a few kinds of objects, each
| | 00:23 | with its own unique properties.
| | 00:24 | So what do all of these objects have in common?
| | 00:27 | The most important answer is,
a location and orientation in space,
| | 00:32 | in other words, a transform or pivot point.
| | 00:35 | This concept forms the
basis of the Unity game object.
| | 00:39 | There are a few other properties,
but this one is the most important.
| | 00:43 | From a programmer's
standpoint it's more than a concept.
| | 00:46 | The GameObject is the base class
for all entities in Unity scenes,
| | 00:51 | so all other objects in the scene
inherit and are members of that class.
| | 00:56 | If you do a search for "GameObject" in
the scripting reference, you can see the
| | 01:00 | variables and functions associated with it.
| | 01:03 | Let's go to Help > Scripting Reference
and type in the search area, GameObject.
| | 01:12 | The first one, GameObject, is the one we want.
| | 01:16 | We can see the variables and
functions associated with it.
| | 01:21 | You can have camera, light, animation,
audio, collider, and there's all sorts of
| | 01:28 | things we can do with it.
| | 01:30 | Let's close this and get back to the editor.
| | 01:33 | The term GameObject should be
pretty familiar by now anyway.
| | 01:36 | We've been creating simple primitive
objects from the GameObject menu, and we've
| | 01:40 | been using GameObjects in some
of our scripts. Let's take a look.
| | 01:44 | From the GameObject menu, there are two choices:
| | 01:48 | Create Empty and Create Other.
| | 01:51 | Under Create Other,
the choices are pretty self-explanatory.
| | 01:56 | Most of you have probably already
deleted and added several types of GameObjects
| | 02:00 | besides the ones we used in the previous videos.
| | 02:03 | Let's take a closer look at
the other option, Create Empty.
| | 02:06 | While it seems kind of silly at first
glance, as soon as you start to think of
| | 02:11 | it as a container,
the possibilities become apparent.
| | 02:14 | It gives you a means to organize
scene assets into tidy groups, control
| | 02:19 | complicated hierarchies, construct custom
objects, and manage object states at the top level.
| | 02:26 | Take a door. Making it slide from
side to side is a simple transform,
| | 02:31 | but to make it a conventional swinging
door, we would need to get it rotating
| | 02:35 | from the end instead of the middle.
| | 02:37 | Not only will an empty GameObject
make that possible, it will also give us a
| | 02:42 | few side benefits as well.
| | 02:44 | Let's give that a try.
| | 02:47 | In the MainLevel, let's focus in on
the First Person Controller to give us a
| | 02:52 | good place to start.
| | 02:54 | Using my Alt key, I'm going to adjust
my view a little bit. Then let's select
| | 03:01 | GameObject > Create Other > Cube.
| | 03:06 | We can move it aside and use Scale to
squash it and expand it until it looks
| | 03:16 | sort of like a door.
| | 03:17 | Now we'll focus the Scene window on it.
| | 03:21 | And from the top view we are now going
to add an empty GameObject, Create Empty.
| | 03:29 | And this one we can move over
to where the door should pivot.
| | 03:36 | When we drag our original cube into
the empty GameObject and switch the pivot
| | 03:42 | from center to Pivot, we now have
a way to rotate our door properly.
| | 03:50 | As an added benefit, we could go ahead
and create another object, a sphere, scale
| | 03:57 | it down to about the size of a doorknob,
put it into position. We don't need two.
| | 04:08 | But when we drag this into that same
GameObject's group and select it again and
| | 04:15 | click the Rotate tool,
everything rotates together.
| | 04:20 | This is a really important concept.
| | 04:22 | Children inherit the Rotation,
Transform, and Scale of their parent.
| | 04:29 | To see this better, let's select the Cube.
To get a better idea what's happening
| | 04:34 | here if we select the Cube and in the
Inspector make note of one of its position
| | 04:41 | values, then move the parent,
| | 04:50 | if we now go back and look at the
Cube, you can see that that value hasn't
| | 04:55 | changed, so its position is relative
to its parent. And this is going to be
| | 05:00 | an important concept when we get
into animated objects, and especially
| | 05:05 | imported animated objects.
| | 05:07 | Let's test another of the
GameObject's properties.
| | 05:10 | With our parent GameObject here, in the
Inspector, if we deactivate it, we get a
| | 05:17 | dialog asking if we wish to
deactivate all the child objects as well.
| | 05:22 | We can choose to or not, and when we
activate, we get the same dialog. And we'll
| | 05:28 | choose Activate Children.
| | 05:30 | When you're scripting though, all you
have to do is deactivate the parent and
| | 05:37 | all of the children
automatically will be deactivated.
| | 05:41 | Another cool thing about GameObjects is
that they can be dynamically parented to
| | 05:45 | different GameObjects at
runtime through scripting.
| | 05:48 | A ride on an elevator for instance with
the First Person Controller will appear
| | 05:53 | kind of jittery, but if we parented the
First Person Controller to the elevator
| | 05:58 | during the ride, it will be a smooth
trip and the First Person Controller will
| | 06:03 | still be able to move around.
| | 06:05 | In the next video, we'll see how
components can be added to turn GameObjects into
| | 06:10 | specialized objects.
| | Collapse this transcript |
| Understanding components| 00:00 | In the previous video, we saw that
an empty GameObject could be used as a
| | 00:04 | container to hold other
GameObjects in a parent-child relationship.
| | 00:09 | In this video, you will see what happens
when we add components to the GameObject.
| | 00:14 | In programming terms, a component is
the base class for everything that can be
| | 00:18 | attached to GameObjects.
| | 00:21 | Let's take a look at few of our
GameObjects to see what kind of components
| | 00:24 | they already contain.
| | 00:26 | Let's select the door object
we created in the last video.
| | 00:30 | It's under GameObject and it's called Cube.
| | 00:33 | We didn't bother naming it door.
| | 00:35 | In the Inspector, besides the features
already present in the GameObject, such
| | 00:40 | as transforms, we can see
that it has three components:
| | 00:44 | a Cube (Mesh Filter), a Box
Collider, and a Mesh Renderer.
| | 00:51 | The Cube component
contains only mesh information.
| | 00:55 | The Box Collider component, however, is
one of the most important in the scene, as
| | 01:00 | it prevents the player from going
through an object or allows a player to go
| | 01:04 | through but flags the intersection.
| | 01:06 | And that's in case some
event needs to be triggered.
| | 01:09 | It's also necessary for
triggering an OnMouseDown event.
| | 01:13 | Try adjusting the size of the Box Collider.
| | 01:16 | You can now see that the green
bounding box represents the collider.
| | 01:21 | So I'll just try changing his X and
in the scene view, we can see it getting
| | 01:26 | larger and smaller, and its Z, like so.
| | 01:33 | The third component is the Mesh Renderer.
| | 01:35 | It is responsible for
rendering the mesh in the scene.
| | 01:38 | It also tells Unity which material
or materials are used on the mesh.
| | 01:44 | Try disabling the Mesh Renderer.
| | 01:48 | The cube disappears in the Scene view,
but the Box Collider is still active.
| | 01:53 | As you might guess, the player
would still be blocked even though he
| | 01:57 | couldn't see the cube.
| | 01:58 | Now let's deactivate the Box Collider by
clicking the box right next to its name.
| | 02:05 | The bounding box still shows, but it's a
dimmer version of the active green color.
| | 02:10 | At this point, the object would no
longer be detectable by the player, but
| | 02:14 | since it is still active at the GameObject level,
the game engine still has full access to it.
| | 02:21 | And here is something else to remember:
| | 02:23 | GameObjects are active when we check or
uncheck, but components are enabled or disabled.
| | 02:33 | These aren't just terms;
| | 02:35 | these are parameters to be used in scripting.
| | 02:38 | Let's look at a few more objects.
| | 02:40 | From GameObjects > Create Other,
let's create a point light.
| | 02:44 | As you can see, it has a single light
component, but that component has several
| | 02:50 | parameters such as Type,
Color, Range, and Intensity.
| | 02:54 | Now let's create a spotlight in the scene.
| | 02:57 | GameObject > Create Other > Spotlight.
| | 03:02 | As you can see, it has the same
light component, but its Type parameter is
| | 03:08 | Spot rather than Point.
| | 03:11 | Besides the components that make up
the predefined objects in the GameObject
| | 03:15 | menu, there are many more
components that can be added to enhance an
| | 03:19 | object's functionality.
| | 03:20 | Open the Components menu and
take a look at what's available.
| | 03:25 | If the submenus are grayed out,
you'll need to select an object first.
| | 03:29 | Note that scripts are also components.
| | 03:32 | Anything that contributes to the
creation and functionality of a GameObject can
| | 03:37 | be found under Components.
| | 03:39 | Just for fun, choose any
component to add to your object.
| | 03:45 | I added a skinned cloth and
that was probably a mistake.
| | 03:49 | If I scroll down in the Inspector,
I discover not only did it add a Skinned
| | 03:54 | Cloth component, but it added a
Skinned Mesh Renderer as well.
| | 03:58 | I need to remove both of them.
| | 04:00 | You can remove a component by right-
clicking over its name and saying Remove
| | 04:05 | Component. And then I'll go
ahead and remove this one as well.
| | 04:11 | Now let's select the Spotlight
and remove its Light component.
| | 04:16 | Right-click over the label and Remove Component.
| | 04:19 | It leaves you with--wait
for it--an empty GameObject.
| | 04:25 | So all of those Create Other
objects are just GameObjects with
| | 04:30 | components already added.
| | 04:33 | In the rest of this chapter, we will
be examining several of the important
| | 04:36 | components in depth so we can add to the
functionality and interactivity of our little game.
| | 04:42 | Go ahead and delete the door
group and extra lights from the scene.
| | 04:45 | I'll do that by selecting the Spotlight,
right-clicking, and clicking Delete.
| | 04:51 | I can also click on the parent
object and press Delete on my keyboard.
| | 04:57 | And one more to get rid of: Point
Light. Right-click, Delete as well.
| | Collapse this transcript |
| Using colliders for barriers| 00:00 | By now you've had a few
run-ins with colliders--literally.
| | 00:03 | Colliders are the components
of mesh objects that prevent you from
| | 00:07 | going through things, but they
have other functions as well.
| | 00:10 | Let's start by looking at the
different kinds of colliders available.
| | 00:14 | From the Component menu > Physics,
we've got Box, Sphere, Capsule, Mesh,
| | 00:21 | Wheel, and Terrain.
| | 00:23 | Wheel and Terrain are specialty
colliders that we won't be covering.
| | 00:28 | The Mesh collider uses the object's own
mesh to check for collision, and is the
| | 00:33 | highest resource user of the regular colliders.
| | 00:36 | When we import objects and check
generate colliders, that's what gets created.
| | 00:42 | Let's select and focus
on the Entry Stair object.
| | 00:47 | It's in the Structures for Scene group,
under Building Group > Entry Stair.
| | 00:55 | Double-click it and then you can use your
Alt and left mouse to get a better view of it.
| | 01:01 | I'll just zoom in a little bit with
my middle-mouse roller and adjust it.
| | 01:08 | The Entry Stair object has a Mesh Collider.
| | 01:11 | Mesh Collider calculates
collision off of every face.
| | 01:15 | The Mesh Collider does have an option
to recalculate the Mesh Collider to be
| | 01:19 | convex, which is much more economical.
| | 01:22 | That is, when it can come up with a
good solution, and sometimes it can't.
| | 01:26 | Let's try that out with the stair.
| | 01:28 | Here's our Convex option, and let's click it.
| | 01:32 | In this case, it worked quite well.
| | 01:35 | Let's set it back to normal.
| | 01:37 | The Mesh Collider also has a polygon
limit, so don't be surprised if an imported
| | 01:42 | mesh's collider fails.
| | 01:44 | Remember also that only one object in an
intersection or collision test can be a mesh collider.
| | 01:50 | The exception is if at
least one is marked as Convex.
| | 01:55 | So what do you do with the
mesh that's too complicated?
| | 01:58 | The answer is multiple colliders.
| | 02:00 | You can have one of each kind of
collider on an object, but they can be
| | 02:04 | tricky to position.
| | 02:06 | A better solution is to add empty
GameObjects to the main object and
| | 02:10 | put colliders on those.
| | 02:12 | They can be transformed into position
using the GameObject, but you will need to
| | 02:16 | use their own scale transforms to adjust them.
| | 02:20 | Let's import the Fountains package
from the Assets menu > Import Package >
| | 02:27 | Custom Package, and we'll find that in the
exercise files for this video: Ch06/06-03/Assets.
| | 02:40 | And there it is, the Fountain package, and Open.
| | 02:46 | Import. And if we check our Project view,
under Imported Assets, we'll see our new prefab.
| | 02:58 | In the Scene view, let's toggle to the
top view, clicking on the Y component
| | 03:05 | of the scene gizmo. and zoom out, and then we'll
move our view to the center of the nature area.
| | 03:17 | Now we can drag our Fountain
prefab into the very center spot.
| | 03:25 | Let's get a closer look at our fountain
by double-clicking to focus on it.
| | 03:29 | And then holding the Alt key, we can
rotate the view and zoom in with the middle-
| | 03:36 | mouse button until we see what we've got.
| | 03:41 | If we look at the various components
of the fountain, besides the Bobbles,
| | 03:47 | Brace, none of these objects have colliders yet.
| | 03:52 | For the Fountain Base, because we want
our first person controller to be able to
| | 03:56 | navigate it, we need to add from
Component > Physics > a Mesh Collider.
| | 04:04 | For the Frufra piece, we're going to add
a Box Collider, and we'll need to adjust
| | 04:12 | its Size in the Inspector by
adjusting its X, Y, and Z parameters.
| | 04:18 | This effectively is going to block
the first person controller from going
| | 04:21 | through it without the high
overhead of a Mesh Collider.
| | 04:25 | We've already seen the
Capsule Collider in action.
| | 04:28 | The first person controller's Capsule
Collider is built into its character
| | 04:32 | controller script, but it allows
for very economical collision testing.
| | 04:37 | Capsule Colliders are also the only
controller types allowed on trees for the
| | 04:41 | Terrain Editor library.
| | 04:43 | Remember that big tree that
we used in the central area?
| | 04:47 | Right now we can drive right through it.
| | 04:49 | Let's select the BigTree in the
Project view and check it out.
| | 04:53 | He is up at the top here. And if we
close his Tree component, we can see that
| | 05:00 | he has no collider.
| | 05:02 | Let's focus in on him, use Alt to swing the
view around, and then zoom in. There we go!
| | 05:15 | Now we can see him. And we'll go ahead
and add a Capsule Collider to the tree
| | 05:21 | from Component > Physics > Capsule Collider.
| | 05:27 | Now the problem is that it's scaled
pretty much to the size of the tree.
| | 05:32 | So the first thing we need to do is
change its Radius, and I'm going to use that
| | 05:38 | by clicking and dragging next to the field.
And you can see it's a little bit off center here,
| | 05:44 | so we're also going to need to adjust
the center to bring it into position on
| | 05:51 | the X and the Z. I'm going to leave it as is.
| | 05:59 | It would be easier to do from a top view.
| | 06:02 | Once we've got it how we like it, then we'll
need to update the prefab in the Project view.
| | 06:10 | We could do that by dragging the
original BigTree onto the prefab, or in the
| | 06:17 | Inspector, we can click Apply, and
that will update the prefab for us.
| | 06:24 | When we've used it in the Terrain Editor,
we also need to remember to go to the
| | 06:28 | Terrain menu > Refresh
Tree and Detail Prototypes.
| | 06:35 | If we were to click lay and test, not
only would we find out we couldn't go
| | 06:40 | through the trees, but we'd also find out
that our cannonballs bounced off them as well.
| | 06:45 | And finally, one of the more interesting
and sometimes useful things is that the
| | 06:50 | Mesh Collider on a plain object is single-sided.
| | 06:54 | If you were to rotate it vertically,
you would be able to find that you could go
| | 06:59 | through it on the back
side but not the front side.
| | 07:02 | And that could make for some interesting traps.
| | 07:05 | Anyway, bottom line on colliders is,
use the simplest colliders for the best
| | 07:10 | efficiency, and use all colliders sparingly.
| | 07:15 |
| | Collapse this transcript |
| Using colliders for triggers| 00:01 | The next bit of collider goodness we'll
look into is the Is Trigger parameter.
| | 00:05 | It turns out you need a collider to be
able to detect a collision of any kind,
| | 00:10 | and that includes ray casting, by the
way. Plus, one of the colliding objects
| | 00:15 | must have a rigid body.
| | 00:16 | Character controllers have a special
kind of rigid body, so we are good to go.
| | 00:20 | So how do you allow the player to go through
something while still triggering an intersection?
| | 00:25 | The answer is the Is Trigger parameter.
| | 00:28 | When checked, it allows objects to go
through it, but it can still be detected.
| | 00:34 | To see how this works, let's select
the Barricade Mid. In the Structures for
| | 00:38 | Scenes > Barrier 2, we'll
select the Barricade Mid.
| | 00:44 | In the Inspector, in the Mesh
Collider, we are going to check Is Trigger.
| | 00:52 | Now we can click play and see
about driving through the barricade.
| | 00:56 | With my W key, I head over and
sure enough, I can get through it.
| | 01:03 | I'm going to hit my Escape key to disable
navigation, so I can get out of Play mode.
| | 01:08 | Now we'll need to create a
new script to trigger something.
| | 01:12 | So in the Practice Scripts folder--and
I'm going to close my Standard Assets
| | 01:17 | folder while I'm there--right-click on
the Practice Scripts folder, Create >
| | 01:23 | Javascript, and we'll name
our new script TriggerTest.
| | 01:28 | And we'll go ahead and
open it in the Script Editor.
| | 01:33 | Because we are going through the
object now, we need to use OnTriggerEnter
| | 01:39 | instead of OnCollisionEnter,
but it works pretty much the same way.
| | 01:43 | I am going to grab the code from
the snippets file for this one.
| | 01:46 | And we want this for a section,
the OnTriggerEnter function. Ctrl+C to copy.
| | 01:55 | I'll tab back to my Script Editor,
and it looks like I need to make sure I'm in
| | 02:01 | the TriggerTest. And then I'll add my
new script after the Update function, and
| | 02:08 | use Ctrl+V to paste.
| | 02:11 | Okay, let's save this guy, get back
into the editor, and now we need to drag our
| | 02:19 | TriggerTest script onto Barricade Mid.
| | 02:24 | Before we click play,
there's something else we should think about. Our Solid
| | 02:29 | Door already has a rigid body on it,
and it's probably intersecting with the wall,
| | 02:36 | so don't be surprised to see our
first message detect the Solid Door.
| | 02:42 | Now we'll go ahead and click play.
| | 02:45 | And sure enough, our script has detected
the Solid Door. And I'm going to go ahead
| | 02:50 | and hit W and go through the wall.
| | 02:53 | And now you see it senses the
presence of First Person Controller.
| | 02:57 | So everything works. Let's click
Escape and get out of Play mode.
| | 03:01 | Let's go back into the Script
Editor again and this time we'll add
| | 03:05 | OnTriggerEnter's counter part, OnTriggerExit.
| | 03:08 | We can do that easily by copying the
OnTriggerEnter function with Ctrl+C and
| | 03:16 | pasting it right below.
| | 03:18 | And we need to change Enter to Exit,
and we can add something else for our
| | 03:25 | message, like "I sense an emptiness," and don't
forget quotation marks, and then we'll save.
| | 03:35 | Now back in the editor, when we click
play, as soon as we exit the wall, we'll
| | 03:43 | get the last message.
| | 03:45 | So W, First Person Controller, and
as I leave, I sense an emptiness.
| | 03:52 | Escape and we'll quit Play
mode and there we have it.
| | 03:56 | So this gives us a non-directional
means of triggering events such as doors,
| | 04:02 | power-ups, disembodied voices,
just about anything you can think of.
| | 04:07 | At its simplest, a collider can be the
only thing on a GameObject, but if we
| | 04:12 | wanted to do something more interesting,
at its simplest, a collider can be the
| | 04:17 | only thing on a GameObject.
| | 04:19 | If we wanted to open and shut doors
in the first barricade like a Star Trek
| | 04:23 | door, we could use an empty game
object with just a large box collider.
| | Collapse this transcript |
| Exploring physics| 00:00 | We've seen the class of Box Test with
physics and used physics to fire our
| | 00:05 | cannonball and drop the solid door, but
there is a lot more we can do with it.
| | 00:09 | Unity's physics engine is based on
NVIDIA's PhysX Engine, and has all kinds of
| | 00:13 | cool stuff like joints, springs, and
motors, not to mention constant forces.
| | 00:19 | Let's switch over to our Scripting Test
scene. We'll double-click it and then we
| | 00:24 | want to go ahead and activate
the Sphere. It was turned off.
| | 00:28 | So I'm going to click on it and up at
the top of the Inspector we'll click to
| | 00:33 | activate it. And we can go ahead and
double-click on it to focus it in the Scene
| | 00:38 | View. And then, since we're going to
drop it, we'll need to add from Component >
| | 00:46 | Physics > Rigidbody.
| | 00:48 | I'm going to zoom back a bit to see
where it is, and it looks like it's nowhere
| | 00:53 | near the rest of our stuff, so I'm
going to click the Y marker on the scene
| | 00:59 | gizmo. And I'm zooming out
and I'm still not finding it,
| | 01:03 | so I'm going to double-click on the
Cube, select the Sphere, and use, from
| | 01:13 | GameObject, Move To View.
| | 01:18 | Switch back to Perspective, and now
zooming out, we've found our Sphere again.
| | 01:26 | So let's go ahead and click play
and watch it drop to the ground.
| | 01:32 | Something is missing here.
| | 01:34 | We expect the cube to hit with a plop,
but we kind of expect the Sphere to
| | 01:39 | bounce, at least a little. For that we
need to assign a physics material, and
| | 01:45 | that's done in the Collider component.
| | 01:48 | Let's go ahead and exit Play
and then look into doing that.
| | 01:53 | In the Sphere Collider we see Material,
and it says None. If we click on the
| | 01:58 | shortcut to the browser, we find that
there are no physic materials listed.
| | 02:02 | Let's close it and it turns out, we
need to go to Assets > Import Package and
| | 02:10 | import the Physics Materials package. Import.
| | 02:14 | Now when we click on the
Browser button, we have a whole bunch.
| | 02:20 | Let's start with Bouncy and click play.
| | 02:27 | Now we can see our sphere bouncing up and down.
| | 02:31 | If we watch it, it seems to be gaining energy
with each bounce. We'll need some air friction.
| | 02:36 | In the Inspector, in the Rigidbody,
that's Drag. And we can click and drag next
| | 02:45 | to the field to increase it.
| | 02:47 | Now you can see our Sphere
slowing down and even to a stop.
| | 02:52 | That's a good time to exit Play mode.
| | 02:54 | The physics materials have parameters
that you can adjust, but if you want
| | 02:58 | to adjust something, you should
duplicate an existing one with Ctrl+D and
| | 03:03 | then tweak that one.
| | 03:04 | The next thing we want to look at in physics
is the Is Kinematic option on the Rigidbody.
| | 03:10 | The name doesn't exactly give us a hint,
but this one is extremely important, for
| | 03:14 | a couple of reasons.
| | 03:15 | When this is checked,
physics are not used on the object.
| | 03:19 | Okay, I know that sounds kind of funky.
Why put a Rigidbody on something if you
| | 03:24 | aren't going to use it?
| | 03:25 | It turns out that if an object has a
collider, physics are working on it anyway,
| | 03:30 | just like the original cube and the plane.
| | 03:33 | As long as the object with the
collider is static, or not moving, there is no
| | 03:37 | problem. But as soon as we transform
it, through scripting or physics, the
| | 03:43 | physics engine is forced to
recalculate, and that sucks up resources.
| | 03:49 | If we wanted to have something like a
windmill turning slowly throughout the
| | 03:52 | game, we would add a
Rigidbody and set it to Is Kinematic.
| | 03:58 | Another important use for Is Kinematic
is so we can anchor objects using joints.
| | 04:03 | We'll test this next.
| | 04:05 | Select the cube and we'll bring it down
within range in the Game view, and then
| | 04:10 | we're going to clone it. So Ctrl+D
clones the cube, and we're going to rename the
| | 04:16 | new one Board. And since it's a board,
we need to move it aside and use our Scale
| | 04:29 | to flatten it a bit.
| | 04:31 | Now we may as well move it over to the
side we can see in the Game view. And it
| | 04:38 | looks like right there would be good.
| | 04:43 | Before we go adding the Hinge
Joint component, think about where the
| | 04:47 | object's pivot point is.
| | 04:48 | It's in the center, right?
| | 04:50 | We want this board to hinge from the
edge of the cube, so we're going to need to
| | 04:55 | add an empty GameObject to that spot.
| | 04:57 | To do that, I'm going to focus on the
board from GameObject > Create Empty, and
| | 05:06 | we'll name this one board parent.
| | 05:09 | We'll adjust its position so it's at
the edge of the other cube, and drag our
| | 05:19 | board down that far, and now reselecting
the board parent, we can see that it's
| | 05:26 | going to look about right.
| | 05:27 | So now I'm going to drag my board into
the board parent to create a hierarchy.
| | 05:35 | Now we're going to add a Rigidbody to
the GameObject, named board parent, and
| | 05:42 | then we'll remove the
Rigidbody from the board, the child.
| | 05:46 | According to the docs,
you should never have a parent and child
| | 05:50 | Rigidbody together.
| | 05:52 | So first, for our board parent, we're
going to add Physics > Rigidbody, and then
| | 05:58 | for board, the child, we're going to
right-click and remove the component.
| | 06:04 | Now we'll add the Hinge Joint
component to the board parent.
| | 06:08 | First we need to select the board parent.
Then from Component > Physics, we're
| | 06:15 | going to select Hinge Joint.
| | 06:19 | It's got a bunch of parameters, but the
only one to worry about here is the axes.
| | 06:24 | We need to set them to 0 over in the
Inspector, and then we need to make sure
| | 06:32 | that we're choosing the right one.
| | 06:34 | In this case I'm okay.
| | 06:35 | It looks like X is the
axis we want to rotate from.
| | 06:38 | So we'll click play and test.
| | 06:45 | Like the Sphere, it looks like
it's going to swing forever,
| | 06:48 | so we could add a bit of drag if we wanted.
| | 06:50 | Let's exit Play mode first.
| | 06:53 | If the object is not going to be moving
aside, from the hinge, it can be parented
| | 06:57 | to the world by leaving the connected
body set to None, as we have it now.
| | 07:03 | If you wanted to connect the board
parent to the cube, you could drag the cube
| | 07:08 | into the Hinge Joint's Connected Body field.
| | 07:11 | We won't be doing that now,
but feel free to try it on your own.
| | Collapse this transcript |
| Working with physics components| 00:00 | So what if you wanted a sign outside an old
inn to swing in the wind during the whole game?
| | 00:05 | First off, you'd probably only have it
swing when the player was around to see it.
| | 00:11 | You already know a few ways to do that.
| | 00:13 | Assuming we'd eventually make it
dependent on the player's presence, we would
| | 00:17 | still need to know how to keep it
swinging, and that's where physics--the
| | 00:21 | Constant Force component--comes into play.
| | 00:24 | Let's add one to our board parent.
| | 00:26 | That's where all the action is.
| | 00:27 | Remember, the board is just
going along for the ride.
| | 00:30 | So we will select our board parent,
go to Component > Physics, and way down at
| | 00:37 | the bottom, we will find Constant Force.
| | 00:43 | In the Inspector, we can see that
we've got Force and Relative Force.
| | 00:48 | The first is global coordinates.
| | 00:51 | So if you had a bunch of physics
objects that were going to be affected by
| | 00:54 | wind, you'd use this one.
| | 00:56 | Relative would be useful for pushing
an object the direction it was facing.
| | 01:00 | We're going to use Force. Let's open it up.
| | 01:04 | If I check my scene gizmo, it looks
like I need to use the Z direction.
| | 01:08 | Positive values go one direction
and negative ones go the opposite.
| | 01:13 | In our Scene view, our Z is on the right-hand
side, but we need our wind to blow to the left,
| | 01:20 | so we're going to need to use a
negative value in our Z parameter.
| | 01:25 | So back in the Inspector, in the Constant
Force component, I'm going to type in a -1.
| | 01:33 | Before we hit play, let's go ahead
and fix one thing. Our cube falls,
| | 01:38 | so in the Inspector, in the Rigidbody,
let's tell that guy to be Is Kinematic.
| | 01:44 | Now we are ready to click
play and check on our wind.
| | 01:47 | So let's select our board parent again
and expose the Constant Force parameters
| | 01:53 | in the Inspector and hit Play.
| | 01:59 | Now you can see our board swinging.
| | 02:02 | You might want to try increasing
the force to see what reaction we get.
| | 02:07 | Okay, let's go ahead and exit play mode.
| | 02:11 | The next parameter in the
Constant Force is Torque.
| | 02:14 | Torque is rotation.
| | 02:16 | We're going to go ahead and add a
Constant Force to the original cube, Cube1, and
| | 02:21 | we'll try Torque on it.
So Component > Physics > Constant Force.
| | 02:30 | This time we didn't add a Rigidbody
first, but because we added Constant Force,
| | 02:38 | one was added for us.
| | 02:40 | And let's set the Torque, the Y parameter--
since that's up in the world--to about 50.
| | 02:49 | Now there's one more thing we need to
know. According to the docs, never have
| | 02:54 | transforms and physics
controlling an object at the same time.
| | 02:59 | That means we need to disable the
rotation script on this cube before we test.
| | 03:04 | And we can just turn it off or we
could right-click and say Remove Component.
| | 03:11 | Now we'll click play, and the
original cube is happily rotating.
| | 03:20 | If we left it going for a while,
it might wander off the board,
| | 03:24 | so we're going to try something else.
| | 03:27 | Exit play and to keep him from leaving
town, we need to go up to his Rigidbody,
| | 03:35 | open Constraints, and now we can
freeze his position to keep him from going
| | 03:42 | anywhere but spinning around.
| | 03:45 | In case you're wondering, when a
character is turned into a rag doll, all the
| | 03:50 | objects were animated by keyframe
animation and they already had Rigidbodies set
| | 03:55 | to Is Kinematic. They're unchecked
dynamically and the keyframe animation turned
| | 04:00 | off to allow the character to
tumble into a heap of bones.
| | 04:04 | Okay, since they're pretty important,
let's do a little recap on physics rules.
| | 04:09 | Number one: objects that have
colliders and are transformed by other than
| | 04:13 | physics need to have a
Rigidbody with Is Kinematic checked.
| | 04:18 | Two: don't mix active physics
and transforms at the same time.
| | 04:24 | Three: don't have parent and child
Rigidbodies together and use joints to
| | 04:29 | create hierarchies.
| | 04:31 | And four: never scale the parent of a
Rigidbody. Remember, children inherit the
| | 04:36 | transforms of their parents.
| | Collapse this transcript |
| Making cloth| 00:00 | Cloth is incredibly easy to make in
Unity, but it also uses a lot of resources,
| | 00:05 | so use it sparingly.
| | 00:07 | From the GameObject menu,
let's select Create Other > Cloth.
| | 00:14 | It starts out rather large, so let's
zoom out using my middle-mouse roller here,
| | 00:19 | move it up a little bit,
and use Scale to bring it down.
| | 00:27 | Let's start out by
moving it up above the sphere.
| | 00:33 | And I'm going to rotate my window to
make sure I am up above the sphere, and it
| | 00:38 | is. And now we can click play.
| | 00:47 | The Sphere and Cloth drop and the
Cloth eventually slides off, so we can
| | 00:52 | exit Play mode now.
| | 00:53 | Okay, everyone has seen the
Cloth-Sphere test a million times.
| | 00:59 | It's quick to calculate, and it looks impressive.
| | 01:02 | Let's try moving the Cloth over the
top of Cube1 and click play again.
| | 01:07 | Cube1 is our original cube sitting on
the ground. And that should do it. We'll
| | 01:13 | click play again, and you can see
it's also reacting to a moving object.
| | 01:25 | Okay, let's exit Play mode again.
| | 01:28 | I always figured the test is to see how
easy it is to attach a Cloth object to
| | 01:32 | something. Anyone can drop it.
| | 01:35 | Turns out, it's pretty easy. Let's save
the scene and get back into the main level.
| | 01:40 | File > Save Scene. And then we'll locate
our MainLevel scene and double-click it.
| | 01:49 | Let's select and focus in on the
fountain object, specifically the Fountain
| | 01:57 | Cloth. And you'll want to rotate the
viewport a little using your Alt button.
| | 02:03 | And now let's create a Cloth object and
then we'll set and position it to match the
| | 02:08 | original one hanging there.
| | 02:10 | GameObject > Create Other > Cloth.
And we'll need to rotate it and then shrink
| | 02:24 | it. And maybe I'll do a little bit of Scale on
my X axis, and then I'm going to drop it down.
| | 02:39 | So I want to leave it pretty much in
the place that the original imported Cloth
| | 02:43 | mesh was. Note that that's
just a mesh. It's not cloth.
| | 02:47 | So let's go ahead and, in the Fountain,
select the Fountain Cloth and deactivate it.
| | 02:56 | I'm going to spin my view
a little bit more again.
| | 02:59 | I'm getting tired of seeing the
crosshairs, so I'm also going to toggle off the
| | 03:03 | Overlays button. And now we have to
see how we go about hanging the cloth.
| | 03:09 | At the bottom of the Interactive Cloth
component, over in the Inspector, when we
| | 03:14 | select the Interactive Cloth, you'll
find something called Attached Colliders.
| | 03:20 | If we open it up, we're going
to see something a bit odd.
| | 03:23 | The variable on this guy is an array.
We'll get to work with arrays later on,
| | 03:28 | but for now all you need to know is
that they can have as many elements as we
| | 03:32 | need. We just need to tell it how many we want.
| | 03:35 | For this example we're going to need
three, so set the Size to 3, and now we can
| | 03:45 | see we have three elements.
| | 03:47 | Let's open Element 0. Arrays, by
the way, start counting at 0, not 1.
| | 03:52 | And it looks like we're
going to need a Collider,
| | 03:55 | so next we'll need to add some box
colliders to three of the bobbles that are
| | 04:00 | sitting on our fountain:
| | 04:02 | this one, this one, and that one.
And those are Bobbles014, 015, and 016.
| | 04:10 | So select Bobble014 and from
Component, we're going to add Physics > Box
| | 04:18 | Collider. And you might want to zoom in
a little bit closer here. And the trick
| | 04:23 | here is that we need that
Collider to intersect with the Cloth.
| | 04:29 | So in the Inspector, under the Box
Collider, I'm going to change its center by
| | 04:35 | adjusting its Y position. And I'll
just drop it down so I'm sure that it
| | 04:40 | intersects, as we can see over
here. And we need to do that for 15.
| | 04:46 | Component > Physics > Box Collider,
and adjust its Y. In this case we
| | 04:54 | probably need to adjust its X, make sure it
intersects the cloth. And the same for Bobble016:
| | 05:02 | Component > Physics > Box Collider.
| | 05:07 | And there again we're going to need to adjust
its X until we're sure that it's intersecting.
| | 05:13 | Now, switch back to our Interactive
Cloth and we'll scroll down to where we can
| | 05:19 | see our elements for our attached
colliders. And I'm going to go ahead and open
| | 05:23 | up Element 1 and 2 as well.
| | 05:27 | And now we just need to drag Bobble014
into the Collider field in Element 0, 15
| | 05:37 | into the Collider field in Element 1,
and 16 into the field in Element 2.
| | 05:45 | And that's all there is to it. If we
click play, we see our Cloth settled.
| | 05:50 | Let's exit Play mode and think about
what we can do to make it more interesting.
| | 05:56 | So you're probably wondering about wind.
| | 05:59 | It turns out the Cloth
Component has it built in.
| | 06:02 | If we select the Cloth and look up
farther in the parameters, we will find
| | 06:10 | External Acceleration.
| | 06:14 | In this case, I'm looking at my Scene
gizmo and I'm looking at my Cloth gizmo,
| | 06:19 | External Acceleration doesn't
tell us whether it's global or local.
| | 06:24 | So let's try turning on the wind on
our Y parameter and see what's happening.
| | 06:31 | I'm going to try a value of about 50.
| | 06:33 | It's probably overkill, but at least
we'll see if something happens. And we can
| | 06:39 | click play and there we go. It looks
like that proves that Y is using world.
| | 06:48 | So I'm going to exit Play and instead
of 50 in the Y, maybe I'll try 10 in the
| | 06:58 | Z. Here is our Z and let's see what happens.
Click play and there it goes; we've got wind.
| | 07:09 | Let's go ahead and exit Play mode.
| | 07:12 | Unlike the Rigidbody animations,
wind also has a parameter for Random
| | 07:18 | Acceleration. You might want
to try this one on your own.
| | 07:21 | So there is one other little issue.
If we use the default Cloth mesh, it's only
| | 07:27 | one-sided. If I hold my Alt key down
and spin it around, you can see, well, that
| | 07:32 | we look right through it.
| | 07:35 | For a material, we could use one of
the particle shaders since they are all
| | 07:39 | two-sided. And there are a few other
shaders that do two-sided, but most aren't.
| | 07:43 | I'll show you how to convert a few
simple shaders later on in the course.
| | 07:48 | One last thing we can try with this guy:
let's add a material to the Cloth and
| | 07:52 | see if we can find a shader that uses two-sided.
| | 07:55 | I'm going to open my Materials folder and see
if I can find anything that looks promising.
| | 08:00 | I have a feeling that this one might, so
let's click on it. And it has a Shader.
| | 08:06 | It's using one of the particle
shaders, so this one should work.
| | 08:10 | We can drag and drop it straight onto
the object in the viewport, and now, if
| | 08:17 | we spin this around, we can see that
we've got a material on both sides.
| | 08:23 | The last thing we can try with our
Interactive Cloth is instead of using the
| | 08:28 | rectangular default Cloth mesh,
we can actually use our own mesh.
| | 08:33 | So I'm going to select my Interactive
Cloth again and in its mesh parameter over
| | 08:40 | here on the Inspector, instead of
Plane, I'm going to hit the browser and I'm
| | 08:46 | going to go looking for our Fountain
Cloth. And we'll select it, and since we
| | 08:55 | can't see it, let's use our Alt
key to look around the viewport.
| | 09:02 | Oh, we are seeing it.
| | 09:04 | It's just small. So we can go ahead
and scale it up and then move it up.
| | 09:12 | It may need a little more scaling, because
it too is going to have to intersect the
| | 09:19 | colliders. And we should
probably double-check those.
| | 09:24 | I'll click on this bobble.
| | 09:25 | I think that was Bobble016. It might make it.
| | 09:31 | It will take a little adjusting to make sure
the Cloth mesh intersects with the colliders,
| | 09:34 | but in the end it will work
just like the regular Cloth object.
| | 09:39 | And finally, if you want to use
Cloth on characters or other skinned mesh
| | 09:44 | objects, you should use physics skin
Cloth instead. It's much more economical
| | 09:49 | since it doesn't offer so many choices.
| | 09:52 | As you can see, Unity offers
several good options for Cloth.
| | Collapse this transcript |
| Working with wind zones| 00:00 | As you've probably figured out by now,
adding wind in Unity is pretty much a
| | 00:04 | painful per-object affair.
| | 00:06 | The only exception is adding
wind to trees. Okay, not quite.
| | 00:12 | And the reason is that non-physics-
related wind is done with shaders, the things
| | 00:17 | that make up Unity materials.
| | 00:19 | Odd as it may seem, shaders can
displace vertices, so the nature shaders can
| | 00:24 | make your trees bend and sway, the
water shaders can add waves to your water,
| | 00:29 | and other shaders can cause other
useful effects if you know how to write them.
| | 00:34 | To activate the bend parameters on
trees, we need to use a Wind Zone.
| | 00:39 | The Wind Zone object allows you to
affect terrain trees as well as custom trees
| | 00:44 | all at once, or within localized
areas when you use a different mode.
| | 00:49 | We're already at the center of the nature
area, so let's focus in on the Fountain.
| | 00:55 | From GameObject > Create Other,
we're going to select Wind Zone.
| | 01:03 | It's come in at 0, 0, 0,
as we can see in the Inspector.
| | 01:07 | So let's go ahead and use
GameObject > Move To View.
| | 01:13 | Now we can see it near the fountain.
| | 01:15 | I'm going to move it up a little bit.
And you can see that the default mode on
| | 01:21 | the Inspector is Directional.
| | 01:24 | Let's go ahead and click play and try it out.
| | 01:29 | In the Inspector, if I click Escape to
get my cursor, we can try changing the
| | 01:36 | Wind Turbulence and any of the other parameters.
| | 01:42 | Let's exit play mode.
| | 01:45 | Under mode, we can also use Spherical.
| | 01:51 | If we click play and Escape to keep
our cursor, we can drag this guy back and
| | 01:58 | forth over our trees and
cause a helicopter-type effect.
| | 02:03 | Okay, let's exit Play mode again.
| | 02:06 | Let's go ahead and set our mode back to
Directional and we'll look at the next topic.
| | 02:14 | So, how do we control the
actual bend on the trees?
| | 02:17 | Well, that depends on the
shader used on the tree.
| | 02:21 | For the BigTree we added to the Terrain
library, changing the bend parameter has
| | 02:26 | absolutely no effect.
| | 02:27 | Feel free to try that out on your own.
| | 02:30 | Meanwhile, let's go ahead and select the
Terrain and head over to the Inspector.
| | 02:36 | I've noticed we're missing the palm tree.
| | 02:38 | That means we need to reload the Terrain assets.
| | 02:42 | So I'm going to go back up to Assets >
Import Package, and we'll reimport the
| | 02:49 | Terrain Assets package.
| | 02:53 | Click on Import and now we can go to
Place Trees > Edit Trees > Add Tree, and
| | 03:06 | we'll add our palm tree.
| | 03:10 | I'm going to leave the Bend
Factor to 0 and see what we get.
| | 03:15 | So let's click Add.
| | 03:17 | Now we can select our Palm tree,
paint a few and click play.
| | 03:26 | Without Bend, they're not moving in the wind.
| | 03:29 | So let's exit play, go back to the
Inspector, select the Palm and Edit Trees--we
| | 03:37 | want to edit them--and this time
we'll set their Bend Factor to about 3.
| | 03:44 | We'll click Apply, and now when we
click play, they're shaking right along with
| | 03:51 | the rest of the trees. Okay, that's good.
| | 03:56 | Let's exit Play mode, and since we
probably don't need palms here, I'm going to
| | 04:01 | zoom out a bit, select my Palm tree,
and, holding Ctrl, we'll remove only the palm trees.
| | 04:15 | You may need to zoom in a little closer
to make sure you get them all. And I'm
| | 04:21 | going to zoom out and rotate my view just to
make sure. And I think they're all gone now.
| | 04:30 | So let's deselect the Terrain and
now let's go up and look at BigTree.
| | 04:34 | I'm going to focus in on it by double-
clicking and then I'm going to rotate
| | 04:40 | the view and see if I can get a
little closer. And that's probably about as
| | 04:45 | good as we can get.
| | 04:46 | So what's the deal with the BigTree?
| | 04:49 | Why doesn't the Bend parameter affect it?
| | 04:52 | Well, it was created with the tree
generator, and it uses a material that uses
| | 04:57 | a different shader.
| | 04:58 | Let's select the BigTree and in the
Inspector, we'll need to open the Tree
| | 05:04 | component. And if we click on one of
the nodes and scroll down, we can see that
| | 05:13 | it has its own Wind parameters.
| | 05:16 | In this case, we have Main
Wind and Main Turbulence.
| | 05:21 | On each node of the Tree
hierarchy, you will see a Wind setting.
| | 05:25 | On the Leaf nodes, you will also get a
Main Turbulence and an Edge Turbulence.
| | 05:31 | If we select one of those,
we will be able to see that.
| | 05:36 | Scrolling down, this one has Main Wind,
Main Turbulence, and Edge Turbulence.
| | 05:45 | Whatever these settings are,
the Wind Zone controls them overall.
| | 05:49 | Main Wind will control how far the
tree bends in the wind direction and its
| | 05:54 | other two, in this case the
randomness and the amount of frequency.
| | 05:58 | Now as long as we're here, let's fix
another niggling problem: the dynamic
| | 06:03 | shadow's lack of respect for texture opacity.
| | 06:06 | This is a shader issue.
| | 06:08 | So we're going to fix this by
selecting the left leaf node and under its
| | 06:16 | Material parameter, we're just going
to click once to locate the original
| | 06:22 | material. Then we want to drag
BigTree_leaves into this one, and notice that
| | 06:30 | BigTree_leaves has an underscore.
And we'll do the same for the other leaf node.
| | 06:39 | This node uses BigTree_branches,
so we're going to take the BigTree_branches
| | 06:45 | and load it in there.
| | 06:47 | Now, if we look closely in our Scene
view, we can see that we're now seeing
| | 06:52 | actual leaves from BigTree,
| | 06:56 | but we aren't seeing them yet in the
Game window because the rest of the trees
| | 07:01 | were painted with the Terrain Editor.
| | 07:04 | To update them, we need to go to
Terrain > Refresh Tree and Detail Prototypes.
| | 07:12 | And now, at least in the Scene View,
we can see that they've been updated.
| | 07:16 | We have a message from the Console,
but I suspect that one is left over from pre-
| | 07:22 | tree-generator days, so
I'm just going to clear it.
| | 07:26 | We won't see it again.
| | 07:28 | And I'll close the Console.
| | 07:29 | Now notice that even our trees in the
Game view have been updated as well.
| | 07:35 | So our takeaways on Wind Zones are
tree creator trees need the wind settings
| | 07:41 | adjusted in the individual tree node;
regular trees used in the Terrain library
| | 07:47 | are adjusted using the Bend settings.
| | Collapse this transcript |
| Using an audio source| 00:00 | About now you're probably thinking a
few sound effects would go a long way
| | 00:04 | towards making our game more engaging.
| | 00:07 | Before we can have any sound in a
scene, we must have an audio listener
| | 00:10 | component, and only one.
| | 00:13 | This should sound familiar. Cameras have one by
default, and we've already had to remove a few.
| | 00:18 | To hear sound we need to add audio
source components, but first we'll need to
| | 00:23 | import some sound files.
| | 00:25 | Let's go out to the exercise folders
and drag the Game Sounds folder into the
| | 00:31 | Unity Sampler Assets folder.
| | 00:34 | In Ch06/06-09, from the Assets
folder--and these are the exercise assets--
| | 00:42 | we're going to right-click and Copy
the entire Game Sounds folder. And then in
| | 00:51 | the UnitySampler folder, our project,
we're going to click on that Assets
| | 00:58 | folder, right-click, and Paste.
| | 01:03 | Now we can return to Unity and if we
check our project view, we should find them.
| | 01:12 | I'm going to close everything else
first. And there it is, Game Sounds.
| | 01:17 | Let's open it, and now we've
got lots of things to play with.
| | 01:21 | Unity can handle several audio file types:
| | 01:24 | AIF, WAV, MP3, and OGG.
| | 01:29 | You will need to decide on how it
stores and plays them, and that will
| | 01:34 | probably depend on length.
| | 01:36 | When you let Unity compress the files
it uses the Ogg Vorbis compression for Mac
| | 01:42 | and PC and MP3 for mobile.
| | 01:45 | Let's see how this works.
| | 01:47 | Select the Birds1 sound
in the Game Sounds folder.
| | 01:52 | In the Inspector, we can either click
Play down in the Preview,
| | 01:56 | (birds chirping)
| | 02:00 | or we can turn on Auto Play, so that
whenever we click the file, sounds will play.
| | 02:06 | (sound effects)
| | 02:10 | sounds will play. I'll be turning Auto Play off.
(sound effects)
| | 02:14 | Most of the sounds in the new folder
are already Ogg Vorbis, but the last one,
| | 02:24 | Warning, is a WAV file.
| | 02:28 | So under Format it shows as Native.
Very short sound effects can be left as
| | 02:33 | native and should be set to Load into memory.
| | 02:36 | This one shows a 6.2K disk
size, so it's pretty small.
| | 02:41 | If we change the Compression to Ogg
Vorbis, under Audio Format, and click
| | 02:50 | Apply, the new file size is now 4.2K.
And now you have the option to keep it
| | 03:00 | compressed in memory.
| | 03:01 | Larger files such as background sound and
music should usually be treated this way.
| | 03:06 | Unity also offers a streaming option,
and it's well covered in the docks.
| | 03:10 | Anyway, our file here is just a little
bitty thing, so let's change it back to
| | 03:14 | Native. Don't forget to hit Apply.
| | 03:17 | In Unity, sound is set to 3D by default.
| | 03:21 | That means that when we add a sound to the
scene, it is directional and distance-based.
| | 03:26 | Let's select the WindZone object
in the Hierarchy and add an audio
| | 03:30 | source component to it.
| | 03:33 | WindZone, Component, and under Audio,
we're going to add an Audio Source.
| | 03:41 | Now zoom back a little bit,
so we can see our WindZone.
| | 03:46 | I'm going to rotate the view just to
remind you that the WindZone is already
| | 03:50 | centrally located in the nature area.
| | 03:52 | And now let's drag the LightWind
sound clip into the Audio Source.
| | 04:01 | The first thing we notice is that it's
set to Play On Awake. Directly beneath
| | 04:07 | that is Loop. We'll need that one too.
| | 04:10 | Now let's click play and drive
towards the center of the nature area.
| | 04:20 | As we drive closer to the center,
we expect to hear some sound, but I'm
| | 04:26 | hearing very little.
| | 04:28 | Let's exit Play and see
was what's going on here.
| | 04:32 | So there are a few things
that are happening here.
| | 04:34 | Let's open up our Sound settings first.
| | 04:38 | So the Max Distance is set to 500.
Our little nature area is only about 200
| | 04:43 | meters, so that should be okay.
| | 04:46 | But here's the clincher: if we look at
the Listener curve in the little graph,
| | 04:50 | we can see that the falloff is pretty severe.
| | 04:54 | Up in the Volume Rolloff, we can see
that it's set to Logarithmic Rolloff.
| | 04:59 | Let's set it to Linear.
| | 05:01 | Now the curve has an even Rolloff and
we should be hearing our sound a lot
| | 05:06 | louder, a lot sooner.
| | 05:08 | Let's click play and try it.
(sound effects)
| | 05:17 | And sure enough, we get a much better effect.
(sound effects)
| | 05:25 | So we can hit Escape and
get out of Play mode again.
| | 05:28 | Now here's a tip: if your sound file was
already stereo, you'll want to turn the
| | 05:34 | Spread--and we can find
that right here--all the way up.
| | 05:39 | Spread combines both channels so that
they can react properly in the 3D environment.
| | 05:44 | Feel free also to adjust the Min Distance
and Max Distance to improve the Rolloff.
| | 05:50 | If you were to click play now, at the
gate we should hear nothing, but it should
| | 05:55 | be loud at the center.
| | 05:57 | If you want, you can even try
your hand at a custom rolloff.
| | 06:00 | In the Listener curve, you can right-
click to add a key, and you can adjust to
| | 06:07 | make a Custom curve.
| | 06:09 | In the next video, we'll be
creating a stand-alone sound zone.
| | Collapse this transcript |
| Creating a sound zone| 00:00 | In this video, we'll start seeing how
to control our audio through scripting.
| | 00:05 | Since our nature section is a
foresty sort of area, we might like to add
| | 00:09 | some bird sounds too.
| | 00:11 | But you can only have one Audio
Source component on an object.
| | 00:15 | We could get around that by adding an
empty GameObject to the WindZone and then
| | 00:19 | giving it an audio source of its own.
| | 00:22 | For now though, let's just reuse
the audio source we've already got.
| | 00:26 | Let's start by selecting our WindZone
and from the Game Sounds folder, let's
| | 00:31 | drag Birds1 into the audio clip.
| | 00:35 | Make sure it's set to Loop. And then I want to
set the Custom Rolloff so I get a steep exit.
| | 00:44 | I'll click on the existing
node, and I can move its handle up.
| | 00:49 | I want to get rid of this node, so I
can click on him and then right-click
| | 00:54 | and say Delete Key.
| | 00:56 | Then I might need to adjust this one
a little bit more. We're good to go.
| | 01:02 | If we clicked play and test it at this
point, we would be able to hear birds
| | 01:06 | all the way out into the other sections,
but it isn't the right mood for the
| | 01:10 | other areas, so we're going to write a script
to turn the whole audio component off and on.
| | 01:16 | To make easy, we can use a
collider to trigger on enter and exit.
| | 01:22 | Let's start by adding a
Box Collider to the WindZone.
| | 01:25 | With the WindZone selected, we're going to
go to Component > Physics > Box Collider.
| | 01:33 | Now in the Inspector, the first thing
we need to do is set it to Is Trigger.
| | 01:39 | That will allow us to drive through it.
| | 01:41 | Then I'm going to adjust my Scene view
for a better top view, and now I'm going
| | 01:48 | to adjust the size by dragging on the X
and dragging on the Z until my Collider
| | 01:58 | fits the area better.
| | 01:59 | We may need to adjust the center as well.
| | 02:04 | And the last important part is to
rotate the view and make sure that the
| | 02:11 | Collider is going to be low enough for
our First Person Controller to interact
| | 02:16 | with, and for that we need to change the Y size.
| | 02:22 | Now in the Game Scripts folder
right-click and create a new JavaScript.
| | 02:30 | We'll name it SoundZoneController,
and we'll open it in the Script Editor by
| | 02:36 | double-clicking on it.
| | 02:38 | To start, this one is going to be very simple.
| | 02:40 | We just need to turn the Audio
Component off and on on enter and exit.
| | 02:45 | So we'll need to make an
OnTriggerEnter and an OnTriggerExit function.
| | 02:50 | I'm going to tab out to the Exercise
folders and copy the code.
| | 02:54 | Ch06/06-10/06-10Code_Snippets.
And we're going to take the whole top section.
| | 03:06 | Copy, tab over and since these are
functions, we're going to add them underneath
| | 03:13 | the existing functions.
| | 03:15 | Paste and we've got our new
OnTriggerEnter and OnTriggerExit.
| | 03:19 | Now we are going to be enabling and
disabling the Audio Source component.
| | 03:26 | You may think we need to use audio
source.enabled, but this is one of the ones
| | 03:31 | that we have a shortcut for,
| | 03:33 | so we only use audio.enabled.
| | 03:36 | Let's go ahead and save our
script and get back to the Editor.
| | 03:41 | Now we need to drag our
SoundZoneController onto the WindZone, but before we
| | 03:47 | click play, let's try one more thing.
| | 03:50 | Let's select the WindZone and adjust the
Inspector so we'll be able to watch the
| | 03:58 | audio source turn off and on as we go in and
out of the Collider. We'll click play.
| | 04:05 | (sound effects)
| | 04:09 | It was set to Play On Awake, so it's
already playing, but now I'll drive forward
| | 04:14 | with W and backward with S
and the audio source turns off.
| | 04:22 | If I go Forward again, it turns on,
but we're not hearing the audio anymore.
| | 04:29 | So there's one more thing we
need to do to our script to fix it.
| | 04:33 | I'm going to hit Escape and then I'll get out
and Play mode and return to the Script Editor.
| | 04:41 | It turns out we need one more little line
here, and that one is audio.Play() and the
| | 04:57 | semicolon to end the line.
| | 04:59 | Now we can save our script
and get back to the editor.
| | 05:04 | This time when we click play, drive
into the zone, drive out with the S key, and
| | 05:14 | drive back in, our birds play again.
| | 05:22 | Let's hit Escape and exit Play mode.
| | 05:28 | So there you have it. We'll deal with
one-off sound effects in the next video.
| | Collapse this transcript |
| Adding audio effects| 00:00 | Now that we've had an introduction
to audio, let's add some sound effects
| | 00:04 | to specific objects.
| | 00:06 | Our cannonball is a prime candidate.
| | 00:08 | Let's start by adding sound when it's fired off.
| | 00:11 | For this we need to add an audio
source to the Proxy Weapon. So let's elect
| | 00:16 | our First Person Controller, Main Camera >
Weapon Handler and here is our Proxy Weapon.
| | 00:24 | From Component > Audio, select Audio Source.
And we need to turn off Play On Awake.
| | 00:35 | Like before, we'll play the audio clip
directly from the script, but this time we
| | 00:40 | won't tell it which clip to play in the
Components audio clip parameter. Let's
| | 00:45 | go ahead and open the Projectile Script.
| | 00:48 | Double-click. It brings up the Script Editor.
First we need to create a variable to
| | 00:53 | hold the audio clip.
| | 00:55 | So under my speed variable, I'll add
var weaponFireFX of type Audioclip;.
| | 01:17 | And inside the if clause where we fire the
projectile we're going to add these lines.
| | 01:23 | So inside the if clause--and we can
start down here. I'll tab over, and we'll a
| | 01:29 | note to ourself with our forward slashes
to make a comment. Play a sound when it
| | 01:35 | fires. Hit Enter and here's our line.
| | 01:42 | audio.PlayOneShot, and now it takes the
argument weaponFireFX, our audio clip.
| | 01:56 | So I'm going to double-click,
right-click and Copy and right-click and Paste,
| | 02:04 | and then I'll close my
parentheses and semicolon.
| | 02:08 | So we can go ahead and save our script
now and get back into the editor. And now
| | 02:14 | we need to select our Proxy Weapon,
find a script--here it is, our Projectile
| | 02:20 | Script--and we need to add a sound.
And I'm going to choose PopCanon and I'll
| | 02:26 | drag it right over here.
| | 02:29 | Before we click play though,
there's one thing I'm going to do.
| | 02:32 | I'm going to disable the WindZone so we don't
have to listen to those birds over and over.
| | 02:38 | So I'm going to click the WindZone
and deactivate it up in the Inspector.
| | 02:44 | Okay, click play and fire the weapon.
Remember, we do that with either the left
| | 02:49 | mouse button or the left Ctrl Key.
| | 02:53 | Play and here we go.
(cannon firing)
| | 03:00 | And so now we have a sound
when we fire off our weapon.
| | 03:04 | Let's Escape, get out of Play mode,
and look to see what we need to do next.
| | 03:11 | Well, of course now we need a sound for
when the cannonball hits something, but
| | 03:16 | we really don't want to have to put an
audio source on everything that can be
| | 03:20 | hit, and we probably don't want to have
to assign a special sound to each object
| | 03:24 | that can be hit either.
| | 03:25 | An advanced solution would be to have
the hit object use send message to tell
| | 03:31 | the projectile what sound to use,
but we're just going to keep it simple.
| | 03:36 | Let's start by adding an audio source to
the Cannonball prefab in the Project folder.
| | 03:41 | So in the Project folder, we'll select
our Cannonball prefab. From Component >
| | 03:48 | Audio, we'll add our audio source.
| | 03:51 | Once again, as soon as we find it,
we're going to turn off Play On Awake.
| | 04:00 | And this time since it maybe quite a
distance away, let's make sure we change our
| | 04:05 | Volume Rolloff to linear rolloff;
otherwise, we might not even hear it.
| | 04:12 | So as long as we have the Cannonball
selected, let's go ahead and tidy things up.
| | 04:17 | I'm going to close the Game Sounds
folder for a minute, and I want to take my
| | 04:21 | Cannonball prefab and drag
it into the Prefabs folder.
| | 04:25 | That was made when we imported the
fountain, but it will serve us well for
| | 04:29 | all of our prefabs.
| | 04:31 | Now let's open the ProjectileHandler script.
| | 04:35 | Double-click it to open it in the
Script Editor and now we need to add a
| | 04:39 | variable named var hitSound, of type
AudioClip, and of course semicolon.
| | 04:58 | Now here's the tricky part: we need
to decide where we want it to play.
| | 05:03 | If it's gotten as far as
OnCollisionEnter, either way, it can play a sound
| | 05:08 | effect, so we are going to add our play
line down below the else. And this one
| | 05:17 | will be audio.PlayOneShot.
And inside the argument will be our hitSound
| | 05:32 | variable, right-click and Copy, right-click
and Paste, close the parentheses and semicolon.
| | 05:42 | So let's go ahead and save our script
and head back to the editor. Before we
| | 05:47 | can test it, we need to select the
Cannonball prefab. And remember, we just put
| | 05:53 | it into the Prefabs folder. And we need to
load a sound into its new Hit Sound parameter.
| | 06:01 | I'm going to open up Game Sounds and
choose plopsm. And be sure you put it in
| | 06:09 | the Hit Sound parameter, not the audio source.
| | 06:12 | Okay, we're ready to play.
Let's click play and fire it off.
| | 06:20 | (sound effects playing)
| | 06:26 | With the addition of audio,
our little projectile is shaping up nicely.
| | Collapse this transcript |
|
|
7. Exploring PrefabsCreating and reusing prefabs| 00:00 | Prefabs are Unity's mechanism for
creating fully-formed sophisticated
| | 00:04 | game objects on the fly.
| | 00:06 | We've made instances of objects in the
scene using duplicate, Ctrl+D, but they
| | 00:12 | only exist in their own particular
scene, to instantiate an object at runtime
| | 00:17 | in any scene or level we need to store the
original and the Project view as a Prefab.
| | 00:22 | We've already created a
simple Prefab, our Cannonball.
| | 00:26 | It's instantiated at the transfer of the
object the script is on. Let's open the
| | 00:31 | Projectile script in Script editor
and take a closer look at what the
| | 00:35 | Instantiate function is doing.
| | 00:37 | We'll just double-click it to open it
up, and here's our Instantiate line.
| | 00:42 | It creates an instance of the projectile
at a particular location and orientation,
| | 00:48 | transform.position and transform.rotate.
| | 00:52 | Transform is referring to the object the
script is on, in this case the Proxy Weapon.
| | 00:56 | Let's take a minute to look up
instantiate in the scripting reference.
| | 01:01 | I'm going to go back to the editor, and
open the scripting Reference, and we're
| | 01:08 | going to type in instantiate
in the search and click Enter.
| | 01:12 | I'm going to choose the first one,
object.instantiate. Let's take a minute to
| | 01:16 | look up instantiate in the scripting reference,
| | 01:19 | we've used the second
variation with the Cannonball,
| | 01:22 | transform.position and transform.rotation.
| | 01:26 | But if we wanted to do something like
instantiate a genie and a puff of smoke in
| | 01:30 | a fixed position, we'd leave off the
position and rotation arguments and the
| | 01:35 | instance would be creating using
the Prefab's original transforms.
| | 01:39 | The last form of
instantiate would be the one we want.
| | 01:44 | Let's try that with something more down
to earth, a rock, and since the code is
| | 01:48 | already written for us in the
scripting Reference we may as well trigger the
| | 01:52 | Instantiation with an OnTriggerEnter.
| | 01:55 | Let's go back to the editor, and
we'll start by moving the first-person
| | 01:59 | controller to the staging area.
| | 02:04 | So on my top view, I'm going to select
my first-person controller, use my middle
| | 02:10 | mouse to pan and roll it to zoom, and
I'm going to switch to Global and drag
| | 02:21 | them back behind the
first barrier, about, like so.
| | 02:31 | Next we'll create an empty game object
near the first-person controller, I'm
| | 02:35 | going to double-click to zoom a little closer.
| | 02:38 | So I'll make it GameObject, Create
Empty, and we'll name this Rock Zone.
| | 02:44 | And we'll give it a box collider,
Component > Physics > Box Collider.
| | 02:53 | Check Is Trigger, and we'll want to
scale it up to about 5x5x5.
| | 03:03 | And I'll zoom out, and we'll move it back
a little from the first-person controller.
| | 03:08 | Now let's create a new script in
the Game folder and name it Rocks.
| | 03:14 | Right-click > Create > Javascript, and
we'll name this one Rocks, and we'll go
| | 03:21 | ahead and open it in the Script editor.
| | 03:24 | I'm going to go out and get
the code from the Snippets file.
| | 03:29 | Exercise Files07/07-01/07-01 Code Snippets.
| | 03:40 | So we'll select it, right-click, Copy,
and then back in our scripts editor I'll
| | 03:46 | just paste it into the Rocks script.
| | 03:49 | This one is pretty simple. Let's go
ahead and Save and head back to the editor,
| | 03:53 | and we'll drag the new script
onto the Rock Zone Game object.
| | 03:58 | Now we'll need a rock, so let's
import the simple rock package from this
| | 04:03 | video's assets folder.
| | 04:06 | Right-click > Import Package > Custom
Package, and in the Assets folder select
| | 04:18 | SingleRock and Open, and we'll
Import, and our rock can be found in the
| | 04:26 | imported assets folder.
| | 04:28 | The usual procedure for
creating a Prefab is to: one,
| | 04:32 | create an object in the scene.
Two, create a new Prefab in the Project view.
| | 04:38 | Three, drag the object from the
Hierarchy view onto the Prefab, and four, delete
| | 04:43 | the original from the scene.
Let's give it a try.
| | 04:46 | We'll start from dragging the rock
into the scene from the Project folder.
| | 04:54 | I'm going to switch to Perspective.
Next we'll create a new Prefab in the
| | 04:58 | Project view in the Prefabs folder.
| | 05:01 | So, select folder, right-click > Create > Prefab,
and we're going to name that
| | 05:10 | one Rock Prefab, since we
already have a rock in the scene.
| | 05:15 | And you'll notice that its icon is white.
| | 05:18 | As soon as we take our rock into it,
we'll see the Prefab icon turn blue.
| | 05:26 | In case you notice the object's name
in the Hierarchy view was already blue
| | 05:30 | since it's an instance of an asset
that's already in the Project view.
| | 05:34 | We've already got an object named
Rock in the project view, so we avoided
| | 05:38 | confusion by naming this one Rock Prefab.
| | 05:41 | Our Prefab is ready to use, so in the
Hierarchy view we can delete the rock from the scene.
| | 05:48 | I'll select it and then hit Delete.
| | 05:50 | And now we need to assign the Rock Prefab
to the Prefab parameter of the Rock Zone.
| | 05:55 | So we'll select this, and we'll drag
our Rock Prefab over onto that parameter.
| | 06:04 | Now if we click Play, and move our
first-person controller into the collider,
| | 06:11 | and I'm going to use my S key for that
to run in backwards, we can see that the
| | 06:16 | Rock gets instantiated right where we placed it.
Let's exit Play mode.
| | 06:23 | The Rock Prefab we instantiated
during runtime is destroyed, leaving the
| | 06:27 | Hierarchy just as it was before we clicked Play.
| | 06:30 | So what it wanted our Prefab to be
instantiated in a different position?
| | 06:35 | Simple, drag the Rock
Prefab into the Hierarchy view.
| | 06:41 | It appears right where we originally put it.
| | 06:44 | Now in the Scene view, let's
move it off to the side a bit.
| | 06:50 | Now we need to update the Prefab.
| | 06:53 | At the top of the Inspector, under the
Prefab section, we're going to click Apply.
| | 07:00 | Now let's delete this guy,
| | 07:03 | right-click > Delete, click Play, and
as we move our first-person controller
| | 07:11 | into the collider again our rock is
instantiated in the new position, and we can
| | 07:16 | go ahead and exit Play mode.
| | 07:18 | If we wanted to include several rocks
in our Prefab we could put them all in an
| | 07:22 | empty game object and drag that back
onto our Prefab, using that method will
| | 07:28 | give us a warning about overwriting,
but it allows us to make more serious
| | 07:32 | changes to an existing Prefab.
| | 07:34 | As an added benefit, once an object or
group of objects exists in the Project
| | 07:40 | view, we can export it as a Unity
package. Let's go ahead and make one now.
| | 07:46 | Let's select our Rock Prefab in the
Prefabs folders and from the right-click
| | 07:52 | menu choose Export Package, we'll click
Export, and I'm just going to save mine
| | 08:01 | here, and maybe I'll make it RockSingle and Save.
We've just made our first Unity package.
| | Collapse this transcript |
| Using prefabs with arrays| 00:00 | Let's have a bit more fun with Prefabs.
| | 00:02 | So far we've instantiated them in
predictable places at predictable times.
| | 00:08 | In our little game the player
will start out in the staging area.
| | 00:11 | It's small, and there's nothing of
interest in it, but we might need to motivate
| | 00:15 | him into leaving it.
| | 00:16 | A bunch of rocks falling on
him just might do the job.
| | 00:20 | Now it would look pretty odd if all
the rocks were the same size, but the
| | 00:24 | Instantiate function
doesn't have a Scale parameter.
| | 00:27 | So the first thing we need to do is
import the LotsOfRocks package from
| | 00:32 | the right-click menu.
| | 00:36 | Import Package > Custom Package, and
from our Assets folder we are going to
| | 00:44 | bring in LotsOfRocks.
| | 00:49 | In the Prefabs folder, you can see
Rock1, Rock2, Rock3, and Rock4.
| | 00:55 | I've added to each a Mesh collider set to Convex, a
Physics material, a Rigidbody, and an Audio Source.
| | 01:04 | Let's drag the four new rocks into
the scene near the original rock pile, and
| | 01:08 | then lift them up above
the Rock Zone's collider.
| | 01:14 | Rock1, Rock2, Rock3, and Rock4, and
I'll use Shift to select them all and drag
| | 01:30 | them up a little ways.
| | 01:32 | I'm going to deselect them, and click Play,
and watch them fall. We'll exit Play mode.
| | 01:41 | And now we need to update each Rock's
Prefab by clicking Apply in the selector
| | 01:47 | to make sure it knows where the new location is.
| | 01:52 | Apply, Apply, Apply, and Apply, and
now we can delete the rocks in our scene,
| | 02:07 | Delete, and there we go, so far so good.
| | 02:10 | Let's make a new Rock script in the Game
Scripts folder by duplicating the original.
| | 02:15 | So I'll select it and use Ctrl+D, and
I want to name this one RockDropper.
| | 02:23 | Let's open it in the Script editor and
make a few changes, double-click, make
| | 02:30 | sure we're on RockDropper.
| | 02:31 | And the first change we are
going to make is the variable.
| | 02:35 | Instead of 1 of type transform
we're going to make it an array.
| | 02:39 | Unity uses two types of arrays, the usual
Javascript type array, and its own version.
| | 02:46 | The Unity array must be declared as a
particular type, and it can show up in the
| | 02:50 | Inspector where we can change
its size and load up its elements.
| | 02:55 | A Javascript array doesn't store types
causing the #pragma strict to report an error.
| | 03:01 | With Unity's emphasis on mobile we're
better off to stick to the Unity arrays.
| | 03:06 | If you're already familiar with
Javascript arrays you may want to read through
| | 03:10 | the scripting reference on
arrays to see the differences.
| | 03:13 | So in the RockDropper script, let's
change the variable line to their Prefabs,
| | 03:20 | I'm adding an S, and then transform
and then open and shut bracket.
| | 03:27 | This is what tells us it's going to be an array.
Next we need to change the instantiate line.
| | 03:33 | To access an element of an array we
need to put the element number in brackets.
| | 03:38 | So Prefabs and open bracket, I'm going
to start with element 0 and close bracket.
| | 03:46 | Arrays always start with element 0.
| | 03:49 | Let's save the script now
and get back to the editor.
| | 03:56 | We can replace the original script
with this one on the Rock Zone object.
| | 04:00 | And we can do that to the browser,
and we'll choose RockDropper.
| | 04:10 | If you click Play, and use the S key to
back into the collider, you'll get an
| | 04:15 | IndexOutOfRangeException Error on the console.
Let's look at that.
| | 04:23 | That's because we haven't filled out the
array with anything yet, and then we're
| | 04:27 | trying to instantiate element 0.
So let's exit Play mode and fix that.
| | 04:33 | I'll close the console, exit Play mode.
| | 04:36 | And in the Rock Zone, we need to
open up Prefabs, set its size to four.
| | 04:44 | And drag the Rock into each parameter.
| | 04:54 | Now we can click Play, press S to back into
the zone, and we get lots and lots of rocks.
| | 05:03 | Let's stop before we get too many.
| | 05:07 | So this time the Rock Prefab
from element 0 drops into the scene.
| | 05:11 | And it keeps dropping because
each rock triggers the zone on entry.
| | 05:16 | In this case that's a serendipitous side effect.
| | 05:19 | It will eventually shut
itself off when it fills up.
| | 05:22 | The problem now is that the same
rock is being used over and over.
| | 05:26 | We'll fix that in the next video.
| | Collapse this transcript |
| Introducing randomness| 00:00 | In the last video we left our rock element
zero dropping over and over into the zone.
| | 00:06 | We need a way to use all four of
our rocks better yet in random order.
| | 00:11 | Since randomness is a mainstay of
games of all types, let's use the random
| | 00:15 | function to get different rocks.
| | 00:17 | We'll start by opening the scripting
Reference and do a search for random.
| | 00:23 | And we'll enter, and we're
going to select Random.Range.
| | 00:27 | If we look up Random.Range, we
see that it has two configurations:
| | 00:32 | one for using floats, where both of the
values are inclusive, and the one that
| | 00:37 | uses integers, where the
max number is not inclusive.
| | 00:42 | This may sound odd until you think
about arrays, they start at element zero.
| | 00:47 | So if we have four elements we can ask
for an integer between zero and four.
| | 00:53 | And it will give us 0, 1, 2, or 3.
| | 00:57 | Perfect. Let's go back to the editor.
And we'll start by opening the RockDropper
| | 01:02 | in the Script editor.
| | 01:05 | Let's start by rewriting the instantiate line
and replacing the zero with the random function.
| | 01:11 | And that will be Random.Range
and our range will be 0 to 4.
| | 01:24 | Let's Save the script and
head back to the editor.
| | 01:28 | Now we can click Play again, and back
the first-person controller into the
| | 01:33 | collider with our S key, and there we go.
Let's click Stop, and you can see it works.
| | 01:43 | A randomly selected rock from our array is
dropped each time the Rock Zone is triggered.
| | 01:49 | There's one more thing
we ought to change though.
| | 01:51 | We hard coded the 4 in the Range, and
that's not good practice, we'd have to
| | 01:56 | manually change it each time we
change the array in the Inspector.
| | 02:00 | Instead, let's create a variable to hold
the length of the array because arrays
| | 02:06 | have a length parameter.
We can get that number in the Start function.
| | 02:11 | So back in the Script editor, we're
going to add the variable var Prefabs
| | 02:17 | length of type int.
| | 02:20 | And in the Start function, we'll go
ahead and assign the value PrefabsLength
| | 02:28 | equals Prefabs.Length.
| | 02:31 | As long as we're in the RockDropper
there's one more thing we need to consider.
| | 02:35 | Since the amount of rock seems to be
dramatically increasing, it might be a good
| | 02:40 | idea to disable the physics after
a few seconds using isKinematic.
| | 02:46 | If we do that after the line is
instantiated in the new Prefab, we'll need a
| | 02:50 | temporary variable name so we can refer to it.
| | 02:54 | The Instantiate function returns the object
it just created, so we can assign it directly.
| | 03:00 | We'll change the line as follows,
| | 03:02 | var clone of type transform
equals the instantiated object.
| | 03:14 | And now we'll add directly
underneath this--so I'm going to give myself a
| | 03:18 | little bit more room.
| | 03:21 | And now I'm going to go out to my
snippets file and grab the next two lines,
| | 03:26 | Exercise Files07/07-03/Code_Snippets,
and we're going to grab the last two
| | 03:35 | here, right-click, Copy, and I'm
going to paste these right here.
| | 03:42 | New here is the yield statement.
| | 03:45 | It's another odd ball syntax
wise, but it's extremely useful.
| | 03:49 | For a single frame you can just use yield.
This one, as you can probably tell, takes seconds.
| | 03:58 | Rigidbody is another one of those
components that you can get directly,
| | 04:01 | we don't need get
component rigidbody to refer to it.
| | 04:05 | The isKinematic we've seen before, it
turns off the physics on an object so we
| | 04:10 | don't suck up all the machine's resources.
| | 04:14 | So let's go ahead and save our
script now and head back to the editor.
| | 04:20 | And we'll click Play, and drive our
first-person controller into the collider
| | 04:24 | again using the S key, and
we'll go ahead and stop Play mode.
| | 04:37 | We've already discovered that the
rocks will eventually pile up so high that
| | 04:41 | they completely cover up the Rock
Zone's collider, effectively shutting it off.
| | 04:46 | Feel free to reduce the height of the
Rock Zone's collider to one and move it
| | 04:50 | down so will shut off sooner.
| | 04:53 | Even without our player taking damage
from the rocks, he'll quickly get buried
| | 04:57 | and should be highly
motivated to get through the door.
| | Collapse this transcript |
| Creating particle systems| 00:00 | A big part of interactive games
regardless of genre is Particle systems.
| | 00:05 | Particle systems make up
most of the eye candy in a game.
| | 00:09 | One of the unique things about
Particle systems is that they usually can't be
| | 00:13 | imported from regular 3D applications
like Max or Maya, so need to be developed
| | 00:18 | almost exclusively in the game engine.
| | 00:21 | Unity has a complex and powerful system
for creating and combining particles to
| | 00:25 | give you all sorts of special effects.
| | 00:27 | We'll only cover enough to get you
familiar with the main features, but you
| | 00:32 | should come away with enough
understanding to let you spend hours on your own
| | 00:35 | experimenting with them.
| | 00:37 | Let's go ahead and import the Particles
package, right-click Import Package, and
| | 00:44 | this time we're looking
for Particles, and Import.
| | 00:52 | Let's create a new scene for our
Particle system experiments, File > New Scene,
| | 01:01 | and we can go ahead and Save.
| | 01:03 | And then we are going to
name this one as Particle Tests.
| | 01:06 | File > Save Seen As, Particle Tests,
and that should automatically open up in
| | 01:16 | our Unity 704 Assets
folder, and we'll click Save.
| | 01:20 | This will save it automatically
into our projects Assets folder.
| | 01:25 | Now that we've got several scenes
cluttering up the project view, let's go ahead
| | 01:29 | and make a folder called Scenes
and put all of our scenes into it.
| | 01:33 | Right-click > Create > Folder, and we'll
name it Scenes, and then we'll drag all
| | 01:44 | of our scenes into it.
| | 01:53 | To make a new Particle system, you can
either make an empty game object and add a
| | 01:57 | Particle system component to it, or
create it directly from the game object
| | 02:02 | Create Other submenu.
| | 02:04 | Let's use that method to create this one,
Game Object > Create Other, and it's
| | 02:10 | right here at the top, Particle system.
| | 02:15 | And it happily spews
particles at a casual speed.
| | 02:19 | Let's deselect the Particle
system in the hierarchy view,
| | 02:24 | the particles are no longer active.
| | 02:26 | Since we won't need the game window for
a while, let's switch to wide layout and
| | 02:31 | focus back on the Particle system.
| | 02:33 | Under 2x3 we'll switch to wide, and
we'll double-click on the Particle system to
| | 02:41 | bring it back into the view,
and once again they start flowing.
| | 02:46 | You can also scrub through the timeline
by clicking to the left of the playback
| | 02:50 | time and dragging the mouse left and right.
| | 02:59 | You can also change the Playback Speed,
that would make it slower 0.5, and if I
| | 03:07 | put it at 5 you can see it's a lot faster.
I am going to set it back to 1.
| | 03:15 | This time let's select Stop before
deselecting them, and now we no longer have
| | 03:20 | particles cluttering the Scene view.
| | 03:23 | We usually have two types of
particles in a scene, those that are happening
| | 03:27 | throughout, like a fountain and those
that are instantiated during runtime and
| | 03:32 | have short life spans, like an explosion.
| | 03:35 | In the Scene view we can you use Stop and
Simulate to see how the finite life spans look.
| | 03:41 | Let's select the Particle system again
and in the Inspector uncheck Looping.
| | 03:53 | Click Stop then Simulate, click Stop.
| | 04:01 | As you can see, the particles were emitted
for the first five seconds, then stopped.
| | 04:08 | Let's look at the basic parameters.
| | 04:10 | Duration is the amount of time the
particles emit or the length of the cycle
| | 04:14 | that repeats when it's set to loop.
| | 04:16 | Prewarm starts the particles fully into
the cycle so that things like waterfalls
| | 04:21 | and chimney smoke are already
going when your game starts.
| | 04:25 | Let's check Looping again,
and Prewarm, and then Simulate.
| | 04:33 | This time the particles are
already underway. Let's click Stop.
| | 04:40 | Start Delay is a built in
pause before they start up.
| | 04:43 | This is handy when you're combining
several Particle systems to make complex
| | 04:47 | particle effects, Unity's term
for several that are used together.
| | 04:52 | In an explosion for an example, you
wouldn't want the smoke to start until the
| | 04:56 | pyrotechnics were nearly finished.
| | 04:58 | Start Lifetime along with the next four
parameters let us add variation through
| | 05:03 | presets in the modules below this section,
and also through the little right-hand dropdowns.
| | 05:09 | At Start Color, we can affect the color
of the particles on a wholesale basis.
| | 05:14 | Using gradient here would cycle the colors
over the duration, not the particle lifetime.
| | 05:20 | Next we can adjust the
gravity with the Gravity Modifier,
| | 05:23 | this adjusts the values
already set in the Physics Manager.
| | 05:27 | The Physics Manager can be found in
Edit > Project Settings > Physics.
| | 05:31 | Let's add more gravity,
about 0.5, and click Simulate.
| | 05:42 | Then we'll try running it up
and down to see the difference.
| | 05:50 | Let's go ahead and stop and set it back to zero.
| | 05:58 | Inherent Velocity will determine what
happens when the emitter is transformed.
| | 06:02 | At zero the particles ignore the transform.
| | 06:05 | We can't see this one in Edit mode,
we'd need to add a script to transform it
| | 06:10 | and observe it during real Play mode.
| | 06:12 | If you opt to try this one out on
your own, be sure to switch to the local
| | 06:16 | coordinate system, the results
will probably make a lot more sense.
| | 06:20 | Simulation Space determines whether the
particles are emitted in local space or world space.
| | 06:26 | For something that moves around, like
water from a fire hose, you'd want to
| | 06:31 | use local space, Play On Awake is just
like the audio, the particles start up
| | 06:36 | as soon as the scene starts, or if they're on
a Prefab as soon as the object is instantiated.
| | 06:43 | Max Particles limits the number of live
particles we will have on screen at any time.
| | 06:48 | When reached, the Particle system will quit
emitting until the old ones start dying off.
| | 06:53 | In the next video we'll look at the modules
beneath these settings to see what they offer.
| | Collapse this transcript |
| Refining particle systems| 00:00 | In the Particles Test scene, let's select
the Particle system object and then click Stop.
| | 00:08 | Before we move on to the rollout
section we really ought to take a peek at some
| | 00:13 | of the options available to some of
the regular Particle system parameters.
| | 00:16 | Let's click on a few of the down arrows.
| | 00:22 | With numbers we get the choice of
Constant, Curve, Random Between Two Constants,
| | 00:28 | and Random Between Two Curves.
| | 00:31 | With Colors we get Color, Gradient,
Random Between Two Colors, and Random
| | 00:38 | Between Two Gradients.
We'll be testing Gradient a little later on.
| | 00:42 | The rollout section of the Particle
system contains modules that give you more
| | 00:46 | control, especially over
the individual particles.
| | 00:52 | Of the three that are already turned
on, Emission and Renderer are mandatory.
| | 00:57 | We can turn the modules off and on
with the checkboxes, but need to open and
| | 01:01 | close the rollouts by clicking on the bars.
| | 01:04 | Under Emission we have rate, how many
particles per second or per distance are emitted.
| | 01:11 | First, let's just emit extra at the
specified time or times in the duration.
| | 01:16 | We can add a remove Bursts with the plus button.
Let's look at Shape next.
| | 01:24 | There are several different emitter
types to choose from, including the option
| | 01:28 | to limit from meshes.
| | 01:31 | The next several modules alter the
particles on an individual basis.
| | 01:35 | Velocity over time lets you affect the
direction of the particles in world or local space.
| | 01:41 | Limit Velocity over time allows
you to dampen or slow the particles.
| | 01:45 | Before we look at Color Over Lifetime,
and we are going to need to turn it
| | 01:53 | on, we want make sure that the start color is
just white, so we're good to go on this one.
| | 02:00 | Color over Lifetime lets us affect the
color on a per particle basis rather than
| | 02:05 | Particle system duration,
let's go ahead and try it.
| | 02:09 | Let's click the down arrow, it
defaults to Gradient, so let's click on the
| | 02:14 | Gradient and give it a try.
| | 02:18 | In the Gradient editor the ramp color
picker works like this, the top markers
| | 02:23 | are for opacity and the bottom are for color.
| | 02:26 | Click above or below the
color bar to create a new marker.
| | 02:31 | The marker will inherit the color
or opacity of the initial position.
| | 02:35 | You can delete a marker by selecting it
and then pressing Delete, and I'll hit
| | 02:39 | my Delete key, and that one is gone.
| | 02:42 | To change the color of marker we can
double-click on it, and it opens up the
| | 02:47 | regular color picker.
| | 02:49 | And if I change the color
we can see the gradient.
| | 02:55 | For the opacity we can click on a
marker here and these are set by number.
| | 03:06 | Let's click simulate and see what it looks like.
| | 03:11 | And I'll zoom in a little bit more,
I'll adjust my window size so we can get a
| | 03:16 | better look at it, and we can stop.
| | 03:21 | For Size over Lifetime we need to open
the Particle system editor to see the curve.
| | 03:28 | The button for that is up near the top.
| | 03:30 | If you click the button we'll see the
curve in the editor, and we can go ahead
| | 03:36 | and close the editor.
| | 03:37 | We'll get lots more practice with the
basic curve editor functionality when we
| | 03:42 | do some Unity keyframe animation, and
let's go ahead and stop the particles.
| | 03:46 | Back to our rollouts, Collision lets
us use planes as deflectors, coupled
| | 03:54 | with bounce and other parameters, this one
can come in handy for things like rain effects.
| | 03:58 | Submitters lets you spawn more
particles on death or collision using
| | 04:03 | other Particle systems.
| | 04:05 | An example would be fireworks were the sparks
flyout and explode into individual fireworks themselves.
| | 04:11 | Texture sheet lets you cycle the
particles through different images on a texture
| | 04:15 | sheet to have animated images on your particles.
| | 04:18 | The Angrybots demo scene has an
excellent example of this with the ripples on
| | 04:22 | the outside raining terrace areas.
| | 04:25 | And finally, we get down to the
Render module. Let's open this one up.
| | 04:31 | From here you can select the type
of particles you want, the default is
| | 04:34 | Billboard or facing planes.
| | 04:37 | Before you test out the last
choice, Mesh, you will want to turn the
| | 04:41 | Max particles down.
| | 04:42 | You can also set the
material for your particles,
| | 04:45 | Unity has several particle specific shaders
that are great for many typical use cases.
| | 04:52 | The Sorting options will help with
opacity draw order issues and the Sorting
| | 04:57 | Fudge will help withdraw order
issues between different Particle systems.
| | 05:01 | The doc say Cast and Receive shadows
is only for opaque materials, so it's
| | 05:06 | usually safe to leave on, if in
doubt uncheck them to save resources.
| | 05:11 | And finally, we have Max Particle
Size as the player gets closer to the
| | 05:15 | particles this is the largest they can scale to.
This is a screen percent 0 to 1.
| | 05:21 | Plan on lots of tests to get the look
and functionality you're looking for.
| | 05:25 | In the next several videos we'll make
use of some of the Particle system Prefabs.
| | Collapse this transcript |
| Combining particle systems| 00:00 | While the power and versatility of
Unity's particle system is impressive
| | 00:04 | thing thought of making your own Particle
systems from scratch can still be intimidating.
| | 00:08 | Fortunately there are several great
Prefabs waiting for us in the Particles
| | 00:12 | Package we imported in the last video.
| | 00:14 | Unfortunately, at the time of this video,
most of the legacy types and are harder to tweak.
| | 00:20 | A lot of the parameters were the same,
but they don't have the playback controls
| | 00:24 | in the viewport and they show the
wires in the Scene view when selected.
| | 00:28 | Unless you select the Parent Game
Object, and then you can't edit them.
| | 00:32 | So until all of the Legacy Particle
system Prefabs have been replaced with the
| | 00:36 | newer Shuriken type it would be
useful to know what some of the legacy
| | 00:40 | parameters equate to.
| | 00:42 | Let's open the Standard Assets folder,
and the Particles folder, and then the Dust
| | 00:51 | folder, let's select Dust Storm.
This is one of the Legacy Particles.
| | 01:00 | The Legacy Particles energy equals
particle life, One Shot means no looping and
| | 01:07 | Size Grow means size over time.
| | 01:13 | For Auto Destruct there is no
equivalent, and it needs to be scripted.
| | 01:17 | Let's check out some other Prefabs.
| | 01:20 | From the Fire folder, let's select
Flame and drag it into the Scene viewport.
| | 01:30 | And I'm going to zoom in on it. Let's
double-click to focus in on it and open
| | 01:38 | the Game Object and select
each of the objects individually.
| | 01:43 | Now we can see we need to
zoom out a bit to see it.
| | 01:49 | So this one has an InnerCore particle
system, a light source, which is an actual
| | 01:55 | light if we look in the Inspector,
| | 01:59 | an outer core, and a smoke. If I zoom
out you'll see that it starts getting
| | 02:06 | darker as it goes up higher.
| | 02:08 | Let's see if we can make an
updated version of the Flame Prefab.
| | 02:12 | You probably don't want to watch me set
each new particle system up to match the
| | 02:16 | Legacy particles, so I've made
replacements available as Unity packages.
| | 02:21 | Let's deselect our current object,
let's use import package to get InnerCore,
| | 02:27 | OuterCore, and smoke from
this chapter's exercise files.
| | 02:31 | Import Package > Custom Package in the
Assets folder, select InnerCore and Open,
| | 02:42 | right-click again, Import > Custom
Package, Assets > Outer Core, and one more time
| | 02:59 | Import Package > Custom
Package > Assets and Smoke.
| | 03:12 | Let's tidy up our Project view,
so we can find our new objects.
| | 03:16 | To start I'm going to drag my
three objects into the Prefabs folder,
| | 03:23 | InnerCore_S, OuterCore_S, and Smoke_S.
| | 03:31 | And now I want to go ahead and
drag them into the hierarchy panel.
| | 03:39 | This one, this one, and the Smoke.
| | 03:43 | Now that we have our three base
particle systems and they are in the
| | 03:47 | Hierarchy view, let's put them together into a
particle effect so we can work on them together.
| | 03:52 | The doc say that all must be parented
to the same object, but what they don't
| | 03:56 | say is that the parent must also
have a particle component on it.
| | 04:00 | So in the Hierarchy view, let's
drag OuterCore_S and Smoke_S onto
| | 04:06 | the InnerCore_S object.
| | 04:09 | So OuterCore on to
InnerCore and Smoke on to InnerCore.
| | 04:15 | And now, let's double-click
InnerCore_S to find in the scene view.
| | 04:23 | And I'll zoom in a little bit, and it looks
like we need to rotate it -90 degrees on the X.
| | 04:36 | There we go, that's much better.
| | 04:38 | Now we can open them in
the Particle system editor.
| | 04:40 | We'll select InnerCore_S, if it isn't
already, and we'll open the editor.
| | 04:47 | It looks like we'll need to drag the side
panel over to see our three Particle systems.
| | 04:52 | This enables us to tweak them
individually while watching the full effect.
| | 04:56 | Let's go ahead and close the
editor and deselect the particles.
| | 04:59 | Now that the fire effect looks pretty
good we can sneak the light source from
| | 05:04 | the Legacy Prefab, drag it out of its
parent, continue, and I'm going to use
| | 05:14 | Move to view to get it
close to our particle system.
| | 05:21 | I should probably double-click to
focus on the InnerCore and be a little more
| | 05:28 | exact when I move it to view.
Drop it down, and there we go.
| | 05:34 | I'll drag it into the other
particle system parent, and we are ready to
| | 05:39 | create our new Prefab.
| | 05:42 | Let's right-click on Prefab and
create new Prefab, and we'll call this one
| | 05:50 | Flame_S and drag our new
Particle system Effect into it.
| | 06:01 | Let's go ahead and save the scene.
| | 06:07 | Now we are going to go ahead and open
up the main level again, and let's focus
| | 06:12 | in on the bridge plank.
That's in the structures for scene section.
| | 06:20 | Give myself a little bit more real
estate here, use Alt and left mouse
| | 06:26 | button, and now we can bring our Flame_S
into the scene to make it much more interesting.
| | 06:38 | You can see the nice addition the
light source makes, feel free to click Play
| | 06:42 | and check out the new stuff in the Scene view.
| | 06:45 | Let's create an empty game
object and name it Flames Group.
| | 06:48 | That way we can keep all of our flame
objects together in the Hierarchy view.
| | 06:52 | GameObject > Create Empty, and we'll
name our New GameObject, Flames Group.
| | 07:01 | And now, I'll resize a little bit here, and I'll
drag all of my Flame_S objects into the Flames Group.
| | Collapse this transcript |
| Upgrading weapons| 00:00 | Now that the compound area is starting to
look pretty good, we may need to get more
| | 00:04 | serious about our weaponry.
| | 00:06 | Lobbing pseudo-cannonballs at
stuff can only take us so far.
| | 00:09 | With all the particle system Prefabs at hand,
it's time to think about improving our cannonball's
| | 00:15 | functionality, and for that
we can start with explosions.
| | 00:18 | We know that on collision returns a bunch
of information besides just the hit object.
| | 00:24 | So let's make use of it to give us a
place to instantiate an explosion.
| | 00:28 | Let's start by opening the ProjectileHandler
script, that's the one that already has the
| | 00:33 | OnCollisionEnter function in it.
| | 00:35 | We'll be using an Explosion Prefab, so the
first thing to do is make a variable to hold
| | 00:40 | it at the top of the script.
Var Explosion of type GameObject.
| | 00:47 | At the top of OnCollisionEnter we'll need
to add a couple of variables to store the
| | 00:51 | exact location of the hit.
| | 00:54 | We also need to know the orientation of the
face or triangles' face normal, so we can point
| | 00:58 | the special effects that local
direction at the hit location.
| | 01:02 | I'm going to copy the next couple of lines
from the snippets file, then paste it in.
| | 01:07 | Exercise Files07/07-07Code_Snippets, and I'm
going to take these lines, right-click, and
| | 01:22 | copy, back to the Script editor, and
I'm going to paste them right in here.
| | 01:30 | And highlight them, right-click,
we'll have an Indent Selection.
| | 01:34 | I've also included comments on these
since they are a little bit confusing.
| | 01:40 | For our contact line, remember
those brackets? That means an array.
| | 01:45 | If you think about it, the projectile hits several times
before being destroyed as we heard when we added sound.
| | 01:51 | So the Collision class is
storing all of those hits in an array.
| | 01:55 | We just want the first one, which is Element 0, and we've
added a comment to let us know what that's doing.
| | 02:02 | The rotation line is a
little bit more complicated.
| | 02:06 | We are used to thinking of rotation in terms of
X, Y, and Z axis, but the Euler Math involved
| | 02:12 | has a few problems.
It's prone to gimbal lock.
| | 02:15 | If you haven't heard that term before, the
easiest way to explain it is to picture yourself
| | 02:19 | standing and watching an airplane flying
towards you, as it passes directly overhead, you will
| | 02:25 | need to turn 180 degrees to
watch it as it flies away from you.
| | 02:29 | Euler Math can also give different results
depending on the order that the axes are evaluated.
| | 02:35 | Quaternion math is much better
mathematically but less intuitive for us to work with.
| | 02:40 | It only needs to know which
direction it needs end up facing.
| | 02:44 | Unity uses both and devotes a lot of
functions to converting from one type to the other.
| | 02:49 | Now if that sounds confusing, don't worry.
| | 02:52 | The bottom line on this one is that it gets
the direction of the hit face's normal, and
| | 02:56 | the normal is an imaginary line perpendicular to
that face, and we've added a comment for that as well.
| | 03:03 | And now inside the if clause, we can tell
it where to instantiate the explosion, and
| | 03:09 | I'm going to copy that one
from the Snippets file as well.
| | 03:13 | Copy it, and we'll paste this line
underneath the SendMessage line.
| | 03:22 | The only mildly tricky thing about this line
is the contact.point, since the location is
| | 03:28 | a three-part affair, X, Y, and Z, the point property
of contact delivers it in one shot, a vector three type.
| | 03:35 | And finally, we need to copy the audio line
into the if and the else statements, so it
| | 03:41 | will play before the object is destroyed.
| | 03:44 | I am going to cut and place one of them here, give
myself a space and the other one I'll put in the else.
| | 03:56 | In the if statement, I need to make sure that
the audio plays before the object is destroyed.
| | 04:02 | So I am going to add a yield statement here.
| | 04:05 | Yield is one frame before
it goes ahead and destroys.
| | 04:08 | In the else statement, this one is going
for five seconds before it gets destroyed, so
| | 04:14 | we don't have to worry about it.
| | 04:15 | Okay, let's save the script
and get back to the editor.
| | 04:20 | Since this script lives on Projectiles, we'll
need to locate our original cannonball Prefab
| | 04:25 | in the project view, so we
can assign the explosion to it.
| | 04:29 | And Prefabs, here is our Cannonball, and in
our ProjectileHandler script, here is our
| | 04:39 | field for the explosion.
| | 04:41 | We're going to get a Prefab from the Standard
Assets folder, under Particles, under Legacy
| | 04:51 | Particles, we're going to drag the Small Explosion
into the Explosion field on our ProjectileHandler.
| | 04:59 | We should be ready to
click Play and try it out.
| | 05:02 | I'm going to drag my window open
a little further and click Play.
| | 05:10 | If we fire using our left mouse button,
we get an explosion, Exit Play mode.
| | 05:20 | Well, that worked, but let's
try a different explosion.
| | 05:24 | I am going to scroll down and
then try just the regular explosion.
| | 05:33 | Click play, and fire again, much better.
| | 05:41 | Let's Exit Play mode.
| | 05:43 | Before we move on, let's do a
little bit of housekeeping.
| | 05:46 | In an earlier video we put a script on one
of the barricades that senses the presence
| | 05:51 | of, well, any object that intersects it.
| | 05:55 | Let's select the Barricade Mid
and remove the Trigger Test script.
| | 06:02 | From Structures Barrier 2, let's select Barricade Mid
and right-click and Remove Component. Okay, we're set to go.
| | Collapse this transcript |
| Exploring water effects| 00:00 | We've made the area beyond the nature
zone more interesting with fire, so now
| | 00:04 | let's go back the other direction
and add water to the nature area.
| | 00:08 | We're going to bring in the Water
Packages for pro and basic, so we can check
| | 00:12 | out the differences.
| | 00:14 | The pro version makes use of reflection and
refraction for some spectacular results.
| | 00:19 | The basic version is pretty sad, so
in a later video we'll also look into a
| | 00:23 | better version of it in case you want
to lower resource using version of water.
| | 00:28 | Let's import both the Water Packages,
right-click, Import Package, and we'll
| | 00:36 | start with Water Basic, Import.
| | 00:43 | And we'll repeat Import
Package, Water (Pro Only), Import.
| | 00:53 | We'll find them both in the
Standard Assets folder near the bottom.
| | 01:01 | Let's start by focusing in on the
Fountain and move the first-person controller
| | 01:05 | to it using Move To View.
| | 01:10 | So we select the first-person controller,
GameObject > Move To View, and we'll
| | 01:17 | double-click on him to zoom in closer.
| | 01:19 | I am going to use my Alt key, spin
around a little bit, and then we'll move him
| | 01:29 | down out of the way.
| | 01:34 | This way we will be able to
see the view when we click Play.
| | 01:37 | It will be a lot easier to see what
we've got if we go ahead and select the
| | 01:41 | Terrain and turn off the Trees.
So let's do that now.
| | 01:47 | In Settings I'm going to
uncheck Draw, and there much easier.
| | 01:54 | I want to rotate it a little bit.
| | 01:59 | From Standard Assets, Water folder,
let's drag in Daylight Simple Water, and
| | 02:08 | maybe move it up slightly.
| | 02:14 | It's not terribly inspiring. Let's
delete it and see how much better we can
| | 02:19 | do with the Pro Water.
| | 02:21 | So I'll right-click and delete it and
from the Water (Pro Only) folder, I'm
| | 02:31 | going to drag in Daylight Water.
And once again I'll position it a little better.
| | 02:39 | That's more like it.
| | 02:41 | The downside to this one is
it tends to be a resource hog.
| | 02:46 | In the Inspector we can see that there
are tons of things you can adjust, but
| | 02:50 | we'll just stick with the defaults.
| | 02:51 | The waves in both water Prefabs use world
scale so shrinking the meshes won't affect them.
| | 02:57 | Let's scale our Water down to fit the fountain.
| | 03:06 | And I'll tip my view a little so I
can get my water a little more centered.
| | 03:15 | Right now, our Terrain fills up the
fountain where our water should be.
| | 03:19 | Let's deactivate our water for a
minute at the top of the Inspector.
| | 03:23 | In the Terrain editor we're going to
need to go ahead and make a hole in the
| | 03:26 | Terrain at the fountain
until we can see the bottom.
| | 03:30 | So I'll select our Terrain, go to our
Raise/Lower the Terrain height, choose a
| | 03:37 | small size, I am going to try about 8.
| | 03:44 | And since we're lowering the Terrain we
need to remember to hold the Shift button.
| | 03:51 | And I should probably rotate my
view to make sure I've got it all.
| | 03:57 | While we've got the Terrain editor open, we
are also going to need a hole for a waterfall.
| | 04:02 | And that will be off to the left here,
so I'm going to increase my Brush Size
| | 04:07 | to about 20, hold my Shift again and
just make a bit of a hole, it doesn't
| | 04:17 | matter how deep it is.
| | 04:19 | Now we can activate our Water again,
and we're going to add a water fountain.
| | 04:27 | So from the Standard Assets folder >
Particle systems > Water, let's choose
| | 04:35 | Water Fountain, and we can drag it
in and drop it right about there.
| | 04:42 | May need a little adjustment, so I am
going to move it over a little bit, wait
| | 04:49 | for the particles to catch up.
Use my Alt to look at the view, and there we go.
| | 04:56 | The Pro Water doesn't come with
Colliders, so if you've already jumped into the
| | 05:00 | Fountain and gotten stuck,
feel free to add a Collider to it.
| | 05:04 | Let's click Play and
watch the results, and Exit.
| | 05:14 | Next we are going to drag
in the Waterfall Prefab.
| | 05:17 | It's the same place as the Water Fountain.
| | 05:19 | So I am going to zoom back a little bit,
and we want to position it up on the cliffs.
| | 05:34 | So from Water > Waterfall, and
we'll drop it right about here.
| | 05:43 | We need to rotate it and maybe
position it a little bit and then the biggest
| | 05:51 | thing we need to change on it
is the life of the particles.
| | 05:55 | Coming from that high up we need a longer life.
In the legacy particle life equates to energy.
| | 06:02 | We'll set our Min and Max
Energy to about 3 for now.
| | 06:10 | We'll add a lower resource using water
later on when we get to textures, but for
| | 06:14 | now, let's pretend there is a
surface there, so we can use one last water
| | 06:18 | Prefab, and that is Water Surface Splash.
| | 06:22 | Located in the Standard Assets >
Particle systems folder > Water, and we'll drag
| | 06:28 | it into the scene beneath the waterfall.
| | 06:36 | Zoom in, looks like I need to
align it to the waterfall first.
| | 06:44 | So I'll double-click my Waterfall, and
then I'll select my Water Surface and use
| | 06:53 | Move To View, and now I should be able
to move it down and inward, and now if I
| | 07:04 | zoom in on it, we'll get to see what it does.
And there we have it, Water Surface.
| | 07:14 | You'll probably want to do
some scaling on this one.
| | 07:17 | Let's set the Min Size to 3 and the
Max Size to 4, and we start to see
| | 07:29 | the effect much better.
| | 07:31 | Okay, let's click Play
and see what it looks like.
| | 07:39 | There is our Water Fountain, and if we
drive over to here we can see the start
| | 07:44 | of our Waterfall, and let's exit Play mode.
| | 07:49 | The four water type Prefabs
make a nice addition to our scene.
| | Collapse this transcript |
|
|
8. Using Imported AssetsImporting static objects| 00:00 | We've had a peak at dealing with
imported assets in Unity in earlier chapters.
| | 00:04 | Now let's dig a little deeper and see
what goes on with the entire process.
| | 00:08 | First off, Unity supports files from
several popular 3D applications, 3ds Max,
| | 00:14 | Maya, Blender, Cinema 4D, Cheetah3D, and Modo.
| | 00:20 | It also reads, .FBX, .DAE,
.3DS, .DXF and .OBJ files.
| | 00:28 | If your application or application's
file type is not directly supported,
| | 00:32 | chances are there's an FBX
Exporter out there for it.
| | 00:36 | The caveat to the supported file
types is that many of the original
| | 00:40 | applications must be installed and
licensed on the computer in order for Unity
| | 00:45 | to read their files.
| | 00:46 | Once the file has been saved in the
Unity folder, the nice thing is that anytime
| | 00:51 | you make changes to that file then return to
Unity, the changes are automatically updated.
| | 00:57 | The not so nice thing is that unless
you're using a versioning software such as
| | 01:02 | SVN or Unity's own Asset Server, you
won't have any earlier versions to revert
| | 01:07 | to unless you manually save them somewhere else.
| | 01:10 | Unity recommends saving the
applications file directly to your Assets folder.
| | 01:15 | Internally though, it converts all
supported file types to FBX format.
| | 01:20 | For that reason I prefer the extra
step of exporting an FBX file to my Unity
| | 01:24 | project and keeping my
application files separate.
| | 01:28 | This way I know anyone will be able to
open the project without having the 3D
| | 01:32 | app installed, and I also have all of
my incremented versions in case I need
| | 01:37 | to revisit something.
So what exactly does Unity support?
| | 01:41 | Well, if FBX supports it
Unity probably supports it.
| | 01:46 | All nodes with position, rotation and scale.
So objects, groups, hierarchies, or linkages.
| | 01:51 | Meshes with vertex colors, normals,
and one or two sets of UVs, no more.
| | 01:57 | Materials with a diffuse color and texture,
and it also supports multiple materials per mesh.
| | 02:05 | For animation, simple transform
animations--and we'll cover imported animations
| | 02:10 | in a later chapter--and bone based animations.
| | 02:14 | Currently there is no native support for
vertex animations such as Morph targets.
| | 02:19 | If you check the manual for how do I
import objects from my 3D app, you can find
| | 02:24 | more information for your specific application.
So let's bring in some more assets.
| | 02:29 | Theoretically you should be able to bring your
meshes and your textures in at the same time.
| | 02:34 | Unity needs to generate its own
version of the materials so it must have
| | 02:38 | the textures at hand, to ensure that I
usually bring my textures in before the meshes.
| | 02:44 | It doesn't matter where in the Assets
folder you drop them, you can always move
| | 02:48 | them later, but only from inside Unity.
| | 02:51 | So let's start by selecting all of
the compound extras textures from the
| | 02:55 | exercise files folder, and then we'll be
pasting them into the Assets folder via
| | 03:00 | the operating system.
| | 03:03 | Exercise Files08/08-01/Assets,
and I'm going to open my CompoundExtrasTextures.
| | 03:15 | I am going to switchover to Details,
so I can easily use shift to select them
| | 03:22 | all, right-click and copy them.
| | 03:28 | And now I'm going to go back and
open my UnitySampler project, the Assets
| | 03:36 | folder, and I'm going to paste them into
my Textures folder that I already have.
| | 03:43 | And we'll open it up just
to make sure they've arrived.
| | 03:50 | And we've got lots of new textures now.
| | 03:52 | Now we can bring in the FBX file,
CompoundExtras.FBX, and we can do that in several ways.
| | 03:59 | We could bring it in through the
operating system like we just did for the
| | 04:02 | textures or we can just use
Assets > Import New Assets.
| | 04:07 | We could also drag it directly into the
Project view from the operating system.
| | 04:11 | I'm going to select the Imported Assets
folder and then use the second method.
| | 04:16 | Here is our Imported Assets,
right-click and Import New Asset.
| | 04:28 | We want to make sure we get to the
right folder Exercise Files08/08-01/Assets,
| | 04:41 | and here is our CompoundExtras
FBX file, and Import.
| | 04:48 | And now in our Imported Assets
folder, we have our CompoundExtras.
| | 04:52 | We'll need to get a good look at what
we've got, so let's start by moving our
| | 04:56 | first-person controller into the compound area.
| | 05:04 | Select him and move him, and we want him
right about there, and I'll switch over
| | 05:13 | to a Perspective view and double-click.
We need to put him down on the ground.
| | 05:23 | And now he should have a pretty good
view of the assets when we bring them in.
| | 05:29 | So now, let's bring the CompoundExtras
from the Project view into our compound area.
| | 05:43 | And maybe I'll bring my first-
person controller a little closer.
| | 05:49 | Let's click Play and drive around and see them.
| | 05:54 | Using my W A S D I go here, and I can
check and see what else I've got here, and
| | 06:04 | we can exit Play mode.
| | 06:06 | The first thing we want to check
after importing assets is the scale.
| | 06:10 | So let's start by selecting the
CompoundExtras in the Project view and
| | 06:16 | looking at the Inspector.
| | 06:19 | Right now we see a Scale Factor of 0.01,
and it seems about right for our new assets.
| | 06:25 | I made these objects in 3ds Max.
Max objects tend to come in huge.
| | 06:30 | I exported my objects as FBX, so
they would be application independent.
| | 06:33 | But if you're using Max files directly
you'll see an option to use file units.
| | 06:39 | This lets you use one Max
unit equal to one Unity unit.
| | 06:43 | Let's try changing the Scale Factor to 0.005.
| | 06:49 | Whenever we change a parameter in the
import settings we need to press Apply,
| | 06:53 | and that is down near the bottom.
Click Apply, we can that our objects shrunk.
| | 07:01 | Let's set it back to 1, 0.01 and click
Apply again, and now they look right again.
| | 07:11 | Unity scaling system is very good.
| | 07:14 | If you're using assets from different
sources it's no problem to set the scale
| | 07:18 | for each import individually.
The next on our list,
| | 07:24 | Mesh Compression may need to be
used if the meshes you import were not
| | 07:28 | modeled for real time.
| | 07:29 | But check the results to make
sure that the model still looks okay.
| | 07:33 | Models that have had serious poly
reduction done on them might benefit
| | 07:37 | from optimized mesh.
| | 07:39 | It renumbers the polygons
internally for quicker rendering.
| | 07:42 | If your mesh looks neat, clean, and
orderly, it's probably okay as is.
| | 07:46 | The next check box,
Generate Colliders, is important.
| | 07:50 | It will generate mesh colliders on all
objects in the selected asset collection.
| | 07:55 | For the Structures Assets
it was extremely useful.
| | 07:58 | For the CompoundExtras we may want to
exchange several of the mesh colliders
| | 08:02 | for Primitive Colliders later, but
let's go ahead and check it now and of
| | 08:07 | course, click Apply.
| | 08:14 | The next to deal with UVs are
texture mapping coordinates.
| | 08:18 | Unity only supports two UV channels.
| | 08:21 | The first is used for the diffused
texture and the second for light maps.
| | 08:25 | Diffused UVs often have chaotic looking
UVs to allow tiling and matching up the
| | 08:30 | textures with the building's stone texture.
| | 08:33 | It allows you to tile a high-resolution map
across a lot of surfaces and retain detail.
| | 08:38 | Light maps however must be normalized.
| | 08:41 | The UVs all must be contained within
the boundary of the texture and must not
| | 08:45 | overlap or share the same spot on the map.
| | 08:48 | If your diffused UVs are not normalized, the
same UVs can be used for the light mapping.
| | 08:53 | Otherwise, a second set will either
need to be provided or you can have Unity
| | 08:58 | generate them for you
with Generate Light Map UVs.
| | 09:02 | If for some reason the two UVs come and
assign to the wrong numbers, you can use
| | 09:06 | Swap UVs to set them right.
| | 09:08 | Most of the objects I've provided come in
with the second set of UVs already made.
| | 09:13 | If you don't plan on baking light in
Unity, you don't need to worry about the
| | 09:17 | second UV channel at all.
| | 09:19 | If your object does not import looking
quite right, you may need to fuss with
| | 09:22 | normals and tangents.
| | 09:24 | Some formats such as .OBJ do not store
smoothing angle data and may need to be
| | 09:30 | manually set up, see the
docs if that's the case.
| | 09:33 | The next section is for Materials.
| | 09:35 | Unity does not import
materials from your modeling app.
| | 09:40 | It finds the diffused texture for each
material on the mesh, but that's as far as it goes.
| | 09:45 | With that texture it generates a
generic material with the diffused shader.
| | 09:50 | As a default for naming that material,
it uses the material's diffused texture
| | 09:54 | name, good news for those of us
who forget to name our materials.
| | 09:58 | So what happens if your objects
material doesn't have a diffused texture?
| | 10:02 | Well, then it gets assigned the
name of the original material.
| | 10:05 | If you prefer that it always named
after the material, you can change it in the
| | 10:09 | Material naming field.
| | 10:11 | For material search there's a
nice description of what's happening.
| | 10:15 | But as I mentioned earlier the safest
thing to do is make sure that all your
| | 10:18 | textures are imported
before you import the meshes.
| | 10:22 | The reason I stress this is that if
you update the asset by re-importing, and
| | 10:26 | you don't use the generic material
assigned on the import, you'll have to
| | 10:30 | reassign the ones you replaced them with.
| | 10:33 | Under Animations > Generation, select
Don't Import, and I'll just do that right now.
| | 10:40 | We're going to select Don't
Import since none of these objects have
| | 10:44 | animations on them.
| | 10:45 | And, having changed something, we
need to go down and click Apply.
| | 10:52 | So a few more things to know
about imported assets in general,
| | 10:55 | you can change the name of the asset
group in the Project view, but the rest of
| | 10:59 | the objects in the file
can't be changed in Unity.
| | 11:02 | Changes to the original file will be
updated as soon as you return to Unity.
| | 11:07 | If you are already using the assets in
a scene, as long as you haven't broken
| | 11:11 | the Prefab, the references to the original
asset file updating should be pretty seamless.
| | 11:16 | As soon as you break the Prefab, by say,
removing something from the group, all
| | 11:22 | bets are off, but you can revert
back to the original if you need to.
| | 11:26 | Let's try removing the rocket.
| | 11:28 | So in the Hierarchy, CompoundExtras, we'll just
drag the Rocket out and put it somewhere else.
| | 11:39 | We get our Losing Prefab warning, and
we are going to say Continue, and since
| | 11:44 | it's no longer referenced
properly, the text turns white.
| | 11:48 | If we rename, say the Crate, and I'll
select it just add a 2 to the end, and then
| | 11:55 | Revert the entire
CompoundExtras, watch what happens.
| | 11:59 | And Revert is up here in the same
place that we usually have our Prefab area.
| | 12:04 | So we'll say Revert and look what happens.
Our rocket is put back and our Crate is renamed.
| | 12:11 | What about the first rocket we removed?
Well, let's check and see, and there it is,
| | 12:17 | it's right where we left it.
| | 12:19 | So this gives us a way to only use
selected objects in a larger group
| | 12:22 | of imported assets.
| | 12:24 | Let's go ahead and delete the
extra rocket, right-click, Delete.
| | 12:28 | We'll take a closer look at how Unity handles
textures and materials for our imported objects next.
| | Collapse this transcript |
| Manipulating textures| 00:00 | Before we can start tweaking the
imported materials we need to investigate
| | 00:04 | textures and how they are handled in Unity.
| | 00:07 | Let's start by looking at
the Cardboard Box object.
| | 00:10 | I'm going to move the CompoundExtras
back a little bit so it will be in the sun,
| | 00:15 | and I'm going to zoom in as well.
| | 00:20 | So opening my CompoundExtras, I'm
going to double-click the Cardboard Box and
| | 00:28 | get a nice view of it.
| | 00:29 | When we select it we see its
material at the bottom of the Inspector.
| | 00:36 | Let's click on the thumbnail, and that
locates the texture in the Project view,
| | 00:42 | and we'll go ahead and select it from there.
| | 00:45 | In the Inspector we can see a preview
of the texture as well as its various properties.
| | 00:50 | Unity, let's us tweak several of them.
| | 00:54 | Selecting the texture type will bring
up the appropriate parameters, it also
| | 00:58 | sets many properties
according to the type selected.
| | 01:01 | If you're feeling like a game texture guru you
can select Advanced and set everything manually.
| | 01:07 | The others are nothing more than
presets, we'll stick with texture.
| | 01:11 | The next option is Alpha from
Grayscale, before we try this let's check out
| | 01:15 | the Preview window.
| | 01:17 | This texture was a simple
JPEG and had no Alpha channel.
| | 01:21 | Now let's check Alpha from Grayscale and Apply.
| | 01:29 | We can now toggle between the
RGB version and the Alpha version.
| | 01:34 | Obviously it doesn't make much sense
for this texture, so let's uncheck it
| | 01:38 | and click Apply again.
| | 01:42 | The next parameter is Wrap mode. Let's
select the Sheet-Metal Rusty Object in
| | 01:47 | the Scene view and track
down its texture, Rusty panel.
| | 01:58 | If we change Wrap from Repeat to Clamp
and click Apply, we can see the pixels
| | 02:09 | are stretched across the rest of the object.
| | 02:11 | Let's set it back to
Repeat and click Apply again.
| | 02:16 | Filter mode is how it goes between mipmaps.
| | 02:19 | With mipmapping decreasingly smaller
and blurrier versions are made and stored
| | 02:24 | of the image, then used in the scene
depending on how far away you are from the object.
| | 02:29 | Scrub the slider in the Preview
window to see the various versions.
| | 02:34 | You won't see the actual
size, but they will be base 2.
| | 02:38 | So the first was to 256x256, the next was
128x128 then 64x64, 32x32, 16x16 et cetera.
| | 02:49 | Look at the Sheet Metal from an angle,
the farther away it is the blurry it gets.
| | 02:56 | The default Filter is Bilinear, so
besides getting blurrier as it gets farther
| | 03:00 | away, it also blurs the texture
when the player gets very close.
| | 03:06 | Aniso Level--Aniso is short for
Anisotropic--allows you to increase texture
| | 03:11 | quality when viewing the
texture at a steep angle.
| | 03:14 | If your floor and ground textures
have a lot of artifacting going on, try
| | 03:18 | increasing this, but use it
sparingly it's a resource hog.
| | 03:22 | What's an artifact?
| | 03:23 | Basically something that doesn't
look like it belongs in the render.
| | 03:27 | It may be some odd black pixels, or in
this case, the ground might look sparkly as
| | 03:32 | move through the scene.
| | 03:33 | That's because the renderer can't
decide what color to make each pixel
| | 03:36 | from frame to frame.
| | 03:38 | Aniso Level samples the area and
comes up with a consistent color.
| | 03:42 | And now the last section, let's select our
Rustypanel again and go back to the Inspector.
| | 03:48 | As a default, Unity compresses and
changes the format internally on your
| | 03:52 | textures unless told otherwise.
| | 03:55 | This means you can use
Photoshop layers and files with abandon.
| | 03:59 | Just as with meshes, as soon as you make
changes in your image and save it from
| | 04:04 | your Texture Editing Application,
Unity updates its compressed version.
| | 04:08 | If you're using the Advanced Texture Type,
and let's switch to it for a minute,
| | 04:12 | you can even specify which flavor of
.dds compression you want, otherwise you
| | 04:17 | only get a few choices.
We'll switch back to Texture, and Apply.
| | 04:29 | One of the nicest features is the Max
texture Size and the option to override on
| | 04:33 | a per platform basis.
| | 04:35 | Let's select the Sentry Gun
and track down its texture.
| | 04:43 | I'll click on its thumbnail, bring up
the SentryGun texture, I rendered out my
| | 04:48 | SentryGun texture at 1024x1024, which is
overkill for the size and importance of the object.
| | 04:55 | I can reduce it and see just
how far it can go down with it.
| | 04:59 | Since it's kind of splotchy by
nature, I can take it down pretty far.
| | 05:07 | And I should zoom into my
SentryGun and Apply first.
| | 05:17 | At 64 it starts to look different, so
I'll just set it to 256 and Apply, back to
| | 05:25 | my SentryGun texture, 256 and Apply.
| | 05:33 | And finally, if you want to edit your
texture, double-clicking on it in the
| | 05:37 | Project view or clicking the Open button
will open it in your Default Texture editor.
| | Collapse this transcript |
| Working with materials and shaders| 00:00 | Let's look at materials next.
| | 00:02 | In Unity materials are made of shaders,
so they are handled by the graphics card.
| | 00:08 | Instead of starting with a generic
material and adding components such as bump,
| | 00:12 | shininess, and reflection as needed.
With Unity you need to select the shader
| | 00:18 | that has all of the
components you need to start with.
| | 00:21 | Most of these parameters will require textures.
| | 00:24 | Let's start by looking at the
Cardboard Box material this time.
| | 00:28 | Select the box in the Hierarchy or Scene views.
| | 00:32 | To locate the material in the Project view we
need to click on the Mesh Renderer component.
| | 00:39 | So under Mesh Renderer > Materials, we're going
to look for the material here, 16 - Default.
| | 00:48 | And we'll click on it in the Project view.
| | 00:51 | Now we've got plenty of room to experiment with
it, and we also get a Preview Window at the bottom.
| | 00:58 | You can change the display
shape and lighting there also.
| | 01:05 | The main color is usually going to be a
light silver, this gives you wiggle room
| | 01:09 | in case your texture
looks a bit dark in the scene.
| | 01:12 | Mine looks a bit dark, I'm going to lighten it.
| | 01:18 | And we should also be looking at
the Cardboard Box in the Scene.
| | 01:22 | It also allows you to add a
different color to the texture map.
| | 01:26 | Along with the texture map we can set
the tiling and offset of the texture.
| | 01:31 | I'm going to select my 16 - Default
material again, and let's see what happens
| | 01:36 | if we change our Tiling, 2 and 2.
And the Offset we can change as well.
| | 01:43 | I'll just leave it as is
and set my Tiling back to 1.
| | 01:47 | But we have no means of tweaking
the UVs that the object came in with.
| | 01:51 | So what about Shader choices?
Let's hit the dropdown and check them out.
| | 01:57 | Since Cardboard is smooth but not
shiny, I guess we can leave this one as it is
| | 02:02 | with the default Diffuse Shader.
Let's look at the Crate instead.
| | 02:07 | It's a simple box with a single bitmap.
| | 02:11 | I'll double-click to select it,
and we'll get a better view of it.
| | 02:18 | It's awfully flat looking, even for wood.
Let's check out our options.
| | 02:23 | First we'll find its material, in the Mesh
Renderer, here's its material 01 - Default.
| | 02:29 | We'll hit the Down Arrow again then if
we look up at the top, Bumped Diffuse
| | 02:37 | might be a good choice.
| | 02:39 | It needs a normal map for the bump
map but Unity can create one for us.
| | 02:44 | But it will change the original in the process.
So we need to make a duplicate of it first.
| | 02:49 | Let's find the CrateSide texture, select
it then use Ctrl+D to make a Duplicate,
| | 03:00 | and we'll name this CrateSide bump or bmp.
| | 03:05 | In the Inspector, now we can
change the Texture Type to Normal map.
| | 03:12 | It will create it from a
Grayscale version of the texture.
| | 03:15 | Go ahead and click Apply.
Little goes a long way.
| | 03:20 | So let's bring it down about halfway,
on the Bumpiness, and click Apply again.
| | 03:28 | Now let's get back to our Crate
material and finish setting up our
| | 03:31 | Bumped Diffuse shader.
| | 03:35 | I'll select my Crate again,
get myself to the material, and now I'm
| | 03:45 | going to locate my CrateSide bump
image and drag it into the Normal map.
| | 03:52 | If I lighten the Main Color, we'll be
able to see the results a lot better.
| | 04:00 | Let's take it one step further.
What if we add it some Specular?
| | 04:04 | Let's go up and choose a Bumped
Specular instead of Bumped Diffuse.
| | 04:10 | We can tweak the Shininess and also the
Specular Color for some interesting results.
| | 04:19 | But here's the interesting thing,
notice that our base texture is now RGB, and
| | 04:24 | the gloss is in its Alpha channel.
| | 04:27 | Since the CrateSide texture doesn't
even have an Alpha texture, it gets a
| | 04:31 | full dose of glossiness.
| | 04:33 | But wait you say, wasn't there an
option for that? Yep, there was.
| | 04:37 | So let's go back to our CrateSide texture
and check Alpha from Grayscale and Apply.
| | 04:48 | That definitely tones this one down, even
though it was not a specially made Specular map.
| | 04:53 | So with shaders it's not unusual to
repurpose an Alpha Channel to use for
| | 04:57 | something other than transparency, and
that's a good thing to keep in mind when
| | 05:02 | you're making your textures.
| | 05:03 | As a sort of wrap up, let's remember
that Unity won't automatically assign
| | 05:08 | non-diffuse textures on import.
| | 05:10 | We will need to have them in the
project, so we can finish setting up our
| | 05:14 | materials once the import is finished.
| | Collapse this transcript |
| Handling multiple materials| 00:00 | Let's look at a few more
materials with different shader needs.
| | 00:03 | The Lamp is a good place to start.
| | 00:06 | So in our CompoundExtras, let's select the Lamp
and double-click it, so we get a good view of it.
| | 00:15 | We'll be dealing with the bulb inside it
first, so you may want to tip it upwards.
| | 00:21 | You can see that the lamp has four
different materials over in the Inspector.
| | 00:28 | Normally we try to combine multiple
textures into a single texture map to reduce
| | 00:33 | draw calls, but sometimes there is
no shader available to do the job.
| | 00:38 | Let's see what we need to do for a
couple of these specialty shaders.
| | 00:41 | Starting with the BulbLit
material we'll want to find one of the
| | 00:45 | Self-illuminated shaders.
So let's go up and select.
| | 00:53 | Since my materials don't have proper names,
I'm going to need to figure them out by number.
| | 00:57 | The BulbLit looks like it's going to be
the fourth, so I'm going to double-click
| | 01:04 | on it, and there it is.
| | 01:06 | With this one we're looking
for a self-illuminated shader.
| | 01:10 | So I'm going to click the dropdown and
under Self-Illuminated, I'm just going to
| | 01:16 | choose the simplest, Specular.
| | 01:21 | Most of the Self-Illuminated shaders
use the Alpha channel for glossiness, even
| | 01:26 | the simple diffuse uses an Alpha
channel for the glossiness and needs an extra
| | 01:31 | 8-bit map for the self-illumination.
Which actually makes the shaders in this
| | 01:35 | category quite useful for those
nice walls with light panels in them.
| | 01:39 | Emission determines whether the material
will emit light when using the Lightmapper.
| | 01:44 | Zero is no light will be added.
| | 01:47 | The dock suggests using emissive light
calculated from material should only be
| | 01:51 | used for large dim areas.
| | 01:53 | So our light bulb object should be
accompanied by an actual light object at some
| | 01:59 | point just like our flame Prefab.
| | 02:01 | Okay, let's select the Lamp again,
and look at the Chrome material.
| | 02:07 | Fortunately this one has a name.
| | 02:10 | I'll double-click on it, it is mapped
to the underside of the fixture and needs
| | 02:15 | a shader with reflection.
| | 02:17 | So let's change its shader
to Reflective > Specular.
| | 02:22 | So under Reflective we're
going to choose Specular.
| | 02:27 | Before we even add a map, we can see
there's some self-illumination going on.
| | 02:32 | Toggle off the scene lights in the
Scene view, and adjust the Specular Color and
| | 02:36 | Shininess to affect the highlight.
| | 02:39 | So we'll toggle off the Scene lights,
and now adjust the Shininess, so it makes
| | 02:50 | a nice pseudo-reflective look.
| | 02:52 | For the reflection, Unity expects
a Cubemap, as we can see right here.
| | 02:58 | Even if you have some of your own, they
may not be the same format Unity uses, so
| | 03:02 | we're going to see how to make a quick one next.
| | 03:05 | Cubemaps require six individual maps,
so let's start with something small.
| | 03:10 | For now we're just going to use a
single texture to make the Cubemap.
| | 03:13 | I want my new Cubemap in the
Textures folder, so I'll select the Textures
| | 03:17 | folder, right-click on it and Create > Cubemap.
Let's name it ChromeRef.
| | 03:33 | And there it is waiting for six maps.
We're going to cheat.
| | 03:37 | Let's drag MetalRef_small
texture into each of the slots.
| | 03:42 | Yeah, I know it's a cheat, we're not using
six different maps, but you got the idea now.
| | 03:51 | So now I have something marginally
better than the Unity defaults to load into
| | 03:55 | Chrome materials reflection Cubemap slot.
| | 03:58 | Let's select the Lamp and
load in the new Cubemap.
| | 04:06 | And we can do it right in
the material, and there we go.
| | 04:17 | For the top of the lamp, we can use the
RibbedRadial as a bump map and change
| | 04:21 | the shader to Bumped Specular.
| | 04:24 | Let's see if we can figure out which is
the top, it looks like the lighter gray,
| | 04:33 | so I'm going to guess it's 07.
We'll change its Shader to Bumped Specular.
| | 04:45 | Rather than making the Normal map first,
let's see what happens if we try to
| | 04:48 | use a regular texture.
Let's duplicate the RibbedRadial texture first.
| | 04:55 | In the Textures folder,
RibbedRadial, use Ctrl+D, I'll name this one
| | 05:03 | RibbedRadial bmp, for bump,
and select our Lamp again.
| | 05:17 | Now I'm going to drag my
RibbedRadial bmp into my Normal map.
| | 05:27 | And we get a warning.
| | 05:29 | This texture is not marked as a
normal map. Fix Now? Sure why not.
| | 05:34 | If we click it, and it fixed it nicely.
| | 05:37 | So now that we've seen if you specialty
shaders, you should have a better idea
| | 05:40 | on how to set up your own materials.
| | Collapse this transcript |
| Animating UVs| 00:00 | Now that we've learned more about
textures and materials we are going to fill
| | 00:04 | in the hole over at the waterfall. This time
with a non-proshader and a useful little script.
| | 00:09 | Let's focus in on the water splash
area, I'll double-click on water surface
| | 00:13 | splash in the Hierarchy to locate it,
and then I am going to use my Alt-left mouse
| | 00:18 | button to rotate
the scene and then zoom in.
| | 00:23 | And now we want to create a plane, so
GameObject > Create Other > Plane, and
| | 00:31 | it's going to come in at about the
same spot as our water splash, and so we
| | 00:37 | want to drop that down just a little bit, and
then we will scale it up so it fills the hole.
| | 00:46 | And we are going to name this one Water Basin.
| | 00:51 | Now we need to import the simple Water
Package from the exercise files for this
| | 00:54 | video, it should turn up in
the Main Materials folder.
| | 00:59 | Right-click, Import Package > Custom
Package, and in our Assets folder, Simple
| | 01:10 | Water, and click Import.
| | 01:14 | So let's locate our new material,
and since I don't see it right-off, I'm
| | 01:20 | going to go ahead and use the search function,
and there it is right here, Simple Water.
| | 01:25 | We will drop our new material
onto the Water Basin, like so.
| | 01:33 | You don't need to click Play to see
that it's going to need some motion, looks
| | 01:38 | pretty static as is.
| | 01:40 | Let's select the Simple Water
material and change the Offset X to 0.5.
| | 01:48 | Our Offset X, and when we change it to
0.5 watch it shift in the Scene view.
| | 01:57 | The Offset loops at one.
So let's go ahead and set it back to 0.
| | 02:03 | Since writing shaders to animate
vertices is an advanced topic, we'll just write
| | 02:07 | a little script to animate
the offset of the texture.
| | 02:10 | It can be used on just about anything
to animate a materials-based texture.
| | 02:15 | Let's think about what we'll need.
| | 02:17 | We'll need to be able to give it a
speed and to tell it which direction, U or V,
| | 02:22 | to scroll, and we will need to tell it
which material it should be affecting.
| | 02:26 | Let's create a new script in the Game
scripts folder and name it UV_Scroller,
| | 02:32 | and then we'll open it in the editor.
| | 02:34 | I'm going to click out of my search
function and locate my Game Scripts.
| | 02:42 | Right-click, create Javascript, UV_
Scroller, double-click it, and we are going
| | 02:57 | to need several variables.
| | 02:59 | So I am just going to copy them from
the Snippets file, Code_Snippets, and
| | 03:04 | we're going to take these first three, Ctrl+C
to copy and add our variables up at the top.
| | 03:14 | In the Update function we'll need to
affect the Offset by using time.time then
| | 03:19 | multiply it by speed.
| | 03:20 | I'm going to grab the next couple
of lines and paste them in as well.
| | 03:24 | Highlight our next two lines, Ctrl+C to copy,
and we add those to our Update function.
| | 03:31 | I am going to give myself a little
bit of space first and Ctrl+V to paste.
| | 03:35 | Now here comes the new bit, to access
a shader's property we need to use the
| | 03:40 | property names a bit differently.
| | 03:42 | We usually start with an underscore
and some of the names are different than
| | 03:46 | what we see in the
Inspector, base being one of them.
| | 03:49 | You can find the common texture names
scattered through the material class functions.
| | 03:54 | Let's open the shader reference for a
minute and search for material, and open
| | 03:58 | the scripting reference,
and do a search for material.
| | 04:06 | We're going to be looking for
SetTextureOffset, so I am going to hit Enter, and
| | 04:12 | we'll see if we can find that,
SetTextureOffset, and it shows us the names that
| | 04:20 | we need to be using to refer to the shaders.
| | 04:23 | It looks like MainTex is the one that
we're going to need. And grab the next
| | 04:28 | line, right-click, copy, and we want to
put that one right beneath the others,
| | 04:35 | using Ctrl+V to paste.
| | 04:37 | And now we can save the script, and
we'll apply the script to the Water Basin
| | 04:43 | object, UV_Scroller over to Water Basin.
| | 04:50 | Let's select it and in the Inspector
we are going to change one of the scroll
| | 04:57 | speeds to about 0.05.
| | 05:02 | Let's switch back to the 2 by 3 layout
and focus in on the Water Basin again.
| | 05:08 | Up at the top, 2 by 3, we'll double-click
Water Basin, and use the Alt key to
| | 05:18 | get back to our view.
| | 05:23 | I'm going to deselect the
Water Basin, and then click Play.
| | 05:30 | And our water has a nice little animation on it.
Let's exit Play mode. Just a note here,
| | 05:37 | if you try the UV_Scroller on
the pro-water nothing happens.
| | 05:41 | Remember, Unity controls that animation
through the shader, so the shader must
| | 05:45 | support the offset property as well.
| | 05:48 | There's a nice water shader in one of
the sample projects, Sewer Room, that does
| | 05:52 | support it, and it also has a
very good non-pro-water shader.
| | 05:56 | That can be found on the Unity web site.
| | 05:58 | Now let's use another trick for
Economical Water, a double layer.
| | 06:02 | Let's duplicate the Water Basin with
Ctrl+D, so we'll select it, Ctrl+ D, and
| | 06:10 | we'll drop it down just a little bit.
| | 06:17 | Just about that much, then we're going to
change its UV_Scroller numbers a little.
| | 06:22 | Let's say 0.03 and 0.03 to get it moving at
an angle that's different from the original.
| | 06:30 | We'll click Play and check it out, and I'll
deselect the water so we can see the difference.
| | 06:41 | The addition of the second layer
really makes our water look dynamic.
| | 06:45 | Let's exit Play mode.
| | 06:47 | Once we edit the partially
transparent Water Basins we started to see a
| | 06:51 | flickering issue with the
Water Surface Splash Prefab.
| | 06:54 | The problem is because both basins and
particles use a transparency shader, so
| | 06:59 | the engine can't decide which to draw first.
| | 07:02 | Unity uses a queue tag system with the
shaders to tell the engine which order to
| | 07:07 | draw objects into the scene.
| | 07:09 | Search queue tag, if you're
curious, that's Q-U-E-U-E on queue.
| | 07:15 | Meanwhile, let's use
import asset to bring in the
| | 07:18 | Alpha-BumpSpecDrawFirst.shader.
| | 07:23 | Right-click, Import New Asset, and this
is the one we want so we'll say Import.
| | 07:32 | Now we can replace the Simple Water
Material Shader with that, it's under
| | 07:36 | the Custom Section.
| | 07:38 | To find our simple water material again,
this time we can click on the Water
| | 07:42 | Basin, and there it is at
the bottom of the Inspector.
| | 07:47 | So we are going to change our Transparent/Bumped
Specular to Custom, Bumped Specular Draw First.
| | 07:57 | I've changed the Queue tags in this
one so it should work better for us.
| | 08:01 | Let's click Play and test.
| | 08:08 | Now the Water Surface Splash Prefab
always draws after the two Water Basin
| | 08:14 | objects, and we can exit Play mode.
| | 08:19 | And in case you already tried walking
on water just leave the colliders on the
| | 08:22 | water surfaces for now.
We'll see a final alternative in a later video.
| | Collapse this transcript |
| Tracking objects with LookAt| 00:00 | With the addition of the Sentry Gun
in the CompoundExtras, we'll be able to
| | 00:04 | check out a few more popular
features with our scripting.
| | 00:07 | Crucial for any interaction between
player and other entities is the ability for
| | 00:11 | them to see the player
when he comes within range.
| | 00:14 | We're going to set up the Sentry Gun so
we script it to turn to face the player.
| | 00:19 | It will need some changes in
the colliders, plus a Rigidbody.
| | 00:23 | So let's import the Better Extras
Package and use the Prefab from it.
| | 00:28 | It's already set up for us.
| | 00:30 | So right-click, Import Package > Custom
Package > Assets > Better Extras, and we'll
| | 00:42 | click Open and Import.
| | 00:45 | We've also got a few other new
Prefabs, we'll look at those later.
| | 00:50 | Now let's focus in on the Sentry
Tripod in the CompoundExtras folder, and I'm
| | 00:58 | going to rotate my view a little bit,
and then from the Prefabs folder we are
| | 01:10 | going to bring SentryGunGroup into the scene.
| | 01:16 | And we can use Move To View
to match it up to the original.
| | 01:20 | We'll need to drop it down a little
bit, and now we can delete our original
| | 01:24 | Sentry Tripod group.
| | 01:26 | Right-click, and delete, and
yes, we'll lose our Prefab.
| | 01:31 | So this guy now, the SentryGunGroup, has
an added Rigidbody, and I have changed
| | 01:40 | him to a Box Collider, and you can see
it's kind of narrow and tall that way
| | 01:44 | when we hit him it will be kind
of wobbly and fall over easier.
| | 01:47 | Now for the fun part, we'll be using
the simplest code, Transform.LookAt.
| | 01:53 | So let's make a new script in the Game
Scripts folder and name it SentryGun.
| | 02:01 | Right-click, Create > Javascript,
SentryGun, and we'll double-click to open it.
| | 02:13 | And I am going to go ahead and close
some of the other tabs so we don't get
| | 02:17 | confused, by clicking the X.
| | 02:22 | So to start, for our SentryGun script
we're going to need a variable to hold the
| | 02:26 | target and then the rest is going to
go into the Update function, so let's
| | 02:30 | start with our target.
Give myself some space, var target : Transform;.
| | 02:41 | And in the Update function we are going
to add, and I'll give myself some room
| | 02:47 | here, transform.LookAt(target);.
| | 02:52 | So now we can save the
script and get back to the editor.
| | 02:56 | And we need to drop it on the SentryGun.
| | 02:58 | So I am going to make sure my
SentryGunGroup is open, and I'm going to drag
| | 03:02 | SentryGun onto SentryGun, and select it.
| | 03:06 | So now we need to drag our first-
person controller onto its target parameter.
| | 03:11 | Let's go to the Inspector find where that is.
| | 03:16 | Here is our first-person controller,
and we'll drag and drop him on to
| | 03:21 | the Target parameter.
| | 03:23 | This is one of those times we need to
make sure and use the 2 by 3 layout so we
| | 03:27 | can get a better view of the gun.
| | 03:28 | So if you haven't already, go ahead
and switch to the 2 by 3 layout, and
| | 03:32 | let's get a little bit of an Overhead view
going so we can see what the gun is pointing at.
| | 03:37 | I am going to use Alt-left mouse key,
and maybe zoom out a little bit.
| | 03:44 | And now we can click Play and drive
around the area, we should be able to see
| | 03:48 | the gun watching the first-person
controller, and don't forget to go up and down
| | 03:51 | the steps and maybe even jump a few times.
| | 03:56 | Click Play, and I'm using my Left Arrow
key, Right Arrow key, I'm going to go up
| | 04:07 | now with my Up key, and maybe I'll
try jumping, and we can see the gun is
| | 04:12 | definitely tracking us,
and we can exit Play mode.
| | 04:16 | So now that we are sure the LookAt is
working nicely, let's see about keeping
| | 04:20 | the SentryGun from tracking the first-
person controller when it's beyond range.
| | 04:24 | That means we'll need a range variable, so
let's head back to the Script editor and add it.
| | 04:29 | We'll edit underneath our
Target variable var range : float,
| | 04:34 | and we'll go ahead and
initialize it at say 30 meters.
| | 04:40 | I am going to grab the next bit of
code from the Snippets file, and we'll
| | 04:45 | open 08_06Code_Snippets, we've already
added the first three, so let's just
| | 04:51 | copy this guy, right-click, Copy, and we
want to add that one up above the LookAt line.
| | 05:01 | The Return Xs us out of the function
so that nothing below it is carried out.
| | 05:07 | In this case that means if the first-
person controller is out of range the
| | 05:11 | SentryGun wont rotate towards it.
| | 05:13 | Let's save the script and
head back to the editor.
| | 05:16 | And there we go, now we can click Play and test.
| | 05:19 | If we leave the compound area this
SentryGun will no longer track the
| | 05:23 | first-person controller.
| | 05:28 | And I am using W to head on out, and he
is still watching, and at some point he
| | 05:35 | no longer rotates to follow us.
And let's exit Play mode.
| | 05:40 | Now that we've got the basics of the LookAt
working we'll be adding a laser beam next.
| | Collapse this transcript |
| Using Linecast and the Line Renderer| 00:00 | The next goody we'll make is a laser beam.
| | 00:03 | Our sentry may not have any ammo, but
its laser will show us what our first-
| | 00:07 | person controller has been detected.
| | 00:08 | Let's start by selecting the
laser point object on the Sentry Gun.
| | 00:12 | I'll need to open him up,
and here is our Laser Point.
| | 00:16 | From the Components menu, Effects,
let's add a Line Renderer component.
| | 00:23 | Components > Effects > Line Renderer.
| | 00:28 | The Line Renderer creates a
plane that always faces the camera.
| | 00:32 | First we want to uncheck Use World Space.
| | 00:38 | That keeps it at the laser
point instead of 000 in the World.
| | 00:42 | Now we can see it in a scene. Let's uncheck
Cast and Receive Shadows and Open Up Positions.
| | 00:51 | Elements 0 and 1 are locations of
the start and end points of the line.
| | 00:57 | The line is actually a plane.
| | 01:00 | Element 1 Y is the length of the line,
we'll be feeding it the hit distance from
| | 01:05 | the guns Line Caster later.
But for now we'll set it to 5 so we can see it.
| | 01:10 | Under parameters we'll set
the start and end with to .15.
| | 01:17 | And now we are going to need a material.
| | 01:20 | Our last package import included a laser
material, let's go ahead and assign the
| | 01:24 | new material in the Line
Renderer's Material Array.
| | 01:29 | Open up Materials we'll add it to 0.
| | 01:35 | And I've opened up the browser, and I
am looking for Laser, and here it is.
| | 01:43 | The Laser material came in with our last
package import, let's take a quick look at it.
| | 01:49 | It's in the Materials folder and here
it is. It's using a Tiling of 20, and
| | 01:59 | that's going to show up as
soon as we start animating it.
| | 02:02 | For now let's get back to our Laser Point.
| | 02:04 | Now we are going to need a script to
calculate the length and direction of our laser.
| | 02:09 | So let's create our new script in the
Game Scripts folder, right-click,
| | 02:18 | Create > Javascript, and we are
going to name this one Laser.
| | 02:23 | Double-click it to open it in the script
editor, and, of course, it's going to need
| | 02:29 | a target there, so we'll
start with var target : Transform;.
| | 02:33 | Var target of type Transform--and
auto complete has got me again.
| | 02:46 | I'm going to copy the next bit
of code from the snippets file.
| | 02:50 | Exercise Files08/08-07/Code_Snippets.
| | 02:55 | So we are going to highlight, right-
click, and Copy, back to our Script editor,
| | 03:03 | now we're going to paste this in the update function.
So let's see what's going on here.
| | 03:09 | In an earlier video we used physics.Raycast
with a starting position and direction.
| | 03:16 | With physics.Linecast we have a
starting position also, but instead of the
| | 03:20 | direction we have a target position that
is used to calculate the direction internally.
| | 03:26 | Next using hit, of type Raycast hit, we
get both the location of the hit and
| | 03:33 | the distance to it.
| | 03:35 | Those values are fed back into the
LineRenderer component to draw Element 1 in
| | 03:39 | the correct location.
| | 03:41 | Our Element 0 is always at
the laser point's location.
| | 03:45 | Let's save the script and
head back to the editor.
| | 03:48 | And we'll need to add the laser script
to the laser point object and then assign
| | 03:53 | the target our first-person controller.
| | 03:56 | So our Laser script goes on the Laser
Point, select the Laser Point and here's
| | 04:04 | our target, and we want our first-
person controller as the target.
| | 04:10 | With the last package import we
also got a nice stack of barrels.
| | 04:14 | This will give our first-person
controller something to hide behind.
| | 04:18 | So from the Prefabs folder, let's drag the
Stack O' Barrels into the Hierarchy view.
| | 04:26 | And we may need to adjust them slightly.
| | 04:32 | I'm going to move them so they are
sort of in and sort of out of the sun.
| | 04:36 | Now let's click Play and test it by
strafing the first-person controller
| | 04:39 | with the A and D keys.
| | 04:41 | I'm going to tip our view a little bit,
click Play, and as soon as our first-
| | 04:49 | person controller gets out from behind
the barrels, the laser beam spots him,
| | 04:56 | let's exit Play mode.
| | 04:58 | So we have now seen how physics.Linecast
can be used to create some special effects.
| | Collapse this transcript |
|
|
9. Understanding LightingInvestigating ambient light| 00:00 | Back when we first setup our environment,
we needed to add a light so we could
| | 00:04 | see things in the game view.
| | 00:06 | Scene view offers the option of default
light, but game view must have lights or
| | 00:11 | everything appears in an odd sort of twilight.
| | 00:13 | In this video we'll be
investigating ambient light.
| | 00:17 | So let's deactivate the
Directional light to start.
| | 00:20 | I select my Directional Light,
and I'm going to deactivate it.
| | 00:25 | If you've been baking your light into
textures you won't see much difference,
| | 00:29 | let's clear them just in case.
| | 00:31 | From the Window menu, open Lightmapping
and click Clear--mine wasn't baked in so
| | 00:39 | you won't see any difference for me.
| | 00:41 | In the game window everything still
looks kind of light. So what's happening?
| | 00:46 | Unity, like most 3D engines, has a setting
for ambient light, it sort of fakes the
| | 00:52 | bounce light that gets
scattered around from the atmosphere.
| | 00:54 | Desert areas have sharp shadows and
high contrast between sunny areas and
| | 00:59 | shadows, this is because the air is so dry.
| | 01:02 | Places with high humidity and/or cloud
cover have softer diffused light and only
| | 01:07 | darkish areas of shadow from the light
bouncing off the moisture in the air.
| | 01:12 | In Unity we can find the ambient light property
in Edit, Render Settings. Edit > Render Settings.
| | 01:22 | We've been here before when we
were looking into fog, so let's turn
| | 01:26 | Ambient Light to black.
| | 01:33 | Now there's nothing much showing in
the game window, we can reactivate the
| | 01:36 | Directional light now, depending on
where we are it's still pretty dark, there's
| | 01:41 | no bounced light, we may as well be
on the moon with no atmosphere at all,
| | 01:46 | select the light, and let's
increase its Intensity to 0.8.
| | 01:49 | The lit area looks much better now,
but the things that receive no light are
| | 01:53 | pretty much in the dark.
| | 01:55 | Remember Directional lights only cast
rays in one direction, so let's set
| | 01:59 | it back down to 0.5.
| | 02:02 | And now, let's turn the Ambient up
just enough so the scene looks believable.
| | 02:06 | We'll go back to Edit > Render Settings.
| | 02:11 | I like it somewhere around 49 or 50
for the RGB values, now we're ready to go
| | 02:18 | ahead and look at light objects.
| | Collapse this transcript |
| Looking at light types| 00:00 | Now that we've seen how ambient light
affects the scene we can look into regular lights.
| | 00:05 | Let's start by selecting the Directional light.
The first parameter is Type.
| | 00:11 | The Directional light cast rays
throughout the scene regardless of position,
| | 00:16 | all rays are parallel to each other.
| | 00:18 | In other words, the direction you point the
light is the direction they all point
| | 00:21 | Let's deactivate the Directional light again.
| | 00:25 | Let's focus in on the Lamp, in the
CompoundExtras, and we're going to create a test light.
| | 00:30 | We could create one from the GameObject
menu, but since it's just a component,
| | 00:35 | let's create an empty GameObject, and
name it Generic Light, and add a Light
| | 00:43 | component to it. And we'll find
that in Component > Rendering > Light.
| | 00:49 | The default Type is Point, I'm going to
move mine aside a little bit, and zoom out.
| | 00:59 | So we'll have a good view of what it's doing.
| | 01:01 | Point lights cast rays in all
directions from a central point, and point
| | 01:06 | lights have a range. Let's reduce the Range
until we can see the range gizmo in the scene view.
| | 01:11 | I'm going to click and drag next to the
Range field, and as I bring it down, we
| | 01:20 | can now start seeing its gizmo.
| | 01:23 | If we move the light down we can see
that it gets stronger the closer to the
| | 01:27 | surface we get, so point lights have a
built-in fall off within the range, and
| | 01:32 | of course we can set the Color and Intensity.
| | 01:36 | Cookies mask the light using a
textures Alpha channel, point lights need cube
| | 01:40 | maps with Alpha channels so
let's change our light to a spotlight,
| | 01:44 | under Type we'll choose Spot.
| | 01:47 | It will need to be rotated 90
degrees on the X to get it to point down.
| | 01:52 | And let's increase the Range, and the
Intensity, and maybe I'll bring it up
| | 02:00 | a bit, and bring my Spot Angle down. Let's
see about loading a texture for the Cookie.
| | 02:07 | I'm going to click on the browser,
and see what we've got. Let's choose Cookie.
| | 02:12 | We've already moved the light
up so let's move it down now.
| | 02:19 | As we move it down we can see that the
cookie shows beyond the cone and since
| | 02:23 | this texture is set to wrap it tiles.
Let's change the light Type to Directional.
| | 02:30 | Now we get a Cookie Size parameter.
| | 02:33 | I'm going to reduce it, by clicking on
it in Inspector, I can find it in the
| | 02:38 | Project file, and look at it in the
inspector, and we're going to change its Wrap
| | 02:43 | mode to Clamp, and Apply. And now we
can see that we have a single Cookie
| | 02:51 | emitting from our directional light. So
using a Directional light it gives us an
| | 02:56 | economical way to use Cookies.
| | 02:59 | Let's remove the Cookie texture by
clicking on the browser and selecting None.
| | 03:07 | And we'll go ahead and reduce its Intensity.
In the next video we'll be looking at shadows.
| | Collapse this transcript |
| Exploring shadows| 00:00 | If you're using Pro, you'll be able to
test out Shadow Types, hard or soft shadows.
| | 00:06 | Click play and select the BigTree and use
Move To View to get it over to the compound.
| | 00:12 | Click play. We'll select the BigTree. We're
going to use Move To View to get into the compound.
| | 00:19 | It doesn't really matter where it ends
up, we're just looking for the shadow.
| | 00:23 | So now activate the WindZone in the
Hierarchy panel, and let's deactivate the
| | 00:32 | Audio Source for a minute.
| | 00:34 | Let's select Generic Light and test the
difference between hard and soft shadows.
| | 00:38 | Under Shadow Type I'm going to select
Hard Shadows, and now we can see our
| | 00:44 | dynamic shadows in the viewports.
And then I'll switch to Soft Shadows.
| | 00:51 | Okay, let's exit Play mode
and continue with shadows.
| | 00:57 | Let's turn our Generic Light back
into a Point light, and increase its range
| | 01:01 | and intensity a bit.
| | 01:02 | So we'll turn it to and a Point light,
and let's increase its intensity a
| | 01:08 | little, and check its Range.
That's probably pretty good.
| | 01:13 | Let's set our Shadow Type back to
Soft Shadows, and we'll see a warning
| | 01:18 | here--Only directional lights have
shadows in forward rendering.
| | 01:24 | With Pro we can switch to Deferred Lighting, we find
that through Edit > Project Settings > Player.
| | 01:35 | In the Other Settings we can change our
forward rendering path to Deferred Lighting.
| | 01:42 | And now we once again have dynamic shadows.
| | 01:46 | Let's select our Generic Light again
and look into a few more parameters.
| | 01:52 | With Shadow Type, Strength
is how dark the shadows are.
| | 01:55 | And you see we can fade it
out and bring it back stronger.
| | 02:01 | Unity uses shadow, or depth maps, for
making shadows, so the larger the map the
| | 02:06 | more accurate the shadows,
but the more memory used.
| | 02:10 | This is in your resolution.
| | 02:11 | Map resolution defaults to the quality
settings from the Project Settings under
| | 02:16 | Quality, but it can be
overwritten in the individual lights.
| | 02:20 | With both pro Shadow Types,
you'll see a setting for Bias.
| | 02:25 | This setting is what needs tweaking when
shadows don't match up with the geometry.
| | 02:29 | We see it mostly on things like
fence posts or other tall narrow objects.
| | 02:34 | In this scene you might
find it at the tripod feet.
| | 02:37 | If the shadow doesn't quite match up
with the foot, and you are sure that the
| | 02:41 | foot is going through the
ground, that may be the problem.
| | 02:45 | By carefully decreasing the Bias, you should be
able to get shadows to match up to the objects.
| | 02:50 | If you go too low though, you get
nasty artifacting, so be careful.
| | 02:55 | So let's recap on dynamic shadows.
| | 02:57 | Directional lights are the only lights that
cast dynamic shadows with forward rendering.
| | 03:02 | Let's go back into the Player settings
and set render mode back to forward,
| | 03:08 | Edit > Project Settings > Player, and we'll
set it back to Forward, and our shadows
| | 03:16 | disappear once again.
| | 03:17 | While we're here, let's try the
other rendering path option, Vertex Lit.
| | 03:24 | With Vertex Lit, lighting is calculated
on each vertex and averaged between them.
| | 03:30 | This older technology is more
economical than pixel lighting where the light
| | 03:34 | calculations are done on a pixel basis.
| | 03:37 | In pixel lighting, more screen real
estate gets more accurate calculation.
| | 03:41 | Unity automatically drops down to
vertex lighting when required by hardware.
| | 03:46 | Vertex lighting does not
support dynamic shadows.
| | 03:50 | Let's set the render path back to Deferred,
if you have pro, or Forward, if you don't.
| | 03:56 | Render mode also drops the
lighting modes to vertex lighting unless
| | 04:00 | important, or more distant lights in your scene.
| | 04:03 | You can change these settings
individually in the Quality Settings.
| | 04:07 | For that, Edit > Project Settings > Quality.
| | 04:13 | In the Quality Settings the Pixel Light
Count lets you define the maximum number.
| | 04:18 | This, by the way, is a good place to see
what features are high resource users.
| | 04:23 | Let's set the Quality to Good and get
back to our Generic Light. Next up is halo.
| | 04:31 | Let's check Draw Halo.
| | 04:34 | If your lights range is large and the
intensity low, you might not notice a difference.
| | 04:39 | Halos draw their intensity
inversely from the light's range.
| | 04:43 | As we decrease the range,
the halo gets stronger.
| | 04:47 | Halos are also affected by distance.
When you zoom closer to halos, they fade out.
| | 04:54 | Halos are drawn on flat planes that
always face the camera, so they are prone to
| | 04:58 | being clipped on geometry,
but are good for effects.
| | 05:02 | You may find that you have more control
with two lights when you want a halo effect.
| | 05:06 | We won't need the Generic Light
anymore, so let's go ahead and delete it.
| | 05:11 | Right-click, Delete, and we'll go
ahead and reactivate the Directional light
| | 05:16 | for the next video.
| | 05:17 | So this should give you a basic idea
on how lights and dynamic shadows work in Unity.
| | Collapse this transcript |
| Baking lighting with Beast| 00:00 | One of the most useful features
Unity brought on board is the Beast Light
| | 00:04 | Mapper by Illuminate Labs.
| | 00:06 | Even at its most economical,
lighting, and especially shadows, are costly.
| | 00:12 | So typically, we bake the lighting into
textures that are internally added to our geometry.
| | 00:17 | As you might guess, it's not free,
texture size can greatly increase the
| | 00:22 | file size of a game.
| | 00:23 | Visually though, it can be well
worth the extra memory usage.
| | 00:28 | Although Beast is available in both the
free and Pro versions, the free version
| | 00:33 | has most of the goodies turned off.
In this video we'll just cover the basics.
| | 00:38 | The most important thing to remember
about the Light Mapper is that it's sort
| | 00:41 | of a one-shot deal.
You don't bake objects individually.
| | 00:45 | So while you may bake the scene
occasionally just for aesthetics, while you are
| | 00:49 | working, generally it will be one of
the last things you do once all of your
| | 00:54 | assets are in and set up.
Let's open the Light Mapper and take a look.
| | 00:58 | From Window > LightMapping.
The first tab is Object.
| | 01:03 | This is where you will deal with
objects on an individual basis.
| | 01:07 | Let's select one of the barrels,
so we'll have something to look at.
| | 01:11 | Light Maps Static is one of the
places an object can be marked as Static.
| | 01:16 | Static means the object will not be
moving in the scene and will both receive
| | 01:20 | light mapping and be
included in the overall solution.
| | 01:24 | It's very important to
get your head around that.
| | 01:27 | Anything that animates, or is controlled
by physics, should not be marked as static.
| | 01:32 | You can also set the static in the Inspector.
| | 01:35 | If you set it in the Light Mapper, it works
more as an override for only the LightMapping.
| | 01:41 | Static is also used for creating the
pathfinding nav maps, among other things.
| | 01:46 | So best practice is to set in the Inspector.
Let's focus in on the fountain base.
| | 01:52 | I'm going to move the Light Mapper, and
let's select the fountain base and the two
| | 02:02 | FruFra, and in the Inspector up at the
top, we're going to check them as Static,
| | 02:08 | and you see that Lightmap Static also
gets turned on in the Light Mapper dialog.
| | 02:14 | Once you have decided to bake light into
an object, it will need a second set of
| | 02:18 | UVs or mapping coordinates.
| | 02:20 | Unlike regular texture coordinates
the second UV channel has strict rules.
| | 02:25 | We found that out in the
video on Importing Static Objects.
| | 02:29 | After Static, if we scroll down a
little bit, comes Scale in Light Map.
| | 02:36 | This one lets you to find how much real
estate an object gets on the texture maps.
| | 02:41 | The larger the value, the more space it gets.
| | 02:44 | Let's select the Fountain
Base again, and zoom in on it.
| | 02:50 | In the Scene view, Light Map
Display check Show Resolution.
| | 02:56 | If we zoom in closer, we can see that there
are lots of checkers on the fountain base.
| | 03:01 | The terrain resolution is handled on
its own, but everything else is handled
| | 03:05 | relative to each other.
| | 03:07 | The tiny checkers mean that the
fountain base will get a lot of mapping space.
| | 03:12 | If we reduce it, to say five, you can
see the checkers start to get bigger.
| | 03:20 | If I bring it down even lower, maybe 0.2, now
you can see the checkers are quite a bit larger.
| | 03:27 | As we reduce it, the checkers get
larger, meaning that its pieces will be
| | 03:32 | smaller or get less real
estate on the light maps.
| | 03:36 | For those of us who are used to baking
in our light maps with VRay, Brazil, or
| | 03:40 | other third-party renderers in Max, Maya,
or whatever App we use, the next bit of
| | 03:45 | info is extremely important.
| | 03:47 | A scale value of zero means no light
map will be generated, but the object will
| | 03:54 | be included in the overall solution.
| | 03:57 | So if your object comes in with its
own light map, it still gets marked as
| | 04:02 | Static, so it will cast shadows, but it
needs its Scale in Light Map set to zero.
| | 04:10 | If we select the Terrain, instead of
scale in Light Map we get Light Map Size.
| | 04:15 | This for Terrain's only since they are
always handled separately from the rest
| | 04:18 | of the scenes objects,
and we'll open it up here.
| | 04:24 | I can probably stretch my dialog out a bit.
| | 04:27 | Atlas index is the array number
of the light map the object is on.
| | 04:32 | The Terrain is automatically assigned minus one.
| | 04:35 | Everything else is combined or
atlased on several more maps in the array.
| | 04:42 | If we select our directional light,
and I'll need to move the dialog out of
| | 04:46 | the way, we will see a couple of parameters
from the inspector plus a couple of new ones.
| | 04:51 | Bounce Intensity multiplies the
bounce light originating from the slide.
| | 04:56 | So if it shines on a bright green object,
the green color would be picked up and
| | 05:00 | intensified on surrounding objects.
More so with a higher Bounce Intensity.
| | 05:06 | This is a pro-feature, by the way.
| | 05:07 | Shadow Samples increase the accuracy and
resolution at the cost of baking speed.
| | 05:14 | Shadow Radius softens hard shadows.
We'll get some practice with this stuff later.
| | 05:18 | The next tab, Bake, is where you
set up the solution in general.
| | 05:22 | Mode is where you set up
for dual, or single, light maps.
| | 05:26 | Single Lightmaps are used with the
forward lighting path and generates full
| | 05:31 | solution light maps.
| | 05:33 | If you have Pro, and are using deferred lighting,
you will need to use Dual Lightmaps.
| | 05:38 | A near and far version of each map is created.
| | 05:42 | The near only contains Indirect
Illumination, Full Illumination from Baked Area
| | 05:47 | Lights, Emissive Materials, and Skylights.
| | 05:50 | The far version is a full solution
version that is used beyond the Dynamic
| | 05:54 | Shadow Range and includes Shadows.
| | 05:58 | Directional Lightmaps allow normal maps to be
included so Specular and Bump data can be seen.
| | 06:04 | Let's move the dialog aside and
look at our Scene view for a minute.
| | 06:09 | In the Scene view's Lightmap display,
you'll be able to set the Shadow Distance.
| | 06:13 | This is the border where the Near Map
plus the Dynamic Shadows are faded into
| | 06:17 | the far maps and no dynamic shadows.
It can be found in the Quality Settings as well.
| | 06:23 | With our good-quality preset, we are using 40.
| | 06:27 | Back in the Light Mapping dialog, Use in
forward rendering, is a check box that
| | 06:32 | should only be checked if you're
planning on making Custom Shaders.
| | 06:36 | The Quality presets are a quick way to
set up baking without spending days and
| | 06:40 | days tweaking and comparing results.
We have a choice between High and Low.
| | 06:46 | Bounces will bounce the lighting, more
Bounces means brighter solutions, but
| | 06:51 | slower calculation times.
| | 06:53 | Towards the bottom, Ambient Occlusion is
available for both free and Pro versions.
| | 06:58 | Ambient Occlusion is calculated
independent of scene lights, it's the stuff
| | 07:02 | that darkens nooks and crannies by deciding how
occluded or blocked the faces on the model are.
| | 07:09 | If your meshes are fairly low poly, with
little concave areas, they probably won't
| | 07:14 | benefit much from Ambient Occlusion.
| | 07:16 | Higher detail meshes, on the other hand,
will have details pop out as the cracks
| | 07:21 | and crevices are darkened.
The last section is about light maps.
| | 07:25 | It lets you set overall
resolution, or map scale, as well as Padding.
| | 07:29 | Padding is the amount of space
between pieces on the light map.
| | 07:33 | Small maps may need more Padding to prevent
colors overlapping into each other's pieces.
| | 07:38 | The Lock Atlas check box allows you
to prevent a piece from recalculating
| | 07:42 | the mapping layouts.
| | 07:44 | And finally, in the last section, Maps,
you'll be able to see the rendered maps
| | 07:49 | and their index numbers
once we have some to look at.
| | 07:53 | Light Probes are a means of adding to
dynamic shadows with localized areas that
| | 07:58 | will contribute radiosity and
emissive lighting effects in real time.
| | 08:01 | They are beyond the scope
of the Essential series.
| | 08:06 | Let's go ahead and turn off Show
Resolution in the Light Mapper display before
| | 08:09 | we close the Light Mapper.
| | 08:12 | So that's our run down of the basic
features in the Beast Light Mapper.
| | Collapse this transcript |
| Experimenting with Beast| 00:00 | If you've already baked light into the
main level you know how long that can take.
| | 00:04 | So before we bake the lighting in to
main scene, let's try a few experiments
| | 00:09 | in a smaller scene.
| | 00:11 | Most of these will be with pro features,
but a few will pertain to free as well.
| | 00:15 | If you are using Pro make sure
that Deferred Lighting is being used.
| | 00:21 | Let's start by saving our current scene,
then creating a new scene named light tests.
| | 00:27 | File > Save Scene, File > New Scene, and
File > Save Scene as, Light Tests, and let's
| | 00:36 | remember to put it in our Scenes folder.
| | 00:39 | Now we need to Import the Lighting Room
package from the exercise files into our Project.
| | 00:45 | Right-click, Import Package > Custom
Package, up to our Assets folder, and
| | 00:54 | LightingRoom, and we'll click Open and Import.
We can find it in the imported Assets folder.
| | 01:02 | In the Inspector, we can see that
Generate Light Map UVs has already been checked.
| | 01:08 | Let's go ahead and drag the
LightingRoom asset into the Hierarchy, and we'll
| | 01:12 | double-click on it to see it in the
Scene view. And I am zooming in using my
| | 01:17 | middle mouse roller, and I
will just rotate it a little.
| | 01:21 | Right now, we have no lights, so let's
see what we can get with Skylights in Beast.
| | 01:26 | Let's select all of the objects,
or the parent, and click Static.
| | 01:34 | Yes to, change children.
| | 01:36 | Now we'll go ahead and open the
Light Mapper from window, Light Mapping
| | 01:41 | and click Bake Scene.
| | 01:46 | If you toggle the Scene Lighting on,
you can see the results, nothing.
| | 01:51 | In the Maps tab, we can see the dual light
maps and the Size shows 2.7 megs of well, nothing.
| | 02:02 | Let's turn our Skylight
Intensity to one and see what we can do.
| | 02:07 | In the Bake tab, Skylight Intensity
which was zero, we are going to change to
| | 02:13 | one, and let's Bake Scene again.
And now we can see our two light maps.
| | 02:19 | In case you're wondering whether the
scenes ambient light affects the baked
| | 02:23 | light maps, we ought to test for that too.
| | 02:26 | In the Render Settings, let's go ahead
and turn the Ambient to 0, Edit > Render Settings,
| | 02:33 | and we'll turn our Ambient
Light to zero, and bake the scene again.
| | 02:43 | Scene Ambient is definitely baked in.
| | 02:46 | So let's go ahead and set it back
to 50 before we move on, Edit > Render Settings >
| | 02:52 | Ambient Light, and we'll
bring it back up to about 49 or 50.
| | 03:00 | If we look at maps in the preview
they still look pretty much the same.
| | 03:04 | That's because the only light so far
is the GI type, Global Illumination.
| | 03:10 | So let's go ahead and add a sun
to the scene, a directional light.
| | 03:13 | GameObjects > Create Other > Directional Light.
| | 03:19 | And I am going to drag it up so I can
see it easier, and we want to set its
| | 03:23 | Shadow Type to Soft Shadows, and
let's rotate it so we get a shadow off the
| | 03:30 | right side of the room.
I am going to set it 45, -90, and 45.
| | 03:37 | And we'll Bake the scene again.
| | 03:42 | Since most of the objects were in the
shade, the map still looks similar, but if
| | 03:47 | you look closely you should be able to
see the shadows from the direct light
| | 03:51 | only in the far map.
| | 03:52 | Let's go ahead and fiddle with Shadow Distance in the
Light Map Display in the Scene view. Let's set it to 0.1.
| | 04:00 | This means all shadows in the scene
are baked and coming from the far map.
| | 04:05 | If we rotate the light coming from the
right, since we have our Directional Light
| | 04:09 | selected here, if we
rotate it, we see no difference.
| | 04:15 | As soon as I increase the Shadow
Difference, we'll see when the dynamic light
| | 04:20 | kicks in, and it's right about there.
| | 04:24 | Let's go ahead and set our
rotation back to 45, -90, and 45.
| | 04:31 | So now let's see what
happens if we Bounce Light.
| | 04:35 | Right now we don't see any
radiosity from the two colorful primitives.
| | 04:39 | Let's add a point light inside there with them.
| | 04:42 | So GameObject > Create Other > Point Light,
and then we'll set its range at about
| | 04:50 | 4 and its intensity to about 0.5.
| | 04:56 | And I'm going to move it kind of
over in the corner, then we can see it
| | 05:01 | shining on the walls.
| | 05:03 | We also want to tell it to have hard
shadows, and then we can go ahead and
| | 05:09 | Bake our scene again.
| | 05:12 | If I zoom in close, I don't see any
Radiosity from either the red or the green.
| | 05:19 | Let's set our Bounce Boost and Bounce
Intensity up and see if we can get some results.
| | 05:26 | We'll bake the scene again.
| | 05:29 | It's a little bright, but now I'm getting a
little bit of a pinkish area around the box.
| | 05:34 | So we'll just set it back to what it was before.
| | 05:37 | I'm going to set it back to 0.5, and
1, obviously we need to turn down the
| | 05:42 | intensity of the regular light
to get the full effect on this.
| | 05:45 | Next, let's find an emissive shader from
Emissive Shader Material for the walls light panel.
| | 05:52 | I'm going to zoom out, and if I rotate
around we can see this panel here, and
| | 05:57 | I'm going to move our light mapper for
a minute, and in the Lighting Room there
| | 06:05 | is our Light panel, and for Emissive we
are going to change this material to one
| | 06:12 | of the self-illuminated shaders.
| | 06:14 | Self Illuminated Diffuse should be
just fine, and I'm going to set my main
| | 06:19 | color to a nice magenta.
We'll go ahead and bake the scene again.
| | 06:27 | The Emission on that material was set
to 2, and yes there's plenty of my
| | 06:32 | magenta showing now.
| | 06:34 | In case you're thinking that this
would bake a good TV screen, let's pop an
| | 06:37 | image into the slot and see what we get.
| | 06:40 | I'm going for one of the leaf materials,
ColocaLeaf, and once again we'll bake.
| | 06:48 | I should have turned the magenta off first.
Let's do that and rebake it.
| | 06:52 | You are seeing lots of green
on the surrounding walls now.
| | 06:59 | Before we switch lights,
let's try something else.
| | 07:02 | Let's select the Point Light again, in
the Hierarchy, and in the Inspector let's
| | 07:08 | tell it, under Light Mapping, to use Baked Only.
Now the huge specular spot on the walls is gone.
| | 07:16 | It won't light something dynamic that
comes into the scene, but the light map
| | 07:20 | looks much better without it.
| | 07:23 | As long as we've got it set to Baked
Only, you may want to go ahead and try an
| | 07:27 | Area Light, if you do be sure and
change the Point Light to an Area Light and
| | 07:32 | then reduce its intensity quite a bit.
| | 07:35 | Now that you're familiar with the basic
process, feel free to tweak the settings
| | 07:39 | and experiment on your own.
| | Collapse this transcript |
| Baking the game scene| 00:00 | Now that we've gotten pretty
comfortable with lights, lighting and baked light,
| | 00:04 | let's finish up a few things in the game scene.
| | 00:07 | We'll need to start by saving this
scene, and opening our main level.
| | 00:14 | And I'll go ahead and zoom in on the fountain.
| | 00:17 | In the Structures for Scene, we want
to turn all of these to Static up in the
| | 00:23 | Inspector and Yes, change the children.
| | 00:27 | Some of the doors animate, so we
better turn off Static for all three doors,
| | 00:32 | Sliding Door Left, and Right, and Solid Door.
| | 00:39 | The Main Building Interior, and Stairs
Interior, already have light maps, so we're
| | 00:45 | going to select them and
open light mapper again.
| | 00:50 | Main Building Interior, and Stairs
Interior. From Window open Light Mapping,
| | 00:59 | and since they already have their light
maps, we're going to set their Scale to zero.
| | 01:04 | To use imported light maps you can use
the legacy shaders light map shaders or
| | 01:11 | if you have newer versions of Photoshop,
you should be able to use the same file
| | 01:15 | type as Beast and add the
maps manually into the array.
| | 01:19 | The Main Building
Basement is also a special case.
| | 01:23 | It should be pretty much in the dark.
| | 01:25 | We'll need a flashlight
to find our way through it.
| | 01:27 | So it really only needs
a small far and near map.
| | 01:31 | The scale tops out at one being full-sized
in relation to the rest of the objects.
| | 01:37 | Let's select the Main Building
Basement and set its Scale to 0.01.
| | 01:44 | Now we need to do a little fiddling.
| | 01:48 | If we turn the Ambient Light off while
we bake light, and use Skylight instead,
| | 01:52 | we'll get a nice solution, but with no
ambient our dynamic objects will be too
| | 01:57 | dark, so then we can turn
Ambient up to match after baking.
| | 02:03 | Once an object is using baked lighting,
it no longer receives ambient because
| | 02:07 | it was already baked in.
| | 02:09 | So let's turn our Ambient Light to 0,
once again Edit > Render Settings, and Ambient.
| | 02:17 | And one more thing.
| | 02:21 | We'd better turn the Trees back on
because we need shadows baked for them.
| | 02:27 | Select the Terrain, and in Settings I'm
going to check, Draw, and our Trees are
| | 02:35 | back, and now we can bake scene.
| | 02:39 | Let me cancel that, I need
to turn up the Skylight first.
| | 02:43 | So in the Bake tab I am
going to set my Skylight to 0.5.
| | 02:48 | Now I'll go ahead and bake scene.
| | 02:50 | In case, you're wondering about what
happens when you add more static measures
| | 02:54 | to the scene sometime down the road,
the answer is simple, you have to rebake
| | 02:58 | everything, and if you're tempted to
try Bake Selected, it does just as it says.
| | 03:04 | It bakes the solution using
only the selected objects.
| | 03:07 | So anything not selected will not be
used in the calculation unless it has
| | 03:12 | a scale set to zero.
| | 03:14 | The worst thing, though, is that
it clears all the other maps.
| | 03:18 | Fortunately, they've hidden the Bake
Selected object in the Bake Scene button
| | 03:22 | dropdown in this version.
| | 03:24 | If you are used to baking lighting in
your modeling app, you're probably used to
| | 03:28 | being able to bake things selectively.
| | 03:30 | Just remember, in Unity, Light Mapping is
more of a final solution, and there we go.
| | 03:37 | Now that Beast is finished, we can
focus on the barrels or some other dynamic
| | 03:41 | object in the scene and
move them into the shadows.
| | 03:44 | Ours are actually pretty good, some
are in and some are out of the shadows.
| | 03:48 | So now we need to adjust the Ambient to match.
| | 03:52 | From Edit > Render Settings > Ambient
Light, I want to bring up the Ambient
| | 04:01 | Light on the shadow part of the barrels, until
it looks like it matches the rest of the scene.
| | 04:07 | And it looks like somewhere
around 55, it starts to look correct.
| | 04:15 | With a little tweaking, my Dynamic and
Baked Lighting is working together nicely.
| | Collapse this transcript |
| Creating lighting effects| 00:00 | There's lots of nice light related
effects we can play with, but first we'll
| | 00:04 | need to import a couple of Unity packages.
| | 00:07 | Let's start with Light Flares, right-click,
Import Package, and select Light Flares.
| | 00:16 | Import, and then let's select
the scenes' Directional Light.
| | 00:21 | From Component > Effects, choose Lens Flare.
| | 00:28 | Lights have a Lens Flare section, but you
will get more control with the component.
| | 00:32 | Let's select Sun for the flare.
| | 00:37 | If we click Play, and look up to
the left, we'll see our sun flare.
| | 00:44 | I'm hitting Escape to
prevent the view from spinning.
| | 00:47 | Exit Play mode, and let's try a different one.
| | 00:51 | Let's try the 50mm zoom, click Play,
and look up again, and now you see
| | 01:00 | the typical Lens Flare.
| | 01:04 | I'm hitting Escape, to prevent the view
from spinning, and then I'm exiting Play mode.
| | 01:11 | The docs say to use these sparingly,
they have become a bit of a cliche, so
| | 01:15 | use your own judgment.
I'm switching mine back to just the Sun flare.
| | 01:19 | Visually related to lights are the nice
volumetric areas that are seen in dusty places.
| | 01:25 | Pro has a shader for God rays, but we can
get a nice cheap version with a line renderer.
| | 01:32 | We used it earlier for the laser beam, but
it's ideal for billboarded objects of any kind.
| | 01:38 | The main thing to remember with the Line
Renderer is to turn off use World coordinates.
| | 01:44 | They take a while to set up though, so
I've included a Prefab complete with a
| | 01:47 | spotlight for use with the hanging lamp.
It came in with an earlier package we imported.
| | 01:54 | So all we need to do is find it in the
Prefabs folder, FakeVolumetricLight and
| | 02:00 | drag it into the Hierarchy.
Let's double-click it to see where it came in.
| | 02:05 | It should be deep in the basement, and
there it is near one of the entry doors.
| | 02:16 | I'm going to turn off Overlays in the
Scene view so we no longer see the cross hair.
| | 02:22 | And finally, we'll take a
quick peek at projector lights.
| | 02:26 | So let's import two more packages, right-click,
Import Package, and this time we
| | 02:33 | want Projectors, Import.
| | 02:36 | And right-click, Import
Package, and we want Light Cookies.
| | 02:45 | And once again, Import.
| | 02:48 | Let's focus back on the barrels to get us
out of the basement, and I'll zoom back a ways.
| | 02:56 | Let's locate the Projector's folder in
the Standard Assets folder, and I'm going
| | 03:00 | to go ahead and close up some of my folders.
And here is our Projector's folder.
| | 03:05 | And we're going to drag the Blob Light
Projector into the scene in a shadowed area.
| | 03:10 | So the Blob Light Projector, and I'm
going to bring it right about here.
| | 03:16 | And now we need to lift it up, until
we can see the effect on the ground.
| | 03:23 | These are the little creatures you often
see parented to the characters in those
| | 03:27 | three-quarter overhead games like
World of Warcraft, and countless other world
| | 03:31 | building strategy games.
| | 03:33 | You could try a couple of textures out
for the cookies, and we can see quickly
| | 03:37 | that they will always need to set to clamp.
| | 03:40 | Let's delete the Blob Light Projector
now and try his opposite number, the
| | 03:45 | Blob Shadow Projector.
| | 03:48 | Right-click, Delete, and this time
we'll bring in the Blob Shadow Projector.
| | 03:54 | And I'm going to drag it into a
sunnier area, and it needs to be lifted up as
| | 03:59 | well, and we can see it casts the blob shadow.
| | 04:05 | This guy is regularly seen parented
to characters in games where real-time
| | 04:09 | dynamic shadows are either
not available or are too costly.
| | 04:13 | With some careful tweaking, I have
repurposed this one to add an ominous
| | 04:18 | darkness to the smoky area.
| | 04:20 | Let's import the Ominous Darkness
package and drag it in from the Prefabs folder
| | 04:25 | into the Hierarchy view.
| | 04:27 | So right-click, Import Package >
Custom Package, and from our Assets folder,
| | 04:34 | we're going to bring in OminousDarkness,
and click open, Import, and that guy
| | 04:42 | should come in the Prefabs folder.
| | 04:47 | Here he is right here, and I'll
bring them into the Hierarchy.
| | 04:51 | And if we double-click him, and rotate
our view around, we can see that our once
| | 05:01 | sunny area is now dark.
| | 05:04 | If you want to see the difference
you can deactivate, then activate.
| | 05:09 | For even more fun, I've created a
falling ash particle system that you can toss
| | 05:13 | in that area as well.
| | 05:16 | Let's bring that package in and put
it into the scene, right-click, Import
| | 05:22 | Package > Custom Package > Assets, and
FallingAsh, Import, and we'll drag him into
| | 05:34 | the Hierarchy panel.
And there it goes right there.
| | 05:40 | Before I click Play, I'm going to
click on Maximize on Play so we'll get the
| | 05:45 | full effect, now click Play, and
let's drive into our ominously dark area
| | 05:55 | now, by pressing W.
| | 06:01 | And we can see now falling ash,
smoke and fire, and darkness.
| | 06:11 | And now we can go ahead and exit Play mode.
I'm clicking Escape first.
| | 06:18 | So now you can see how light, and light related
effects, can add dramatically to your scene.
| | Collapse this transcript |
| Adding a flashlight| 00:00 | In the basement area, our player might
need a flashlight to find his way in the
| | 00:05 | dark, since there's nothing new involved,
I've prepared a flashlight Prefab to
| | 00:09 | help us get the player through the dark.
| | 00:11 | Let's start by importing the flashlight package
and dragging the Prefab into the hierarchy view.
| | 00:16 | Right-click, Import Package > Custom Package > Assets,
and let's open our Flashlight, and Import.
| | 00:30 | From the Prefabs folder, we'll go
ahead and bring it into the hierarchy.
| | 00:35 | To get started I'm first going to double-click
on my first-person controller, so
| | 00:41 | we can see him in the scene view.
| | 00:46 | Right now he's facing the barrels,
let's go ahead and turn him around, so he's
| | 00:51 | facing the cliff wall, now we can
select our flashlight and use, Move To View,
| | 01:02 | to get him lined up with the player,
and we'll need to rotate it, until we can
| | 01:10 | see our flashlight in front of him, and
that's probably a pretty good position right there.
| | 01:15 | So now I'm going to go ahead and open
the first-person controller's main camera,
| | 01:21 | and I want to put my
Flashlight in with my Weapon Handler.
| | 01:25 | When we made our original Cannonball
projectile, we fired it directly from the
| | 01:29 | Update function in the projectile script.
| | 01:32 | Now that we have a flashlight to handle,
we can make the whole process much more
| | 01:36 | generic by separating it out into a
separate script, it will send out the fire
| | 01:41 | message to which ever weapon or
other device is currently active, in the
| | 01:46 | Flashlight's case, Fire
will toggle it off and on.
| | 01:50 | So let's make a new script in our game
scripts folder and call it Trigger Finger.
| | 01:56 | Right-click, Create > Javascript, and
we'll name this one TriggerFinger, and
| | 02:03 | we'll open it in the
Script editor. Double-click.
| | 02:07 | In the Update function, we're going
to be checking for the fire one button,
| | 02:11 | you remember it, it's a virtual button
defined in Unity's Game settings Input Manager.
| | 02:17 | I'm going to go ahead and get the
first bit of code from the snippets file.
| | 02:20 | I'll go out to the desktop,
Exercise Files09/09-08, and open my code snippets,
| | 02:30 | and I'm going to copy this whole first
section, right-click, Copy, and we're
| | 02:36 | going to put this one
inside the update function.
| | 02:40 | So BroadcastMessage is a cousin of
SendMessage, where SendMessage calls the
| | 02:45 | specified function on any of the game
objects components, BroadcastMessage calls
| | 02:51 | it on the game object and all
of its children's components.
| | 02:55 | That means we'll be able to add
different weapons or tools and trigger them all
| | 03:00 | from the same script, as long as they
have a fire function to do the work.
| | 03:05 | Let's save the script and return to the editor.
| | 03:09 | And now we'll drag the new
TriggerFinger script onto the Weapon Handler and
| | 03:14 | deactivate the Proxy Weapon, and we'll
select the Proxy Weapon and deactivate it.
| | 03:22 | Let's click Play and toggle
the Flashlight off and on.
| | 03:25 | That's either using the left mouse
button or the Ctrl Key, Ctrl-Off and Ctrl-On,
| | 03:32 | and we'll exit Play mode.
| | 03:36 | The Flashlight already came in with the
script, it's called Toggle Light, I'll
| | 03:41 | open it, it's pretty simple.
| | 03:42 | It has the usual stuff we need to prevent it
from firing over and over again on a single input.
| | 03:50 | Let's go back to the editor and make
sure that the Proxy Weapon still works.
| | 03:55 | I'm going to deactivate the
Flashlight now and reactivate the Proxy Weapon.
| | 04:02 | I'm also going to turn off Maximize on Play.
| | 04:06 | So now when I click Play, and click on the
Fire button, there we go, so it still works.
| | 04:18 | Let's exit Play mode, I also need
to turn Gizmos off in the window.
| | 04:22 | So now we need a way to toggle between
the flashlight and weapon, or maybe even
| | 04:28 | cycle through any number of weapons,
we'll do that with a keyboard key press,
| | 04:33 | I'm choosing keyboard number pad 0,
let's head back to the TriggerFinger
| | 04:38 | script, and we're going to start by
adding a variable for the current weapon,
| | 04:44 | var, and I'm going to call it
currentWeapon, and that's been a being of type
| | 04:49 | int, because this is just a number assignment,
and we'll go ahead initialize it to zero.
| | 04:56 | This script is going to allow for
multiple weapons or gear, so we're going to
| | 05:01 | need to see how many children are in
the Weapon Handler object, right now it
| | 05:05 | just has two, but we need to give it a
variable as well, and that we're calling
| | 05:10 | totalWeapons, and it also is of type int.
| | 05:14 | For the start function, I'm going to go
and get the code from the Snippets file,
| | 05:18 | and this is the line we want.
| | 05:22 | Right-click, Copy, and then the Start
function, we're going to assign a value to
| | 05:30 | totalWeapons, and we're doing that
with transform.childCount, childCount gets
| | 05:37 | the number of children from the parent.
| | 05:40 | In the Update function, we'll increment
the weapon, then call a function to do
| | 05:44 | the actual work, and I'm going to get
that from the snippets file as well, and
| | 05:49 | we'll copy this guy,
| | 05:51 | right-click, Copy, and
we're going to Paste this one,
| | 05:56 | right-click, Paste beneath the fire one message.
| | 06:02 | In this section the brackets around
the zero tell us to check for the zero on
| | 06:07 | the number pad, next we increment the
current weapon by one, then we do a check,
| | 06:12 | if that number is greater than the
number of child objects we set it back to the
| | 06:17 | first, element zero,
| | 06:18 | and finally, we call the function that
does the work, it looks like I missed the
| | 06:23 | closing bracket for this bit of
code, I'll just add it in now.
| | 06:28 | Next we need the select Weapon function,
it includes something we haven't yet
| | 06:33 | used, a for to statement, that lets us
iterate through an array, and that's what
| | 06:38 | the children of an object are
internally packaged as, an array.
| | 06:43 | I'm going to get the code for
that from the snippets file.
| | 06:47 | And I want to make sure I get
the closing brackets for that,
| | 06:52 | right-click, Copy, and this is a
different function, so down below my Update I'm
| | 06:59 | going to use Ctrl+V to paste it in.
| | 07:03 | A for loop uses a variable,
traditionally I, and that's assigned the first
| | 07:08 | value, in this case zero, the first
element of the child array, and an end
| | 07:14 | value, which is going to be the child
count, which is just the length of the
| | 07:18 | array, and finally instead of
changing its active property to true or false
| | 07:23 | directly, we use set active recursively.
That will apply the value to the object
| | 07:29 | and any of its children. And finally we
need to add a line to the Start function
| | 07:34 | to initialize the first weapon.
| | 07:36 | In the Start function we're going to call our
SelectWeapon function and pass it element zero.
| | 07:45 | And now we can save the script.
| | 07:49 | I'm going to deselect my Proxy Weapon,
and then we'll click Play and use 0 on
| | 07:54 | our keypad to cycle through the weapons,
we should be able to see them become
| | 07:58 | active and inactive as
well as change in the scene.
| | 08:03 | So clicking Play, I click my 0, and
the Proxy Weapon is active, click it again,
| | 08:09 | nothing is active, and I click it
again, and now the Flashlight is.
| | 08:14 | Let's go back and see why it turns
both off before it restarts at zero, and
| | 08:19 | let's exit Play mode.
| | 08:20 | Let's go back into our script and see
why it cycles through Flashlight, Proxy
| | 08:25 | Weapon, and neither before it starts up
again. Because we've used greater than
| | 08:31 | total weapons here, instead of
greater than or equal to, we get one number
| | 08:35 | that's outside the child count number,
this works in our favor because now we
| | 08:40 | can have no weapon, the flashlight, or the
proxy weapon, and we'll head back to the editor.
| | 08:47 | Now the only issue is the Crosshair, if
we made a child of the proxy weapon it
| | 08:52 | would inherit its parents transform
and would quickly go missing, so let's
| | 08:56 | just disable it for now.
| | 08:58 | When we get to the chapter on Unity GUI
we'll be able to replace it easily, so
| | 09:02 | I'm going to select the
Crosshair here and deactivate it.
| | 09:07 | In this video we've used a for loop
to iterate through an object's children
| | 09:13 | and then used set active
recursively to change the state on all of the
| | 09:18 | children's children as well.
| | Collapse this transcript |
| Exploring waypoints and death zones| 00:00 | In the next chapter we'll be moving
our player onto a new area, a platform
| | 00:04 | jumper setup over the chasm. And, of
course, the first thing he'll try is
| | 00:09 | jumping into it. So let's start by moving our
first-person controller to the lower platform.
| | 00:15 | I'm going to focus on the lower
railing rope to get there quicker.
| | 00:19 | In Structures for Scene, inside the
building group, I'm going to double-click on
| | 00:24 | Lower Railing Rope, and use Alt and my left mouse
button to kind of spin around a little bit.
| | 00:30 | And now I can go up and get my first-
person controller, and use, Move
| | 00:37 | To view, to get him there quickly. I'll
need to move them back, and I want to
| | 00:42 | make sure that he's at a good height
above the floor, if he intersects it he
| | 00:48 | might drop through it, so I'm going to
leave them a little bit higher, and we
| | 00:53 | want to click Play and make sure.
Yep, and he stays put, so he's good.
| | 01:02 | I also want to spin him around, so he
is facing out towards the other side,
| | 01:09 | let's click Play, and see how helpful the
chain is from keeping us from going over.
| | 01:14 | I'm going to click Play, Click W, and
then I'm hitting my spacebar, and I'm
| | 01:21 | falling off into the abyss.
So let's click Escape and get out of Play mode.
| | 01:29 | It turns out the guardrail doesn't do a very
good job, we can jump over it into the abyss.
| | 01:34 | A common feature in several different
genres is, the death zone. As soon as the
| | 01:40 | player falls somewhere where we don't
want him to have access, we move him to
| | 01:43 | either a preset or maybe even a random location.
| | 01:47 | These instant destinations could be
referred to as spawn points, especially when
| | 01:51 | instantiating enemies or other Prefabs.
| | 01:54 | When used as goals, as in a racing
game, they are often called waypoints.
| | 02:00 | Let's make a spawn point at the
first-person controller's position.
| | 02:04 | Let's focus in on his current position
in the Scene view and make a new empty
| | 02:09 | game object, Create Empty, and
we'll name this one Waypoint Start.
| | 02:17 | It's created right where we want our first-
person controller to appear after a fall.
| | 02:22 | Now let's make a cube and name it Death zone,
| | 02:26 | GameObject > Create Other > Cube, and
now we're going to want to rotate our view
| | 02:34 | a little bit and zoom out, and we will
want to move this out towards the center
| | 02:42 | and then scale it both directions, and
let's rotate our view again and maybe
| | 02:52 | we'll give it a little bit more height.
| | 02:54 | And then we're going to drop it down
into the chasm a little ways, we'll just
| | 03:02 | give him a little way to
fall before it catches him.
| | 03:05 | We really only need its box collider,
so you can remove the mesh render if you
| | 03:09 | want, and then we need to set
our Box Collider to Is Trigger,
| | 03:14 | right-click, remove the mesh render,
and for our Box Collider we're going
| | 03:20 | to turn on Is Trigger.
| | 03:22 | Now for the script. Let's create a
new script in the Game Scripts folder.
| | 03:28 | Right-click, create Javascript, and
we're going to name this one Death Zone, and
| | 03:34 | we'll double-click to open it.
| | 03:38 | On the off chance we want our player
to come back to life on different spots
| | 03:42 | we'll make the waypoint variable an
array, so let's add, var waypoint, of type
| | 03:54 | Transform, and to make it an array we
give it our two brackets, and once again
| | 04:02 | auto complete adds things that I don't want.
| | 04:06 | So let's save the script and go back to
the editor and drag the Death Zone onto
| | 04:13 | the Cube Object which I also
need to remember to name Death Zone.
| | 04:20 | In the Inspector, let's open up the
Waypoint array, and since we only have
| | 04:26 | one spawn point, let's set its size
to one, and we can drag our waypoint
| | 04:31 | start object into it.
| | 04:35 | And I'm going to go out to the snippets
file and grab our on trigger inter function.
| | 04:40 | Exercise File09/09-09/Code Snippets, and
I'll copy all of the OnTrigger Enter function,
| | 04:52 | right-click, Copy, and because it's a
function, I'm going to Paste it, Ctrl+V, in
| | 05:00 | below the other functions,
so we can save our script now.
| | 05:05 | Before testing, we need to make sure
that the first-person controller is
| | 05:08 | tagged as a player.
| | 05:11 | So we'll select him, and
change him from Untagged to Player.
| | 05:19 | Now let's click Play and test.
| | 05:22 | If I run him off the ledge with my W Key he
falls, and then he has popped right back up.
| | 05:29 | So let's exit Play mode.
| | 05:31 | Just in case you want to spawn them
in different places, let's add the code
| | 05:35 | to choose a random position from the
array of waypoints, I'll get the next
| | 05:39 | bit of code from the snippets file first, and
I'll scroll down, and first we need a variable.
| | 05:46 | I'll get the next bit of code from
the snippets file, and back in the script
| | 05:53 | editor, inside the if clause, I'll paste it in.
| | 05:59 | I'm assigning a random number between
zero and the length of the wave point to a
| | 06:04 | variable called element.
| | 06:06 | I'm going to go out and
get the next line of code.
| | 06:11 | Right-click, Copy, and this one
replaces the victim line, Ctrl+V for Paste, and
| | 06:21 | instead of zero in here, we have element,
which is going to be the random number.
| | 06:27 | I'm going to tidy that up a little bit.
| | 06:29 | So I'll save the script
and head back to the editor.
| | 06:34 | Now that we've made a Death Zone you
might want to put another one below the
| | 06:37 | water over at the waterfall and give
it some suitable waypoints of its own.
| | Collapse this transcript |
|
|
10. Keyframing AnimationPlatformer setup: Snaps and cosines| 00:00 | In this chapter, we'll be delving
into a lot of keyframe animation.
| | 00:04 | Before we do, though, let's get
some new assets to play with.
| | 00:08 | The new zone is the Platform Jumper Zone.
| | 00:10 | It lies over the chasm, so let's import
the Platform Jumper Assets Start Package.
| | 00:17 | Right-click, Import Package > Custom
Package > Assets/PlatformJumperAssetsStart
| | 00:29 | and Open and then Import.
| | 00:35 | It contains some platforms, a couple of
invisible walls, obstacles, and some power-ups.
| | 00:41 | Let's drag the new Prefab Platform
Objects Start from the Prefabs folder
| | 00:46 | into the Hierarchy view.
| | 00:47 | It should be aligned with the lower
ledge where the basement lets out.
| | 00:51 | And it looks about right.
Let's start by deactivating the invisible walls.
| | 00:56 | They'll keep our player from falling sideways
'til we deal with the navigation scripts.
| | 01:01 | Open the Platform Assets Start and the top two,
Invisible Wall Left and Invisible Wall Right.
| | 01:10 | Unity has a very robust vertex snapping system.
Let's use it to tidy up the first few platforms.
| | 01:16 | I am going to pan over a little bit, and I
might want to turn off my Scene Lighting.
| | 01:23 | We start by selecting the object we
want to move, I am going to select the
| | 01:29 | second platform, and then we hold down
the V key--V as in Victor--as you move
| | 01:34 | the cursor around, it
snaps to the various vertices.
| | 01:38 | With my V key still down, I am now
going to click and drag, and it snaps to
| | 01:45 | the closest vertex.
Let's try that again.
| | 01:49 | I'll select this platform, press my V
key, move my cursor over it and drag it
| | 01:56 | until it snaps to the correct vertex
and my view over it looks like this guy's
| | 02:01 | a little high, so I am going to select him.
This time I'm going to snap to the
| | 02:06 | lower vertex, so I press my V key, click and
drag, and I want to snap it to the bottom vertex.
| | 02:15 | And always use your Alt and sort of rotate around
and make sure you've got everything correct.
| | 02:20 | You can also snap objects in units
around the scene by holding the Ctrl or
| | 02:24 | Command keys while moving the objects.
| | 02:28 | I'm going to press Ctrl and pull up, and
you can see that as the mouse moves the
| | 02:37 | platform snaps to--it's
probably set to 1 unit as a default.
| | 02:42 | You can change the snap
amounts from Edit > Snap Settings.
| | 02:50 | Before you go off adding more
complexity to the platform setup, let's make a
| | 02:54 | couple of scripts to animate the platforms.
| | 02:57 | The scripts will be very useful
and generic, well worth the effort.
| | 03:01 | So let's create a new script
and name it V_position cycler.
| | 03:06 | In my Game Scripts folder, right-click,
Create > Javascript, and this is going to be
| | 03:15 | V for vertical, underscore PositionCycler,
and well go ahead and open it by
| | 03:25 | double-clicking to get to the Script editor.
| | 03:29 | Since we started a new chapter, let's go
ahead and take the opportunity to clean
| | 03:33 | up some of our open scripts.
I'm going to close them off in their tabs.
| | 03:40 | We are going to need several variables
for this, so I'm going to go over to the
| | 03:43 | Snippets file and get them.
| | 03:46 | Exercise Files10/10_01/Code Snippets.
And we want all of these.
| | 03:56 | Right-click, copy, and we'll make some room
for them up here and Ctrl+V to paste them in.
| | 04:06 | This is for the vertical scroller so
we've got an upRange and a downRange, and
| | 04:12 | we've got a waveOffset,
I'll explain that in a minute.
| | 04:15 | We also have the Y Start Position, so
the upRange and downRange are going to be
| | 04:20 | added to the start position so
it knows where to cycle between.
| | 04:25 | In the Start function we'll need to get the
starting position, the object's current Y location.
| | 04:30 | I'm going to go out to
Snippets and get that one to.
| | 04:35 | Right-click, Copy, and this one goes in
the start function and Ctrl+V to paste.
| | 04:44 | And now we are going to change our
Update function to a FixedUpdate, and this is
| | 04:49 | so that the speed will be the same
across all platforms, and that's got quite a
| | 04:53 | bit of stuff in it, so I'm going to get this.
| | 05:00 | Right-click, Copy, give myself
some room and Ctrl+V to paste.
| | 05:08 | So let's see what we've got. The first
two lines calculate the position from the
| | 05:12 | offset and the up and down range.
| | 05:14 | By putting them in the Update instead
of the Start function, you can adjust
| | 05:18 | positions at runtime
without restarting each time.
| | 05:21 | The next line is the Mathf cosine
function and uses the variable's values to
| | 05:27 | adjust the speed and height of the cosine wave.
| | 05:30 | waveOffset adds an offset to where we
are in the cosine curve, and the last line
| | 05:38 | adds it all up for the platform's position.
If the math is confusing, don't panic.
| | 05:44 | As you get more confident with scripting,
you'll find tons of script from the Unity community.
| | 05:49 | Bottom line, as long as you can figure
out what it does and what it needs,
| | 05:53 | you don't necessarily need to
understand how it does it.
| | 05:57 | Let's save the script and
head back to the editor.
| | 06:01 | Now we want to go ahead and drag the
script onto the Platform Short Move V object.
| | 06:08 | So here is my V_positionCycler script,
and I want to move onto PlatformShort,
| | 06:13 | Move V, that will be this one right here.
| | 06:18 | Let's go ahead and
deactivate the Terrain for now.
| | 06:24 | Select the Terrain, and we'll
just deactivate the whole thing.
| | 06:28 | To get an idea of how far to raise that
platform, we can use the Ctrl or Command
| | 06:33 | key to snap while moving it
up, then move it back down.
| | 06:38 | I'm going to zoom out a little bit, adjust
my view, select my platform, I'm going to
| | 06:45 | hold my Ctrl key, and then
count as it snaps upward.
| | 06:49 | 1-2-3-4-5-6-7-8-9.
| | 06:56 | So it looks like I'm going to need to
move it up about 9 on the vertical.
| | 07:05 | I can't see my variables here, so I am
going to go back and make sure that my
| | 07:09 | script got saved properly.
| | 07:12 | And into the Script editor by double-
clicking, and sure enough it wasn't.
| | 07:17 | So I'll save back my scene.
And now I've got my variables.
| | 07:22 | So we decided that the upRange needed to be about
9 units, and I'll leave the downRange as 1.
| | 07:29 | Let's click Play and see how it works.
| | 07:35 | It goes down 1 and up 9,
and we'll exit Play mode.
| | 07:42 | The platform moves up and down using a
nice cosine wave for speed and height.
| | 07:46 | The horizontal version is pretty much
the same, so I have included it in the
| | 07:51 | Videos Asset folder and
also in the snippets file.
| | 07:54 | You can pull the script into the Game
Scripts folder using Import New Asset.
| | 07:58 | So I am going to select my Game Scripts
folder, right-click, and Import New Asset,
| | 08:06 | and here it is, H_PositionCycler.
Import, and there we go.
| | 08:13 | I am going to put this one on
PlatformLong Move H, and I'll select it, and mine
| | 08:21 | ended up needing to be about 16.8 to
the left, and I slowed it down quite a bit
| | 08:27 | and set the speed to 0.1.
You can hit Play and test it if you'd like.
| | 08:31 | We'll be taking a shortcut through
the platforms to get the game developed
| | 08:35 | quicker, but feel free to make duplicate platforms
and make use of the snapping functions to arrange them.
| | Collapse this transcript |
| Using the Animation view| 00:00 | For simple looping animations,
scripts can be very useful. Once you get the
| | 00:04 | formula worked out, you can apply
the script to any object, adjust the
| | 00:08 | parameters, and you're good to go.
| | 00:10 | But for one-off animations or complex
animations there is nothing like good old
| | 00:14 | keyframing to make things look good.
| | 00:17 | Besides the platforms, we also got a Heart
and a key Prefab added to the Prefabs folder.
| | 00:22 | Let's drag the Heart into the scene
over the first couple of platform sections.
| | 00:28 | In my Prefabs folder here is my Heart,
and I'm going to drag it into the scene,
| | 00:34 | and I can see it is sort of embedded in
the platform, so I know it's going to be
| | 00:39 | in a pretty good position, and
then I'll go ahead and drag it up.
| | 00:43 | We can use the scene gizmo to get to a
right view by clicking on one of the side
| | 00:49 | arrows, left, back, and right, so there we go.
| | 00:54 | Then I am going to move it just
high enough so that the first-person
| | 00:59 | controller has to jump for it.
And we'll go ahead and zoom in, and there we go.
| | 01:04 | So now, let's go ahead and create a
new camera so we can see it in both views,
| | 01:08 | the scene and the game view.
| | 01:11 | Game Object > Create Other > Camera,
let's leave aside the Listener on for now.
| | 01:18 | We'll need it when we disable the
first-person controller's camera.
| | 01:22 | Now from the Game Object menu,
we'll use Align With View.
| | 01:28 | In the Inspector, let's adjust the field of
view down, so it looks similar to the scene view.
| | 01:34 | And that's pretty good!
| | 01:36 | If we click Play, the view might shift
slightly, but we'll have a pretty good
| | 01:40 | view of our target objects.
| | 01:42 | So let's go ahead and
look at Key Frame Animation.
| | 01:44 | From Window choose Animation.
| | 01:50 | The widow comes up showing the main camera,
the object that's currently selected.
| | 01:54 | Let's expand the camera component.
| | 01:56 | Any variables exposed to the Inspector
are also exposed in the Animation View.
| | 02:03 | Now let's go ahead and select the Heart.
| | 02:07 | We need two things before we can
animate with keyframe animation, the first is
| | 02:11 | an animation component, and
the second is an animation clip.
| | 02:16 | As soon as we create a clip, the animation
component will be automatically added.
| | 02:21 | So let's click in the blank area next
to the object name bar, the option to
| | 02:26 | Create New Click pops up.
| | 02:28 | Let's select it. The browser
opens up to our Assets folder.
| | 02:33 | The key Prefab already has a couple of
animations, they are in a folder called
| | 02:38 | AnimationClips, and we're going to go
ahead and use that for all of our clips.
| | 02:41 | So I'm going to open my AnimationClips folder,
and I want to name my new animation heart beat.
| | 02:49 | All lowercase isn't really necessary,
but it will help me remember when I'm
| | 02:53 | working with an animation clip,
and now we can click Save.
| | 02:57 | In the Inspector we can see the animation
component that was automatically added.
| | 03:02 | In the animation view, let's go
back and select the three scale tracks.
| | 03:08 | Before anything can happen, we also need to
click the Play button, that's the red dot.
| | 03:14 | Now we can see current values, a time
indicator at frame 0, and we also note
| | 03:21 | that the Play controls at the top of
the editor have turned red to remind us
| | 03:26 | that we're in record mode.
| | 03:28 | The first thing we want to do is set a
key for the selected tracks to define the
| | 03:32 | start frame of the animation.
| | 03:34 | That's the little button with the Add
Keyframe tooltip, the one to its right is Add Event.
| | 03:40 | Don't click that one by mistake.
| | 03:43 | So let's go ahead and
click the Add Keyframe button.
| | 03:46 | A white key is added at the top of the
timeline, this is similar to a dope sheet
| | 03:51 | that shows the keys on the timeline.
| | 03:54 | In the list, the track keys are color coded
a pale red, green and blue. RGB equals XYZ.
| | 04:02 | When animating more than one track like
we are with scale, it's usually easiest
| | 04:06 | to do it in the viewport.
| | 04:08 | So to start our animation, the first
thing we need to do is to move the timeline
| | 04:13 | indicator to where we want
the animation to finish up.
| | 04:16 | The timeline shows seconds and frames.
The default is 60 frames per second.
| | 04:22 | So let's move our indicator to 1 second,
that's also 60 frames as we can see over here.
| | 04:28 | Now in the Scene view, let's go ahead
and scale the Heart up to about 1.3, and
| | 04:36 | I'll be watching the Inspector in
the scale section to see my numbers.
| | 04:44 | And that's close enough, the curve--yes,
it's called a curve even when straight--
| | 04:49 | doesn't appear to have changed.
| | 04:51 | But let's go ahead and click the
Animation View's Play button. The animation
| | 04:58 | plays, looping in the viewport, and as
soon as you click it again, the graph is
| | 05:04 | automatically zoom to fit.
| | 05:06 | We can also scrub through the animation
manually by dragging the indicator up on the time bar.
| | 05:13 | The frames show to the left
of the Add Keyframe button.
| | 05:18 | So let's see about improving the animation.
| | 05:20 | If we drag around the keys at frame 60--
yes, there's three in one spot--and
| | 05:25 | right-click, we can change them to free
smooth to get the Bezier handles that
| | 05:31 | will allow us to affect the curves.
| | 05:33 | For those of you who know your way around
curve editors, you can also set the
| | 05:37 | in and out tangent
separately in the right-click menu.
| | 05:40 | So let's make some changes. Grab the
handle for each key and drag it up level
| | 05:45 | with the non-animated part of the curve.
| | 05:47 | I'm going to click, and
again, and one more time.
| | 05:56 | And we'll repeat for the keys at frame 0.
| | 06:00 | Drag a region, right-click, Free
Smooth, and we'll drag the handles down.
| | 06:09 | We now have a classic ease-in/ease-out curve.
| | 06:13 | If you're new to curve editors,
reading them is easy, time is always on the
| | 06:17 | horizontal, and the value that is
getting changed is on the vertical.
| | 06:22 | So the flatter the curve, the slower the
animation, that's less change over time.
| | 06:28 | The steeper the curve, the faster
the animation, more change over time.
| | 06:33 | A change in direction of the curve
will make the values go backwards.
| | 06:37 | So our animation starts out slow, speeds up,
then slows back down. Let's click Play.
| | 06:46 | It's a little hard to see the results,
so let's slow down the animation a bit,
| | 06:51 | and we'll stop play for a minute, and we
are going to click the white key in the
| | 06:55 | timeline at 1 second.
| | 06:57 | I am going to drag it to 130.
Let's exaggerate it and move it to 2.
| | 07:07 | Now we'll click Play, and
you can see it's a lot slower.
| | 07:15 | We'll Stop Playback again, and maybe we
want to adjust the amount of scaling.
| | 07:20 | We could move the time indicator to
its new position in the timeline, then
| | 07:24 | adjust it in scene view again, but
for more control, we can enter numbers
| | 07:29 | directly in the track we want to change.
So we could change them here.
| | 07:34 | We could also move them in the graph itself.
So let's see what happens in the actual game.
| | 07:39 | We'll close the animation view
and click Play and nothing happens.
| | 07:46 | Let's Exit Play mode again. Let's look
over in the animation component to see if
| | 07:51 | we can figure it out.
| | 07:53 | It is set to play automatically, but
there's no clip selected as the default animation.
| | 07:59 | Let's open the Animations array, it
shows one clip, heart beat, but we can't drag
| | 08:04 | it to the animation field from there.
| | 08:07 | If we click on the browser to load our
default animation, all kinds of animation
| | 08:12 | clip show up which should remind you
that naming your clips well is important.
| | 08:17 | The best way to get it loaded often is
to click on it in the array located in
| | 08:21 | the project view and drag it in.
| | 08:24 | It is pretty easy to figure out which one
we want here, so I'm going to select it.
| | 08:29 | Now let's click Play and Exit Play mode.
| | 08:33 | As you might have suspected,
it scales up and stops.
| | 08:36 | To control looping and related
properties, we can either select the clip itself
| | 08:41 | and change its wrap mode in the
Inspector, so I'm going to go up and find it
| | 08:46 | here, Animation clips, here is heart beat.
| | 08:52 | So we can change our wrap mode here.
I'll set it to Loop. Or our other option is
| | 08:59 | that we can open the Animation
Window--and of course we need to select our
| | 09:05 | object, make sure we are on the right
clip--and down here to the right we can
| | 09:12 | choose from here as well.
| | 09:14 | And this one really should Ping Pong,
so I'm going to change it to Ping Pong.
| | 09:18 | If we zoom out in our graph--and we
can do that the same as zooming out in
| | 09:22 | the viewports with middle mouse ruler--we
can see that the curve is now Ping Ponging.
| | 09:29 | You can focus back on the actual
animation the same as you do in the
| | 09:33 | viewport with the F key.
So I'll press my F key, and I'm focused back in.
| | 09:40 | I'm going to go ahead and speed mine
up by moving that last key back to 1.
| | 09:45 | So let's go ahead and
close the Animation Window.
| | 09:48 | So there you've had your first taste
of animation in Unity's animation view.
| | Collapse this transcript |
| Working with multiple animation clips| 00:00 | So we got the Heart Animation looping and animating
in the scene with no scripting, easy, huh?
| | 00:06 | Well, what about when our player
intersects its collider, which by the way,
| | 00:09 | is set to as trigger.
| | 00:11 | We could just have it disappear,
but what if we wanted to call a
| | 00:15 | different animation clip?
Let's do that next.
| | 00:18 | First we need a new animation, so let's select
the Heart and open the Animation View.
| | 00:24 | Window, Animation, you can see it also
can be called up with Ctrl+6.
| | 00:32 | Click the Clip Selection Box and select Create
New Clip, once again, we'll make sure it
| | 00:40 | goes into Animation Clips folder,
and we'll name this one heart score.
| | 00:49 | I like to name my animations after
the object first, then what it does,
| | 00:54 | that way all of the Objects Animation
Clips will be together in the browser
| | 00:58 | and the Project view.
| | 00:59 | Let's check out the Inspector. The new
clip has been added to the Animations
| | 01:05 | array, so let's have the heart
pop up, then shrink to nothing.
| | 01:10 | First we need to turn on the Animation
button, and then we're going to select
| | 01:15 | the position Y track, and this time
we're going to tell it to create a curve.
| | 01:21 | We do that by clicking on the little bar to
the right of the field and choosing Add Curves.
| | 01:27 | It will automatically set keys at
wherever we are in the timeline.
| | 01:32 | So now let's move to frame 20, and
I'm going to watch this as I move my time
| | 01:39 | indicator, and I'm going to move
it up in the viewport about a meter.
| | 01:45 | Let's click Play and watch it and Stop.
| | 01:51 | When it stops, we're shown all three
position tracks even, though, we only animated Y.
| | 01:56 | So let's scale the heart after it pops up.
| | 01:59 | Select all three of the scale tracks
this time, and I'm holding my Ctrl key
| | 02:05 | to add to my selection, and we're
going to move the time indicator to frame
| | 02:09 | 20, and once again we're going to use the
little bar, click on it, and say Add Curves.
| | 02:17 | Let's zoom and pan the graph view
until we can move the time indicator to
| | 02:21 | frame 60, or second 1.
| | 02:24 | I could actually zoom in on mine,
so I'm rolling my middle mouse.
| | 02:29 | So we'll go ahead and move the time
indicator to that frame, frame 60, 1 second,
| | 02:36 | and in the viewport we're going
to scale the heart up to about 1.5.
| | 02:41 | Once again, that's easily done by
using the regular scale function, and I'm
| | 02:46 | going to watch my Inspector to see
when my scale values reach 1.5-ish.
| | 02:54 | Next we'll have it hold the
scale, until frame 120, 80 frames.
| | 03:00 | So let's scrub the time indicator to
that frame, and this time we're going to
| | 03:05 | use Add Keyframe--this button--to add
keys, and this is going to do all three
| | 03:13 | tracks, since we've got them all selected.
| | 03:15 | And finally, let's add our last key at 110, 1.5.
| | 03:21 | I'm going to use my middle mouse
button to pan the view over a little bit.
| | 03:26 | So now I'm going to move my time indicator to
110, and I want to scale the heart down to 0.
| | 03:34 | This is one time when it's going to be
easiest to do clicking in the Inspector.
| | 03:43 | Click 0, Click 0, Click 0.
| | 03:48 | Okay, let's go ahead and focus in on
the curve. You'll need to re-click in the
| | 03:52 | animation view to change focus and then
press the F key, and there we've got our curve.
| | 04:00 | It looks like our curve went a little
bit wonky. Let's use the middle mouse
| | 04:04 | ruler to zoom in on the area
that should've stayed flat.
| | 04:11 | The problem is the
interpolation between the two scaled keys.
| | 04:15 | To fix that, I'm going to drag a
region around the left keys and from the
| | 04:19 | right-click menu change
their Right Tangent to Linear.
| | 04:27 | Then I'll select the right keys, right-
click and change their Left Tangent to
| | 04:33 | Linear, and now our curve looks okay.
| | 04:37 | If you're fussy, you could even adjust the
Tangents for a smoother in and out on the two.
| | 04:42 | Let's click Play and see the timing and Stop.
| | 04:50 | We only see the time segment showing in
the Animation View, so let's drag
| | 04:54 | the left side of the bottom slider to
the left to show the entire animation.
| | 05:00 | Now if we click Play, we see
the whole thing, then we'll stop.
| | 05:08 | Just to note here, we don't need to
manually add keys at the start of the scale
| | 05:12 | tracks or the end of the position tracks.
Unity considers the whole time frame the clip.
| | 05:18 | To make things easier to view, we can
also filter out for only animated tracks
| | 05:24 | in the left, and we can toggle
between Show All and Show Animated.
| | 05:29 | So now we have got an
animation clip for our power-up.
| | 05:33 | You can save the scene if you want to,
but the Animation clip is saved in the
| | 05:37 | clip file every time you change it.
| | Collapse this transcript |
| Triggering keyframe animations| 00:00 | Now let's see about
triggering a new animation clip.
| | 00:03 | In the Game Scripts folder, let's
create a new script and name it PowerUp.
| | 00:08 | Right-click, Create, Javascript, and
we'll call this one PowerUp, and let's
| | 00:18 | go ahead and open it.
| | 00:20 | Double-click to bring up the script
editor. Let's start by making a variable
| | 00:25 | for the animation clip, and we're going to
call it clip, var clip of type AnimationClip.
| | 00:38 | And now, let's turn the Update into an
OnTriggerEnter function, and inside it
| | 00:44 | we're going to add animation.Play, and
Play is a function, so it's capitalized,
| | 00:53 | and it gets the open and closing parentheses.
| | 00:56 | So without specifying an animation name,
Unity will play the default clip, but
| | 01:02 | we need it to play the other
clip, the heart score clip.
| | 01:06 | We'll feed in the correct clip, but we
need to use its name as the function argument.
| | 01:12 | So our variable clip, which is the actual clip,
but all we really need is its named property.
| | 01:21 | Let's go ahead and save the
script and head back to the editor.
| | 01:25 | And we need to add the new script to the Heart.
| | 01:31 | We will select the Heart, find our new script,
and we need to bring in the animation clip.
| | 01:40 | We can click on the browser
and here it is, heart score.
| | 01:46 | Let's click Play and jump the
first-person controller into it.
| | 01:50 | Remember, spacebar to jump, click
Play and test by jumping the first-person
| | 01:58 | controller into it with the spacebar. It works.
| | 02:02 | So let's Exit Play mode. If you need
to adjust any of the timing, you can just
| | 02:07 | select the heart, open the Animation
view, select the heart score clip, and make
| | 02:13 | adjustments that you need.
| | 02:15 | Before we continue with the PowerUp
script, let's go ahead and load a little
| | 02:18 | package I've made for us,
it's called ScoreKeeper.
| | 02:22 | It's just an empty game
object with a simple script.
| | 02:26 | So right-click, Import Package, Custom
Package, and from our Asset folder,
| | 02:38 | we'll bring in ScoreKeeper.
Clicking Open and then Import.
| | 02:46 | It should turn up in our Prefabs folder,
and there it is, and we'll go ahead and
| | 02:53 | drag it into the scene.
| | 02:55 | Let's take a quick look at the
ScoreKeeper script, double-click it, and you can
| | 03:00 | see it's really simple. It has a
variable named score which is initialized at 0,
| | 03:04 | and then it has a function called UpdateScore.
| | 03:08 | It has a local variable called points
that we will be passing to it, and that
| | 03:12 | increments the score with the
number of points we feed it.
| | 03:16 | Let's head back to our PowerUp script
now in the other tab, so we're going to
| | 03:20 | need a couple of new variables.
| | 03:21 | I'm going to go out to the
Snippets file and Copy them.
| | 03:27 | Exercise Files10/10-04/Code_Snippets,
and we need these right here,
| | 03:36 | pointValue and ScoreKeeper.
| | 03:40 | Right-click and copy, back into the
Script editor, and we'll put them right
| | 03:45 | beneath our first variable.
| | 03:47 | The pointValue is the value for each of
our PowerUps and the ScoreKeeper is the
| | 03:52 | game object that we just
imported into our scene.
| | 03:55 | He's keeping track of the overall score.
| | 03:58 | Let's go ahead and get the next bit of
code, and for the ScoreKeeper--I'm going
| | 04:03 | to right-click and copy--we're going
to send a message to its UpdateScore
| | 04:09 | function to tell us what point value it
should update the score by, and we can
| | 04:14 | put this one underneath the Animation,
paste, and then we may as well go ahead
| | 04:20 | and put some sound effects in there.
| | 04:22 | And we're going to var a sound
effects variable to hold an AudioClip,
| | 04:28 | right-click, Copy, add that
variable up here and grab our final line.
| | 04:35 | Right-click, Copy, and we'll
Play our sound effects right here.
| | 04:41 | Tab over, and I'm going to be neat
and tidy and give myself one open line.
| | 04:46 | Okay, so we're ready to save our script.
The first thing we need to do is make
| | 04:51 | sure we put our PowerUp script on the heart.
On my console, it's giving me an error.
| | 04:56 | I need to go back to my Script editor
and make sure I capitalize GameObject.
| | 05:01 | That will make it happy. Now I'll click Save,
and now we can go back to the editor.
| | 05:08 | In the Inspector, with our heart selected we
now need to fill in our two new parameters.
| | 05:13 | ScoreKeeper, we'll drag him into that
parameter. And for the Sound Effects,
| | 05:20 | I'm going to click on the browser and choose Ding.
| | 05:25 | The heart and the key Prefabs already
have an audio source with the Rolloffs set
| | 05:29 | to Linear, so we should
be able to hear it easily.
| | 05:33 | Let's go ahead and click Play and see what
happens now, W, spacebar, and there we go.
| | 05:41 | You'll notice that when we trigger
the new clip to Play, the first one is
| | 05:45 | automatically turned off. Let's Exit
Play mode, and if your first-person
| | 05:51 | controller is falling off the platforms
too often, you can go ahead and activate
| | 05:55 | the two invisible walls again.
| | Collapse this transcript |
| Animating transparency| 00:00 | Let's add another power-up, the key.
| | 00:03 | Go ahead and drag the key Prefab
into the Hierarchy view next to the
| | 00:07 | Heart, Prefabs, Key.
| | 00:11 | I'm going to drop it near the heart, so
I can make sure it's going to be lined
| | 00:16 | up with platforms, and then I can go
ahead and move it over, according to the
| | 00:21 | Game Window, I'm not, so I'm going to
go ahead and go into perspective or maybe
| | 00:27 | even top view, and move it into place.
| | 00:32 | And then I'll switch back to my right view,
by clicking on the Scene gizmo. There we go!
| | 00:41 | So now we have a new power-up, and it
already has some animation clips added
| | 00:45 | to it, but we're going to try something
that ought to be easy but has a catch to it.
| | 00:49 | We're going to have this guy fade out on
score, so let's start by opening the
| | 00:55 | Animation View and check
out its Key spin animation.
| | 00:59 | Window, Animation, and it's already
set to the Key spin clip, so let's
| | 01:06 | click Play and watch it.
| | 01:11 | And you can see it goes around, and
we'll check out its key spin animation.
| | 01:16 | It's pretty straightforward.
| | 01:18 | Now let's select the keyscore
clip and watch its animation.
| | 01:23 | We'll click on our clips area and select
keyscore, and we'll go ahead and click Play.
| | 01:31 | So now it flips up, and it turns
around, and we can stop Playback.
| | 01:37 | For the fadeout, we need to access the material.
| | 01:40 | That's found in the
material track, brass in this case.
| | 01:44 | So click this Open, and we're going to
need the color.a or Alpha track at frame
| | 01:51 | 90, so let's turn on our Record button
and move the time indicator to frame 90,
| | 02:00 | we're going to click AddCurve.
| | 02:03 | So click on the little bar and Add
Curve, and it gives us a key at frame 90,
| | 02:11 | and now we're going to set the Alpha
value to 0, and I'm going to do it right
| | 02:16 | in the track itself.
| | 02:19 | So at frame 90, it's fully transparent.
| | 02:24 | At about frame 60, when it's in the
middle of the other animations, we want it
| | 02:28 | to still be visible.
| | 02:31 | So I'm going to add key, in
this one I'm going to set to 1.
| | 02:37 | 1 is fully visible, 0 is fully
transparent, and if I focus in on my animation
| | 02:45 | now with my F key, we can see that at 1,
it should be fully visible and at 0
| | 02:51 | it's all the way transparent.
| | 02:53 | But if we look in the viewport, fully
visible when it should be transparent.
| | 03:01 | So what's the deal?
| | 03:01 | It turns out--and this is a very
important thing to remember in Unity--you must
| | 03:07 | use a transparent shader to be able to
affect the material's opacity through
| | 03:12 | its color parameter.
| | 03:14 | So let's select the key in the Prefab folder,
because we want to change any keys we're using.
| | 03:21 | So in the Inspector, we're going to
change its Shader from Specular to
| | 03:27 | Transparent Specular.
| | 03:32 | Let's go ahead and select our key in
the Hierarchy again, and now if we turn on
| | 03:39 | Animate and scrub through our timeline,
our key fades out as we expect it to,
| | 03:49 | and we can close the animation view.
| | 03:51 | So let's go ahead and add the
PowerUp script to the key and go ahead and
| | 03:55 | fill out its parameters.
| | 03:59 | Power-up onto the key, fill in its
parameters, point value of 5 is okay, we need
| | 04:07 | the scorekeeper object, and you can
choose a sound effect of your choice.
| | 04:12 | I'm going to choose PortalWhoosh.
| | 04:18 | And one more thing we need to do is we
need to assign the Clip, which is going
| | 04:25 | to be heart score, and in the Animation
component, let's double-click, and yes
| | 04:34 | it does have key spin as its default.
| | 04:36 | Let's click Play and test our two PowerUps.
| | 04:39 | I'm going to zoom out a little bit,
Click Play, W, spacebar. Oops!
| | 04:46 | I missed him.
| | 04:48 | Press S, and there I go.
| | 04:52 | So I'm going to Exit Play mode and
double check to make sure that my keyscore
| | 04:58 | was set as the clip.
| | 05:01 | And there's the problem.
| | 05:03 | I loaded heartscore.
| | 05:05 | Back to the browser, key score, and
now it should work, press W, and there we
| | 05:20 | go, and Exit Play mode.
| | 05:24 | So far we have just shrunk or faded
out the power-ups, we really need to
| | 05:29 | destroy them when they're finished
animating, but different objects are
| | 05:32 | finished at different times.
| | 05:34 | It turns out just like the audio clips, we
can get the length of the animation clips.
| | 05:40 | So let's open up our PowerUp script again.
| | 05:43 | I'll double-click it, and in the
Script editor, we're going to use a yield
| | 05:51 | WaitForSeconds with the
clips length plus a little extra.
| | 05:55 | I'm going to go out to my
Snippets file and grab that line.
| | 05:59 | Exercise Files 10/10-05/Code_Snippets,
and we'll grab both of these lines,
| | 06:08 | right-click, Copy, and we'll paste
it inside the OnTriggerEnter function.
| | 06:15 | Control V, so yield new WaitForSeconds,
and we are waiting for the clip length,
| | 06:21 | plus one extra second, and then
we're going to destroy the Game Object.
| | 06:26 | Let's save our script, click Play and
test one more time, and this time if
| | 06:32 | we watch the heart and the key in the
Hierarchy panel, we should see them disappear.
| | 06:38 | Click Play, and there they go.
| | 06:47 | Both of them have now disappeared from
the Hierarchy, and we can Exit Play mode.
| | 06:52 | So our two takeaways are if we need to
fade an object out, we need to make sure
| | 06:57 | that it has a transparency shader on it,
and we also found that we can get the
| | 07:02 | length of an animation clip using clip.length.
| | Collapse this transcript |
| Keyframing events| 00:00 | So, we've got a couple of power-ups
working, but they are looking a little sparse
| | 00:04 | despite our animations.
| | 00:06 | It would be much cooler to have maybe a
particle system explode at an opportune
| | 00:11 | moment during the timeline.
Well, guess what. We can do that.
| | 00:15 | Before we go any further, though,
let's go ahead and import a new package,
| | 00:20 | right-click, Import Package > Custom
Package and from our Assets folder, we're
| | 00:30 | going to bring in Soap Bubbles
1 Shot, Open and then Import.
| | 00:37 | In our Prefab, there they are,
Soap Bubbles 1 Shot.
| | 00:41 | Now let's go ahead and open up our
PowerUp script and add the ability to
| | 00:46 | instantiate a particle
system or any other Prefab.
| | 00:52 | Double-click, we're going to need
to make this functionality in its own
| | 00:57 | function, and we'll name it SpecialEvent.
| | 01:00 | I'm going to go out to my
Snippets file, and get the code,
| | 01:05 | Exercise Files10/10-06/Snippets, and we're
going to start with our empty SpecialEvent function.
| | 01:15 | Right-click, copy, and we'll add it
below our OnTriggerEnter function.
| | 01:21 | Inside it, also from the Snippets file,
we're going to instantiate our object.
| | 01:26 | So, I'll grab that one, right-
click, copy, and I'm going to paste--
| | 01:34 | Ctrl+V--my new line inside there.
| | 01:38 | So now we're going to have a local
variable called clone of type GameObject
| | 01:42 | that instantiates our eventFX in the
current position and rotation of the
| | 01:49 | object that the script is on.
| | 01:51 | That means, of course, that we're also
going to need a variable for the eventFX.
| | 01:57 | Up at the top, var eventFX,
that one is of type GameObject.
| | 02:10 | So let's save the script,
and get back to the editor.
| | 02:14 | Let's go ahead and select the Heart,
and then our script for the parameter,
| | 02:19 | and in the Inspector, we'll go ahead and drag
Soap Bubbles 1 Shot into our Event FX parameter.
| | 02:28 | Soap Bubbles 1 shot already has a time
destroy script, and it will go away on its own.
| | 02:34 | Now let's open the Animation View,
| | 02:36 | Window > Animation, and
select the Heart Score clip.
| | 02:42 | I'm going to click to see my clips list,
and I want to choose Heart Score, and
| | 02:49 | press my F key to focus in.
| | 02:52 | And then we need to scrub through
the timeline and decide when the Prefab
| | 02:56 | should be instantiated.
| | 02:59 | To do that, we need to
turn on our Record button.
| | 03:03 | So, I'm going to scrub through the timeline and
decide where the Prefab should be instantiated.
| | 03:08 | I'm thinking somewhere around frame 45 or 50.
We're going to add an event.
| | 03:13 | To do that, we could use the Add
Event button which is right here, but in
| | 03:20 | Windows at least, the dialog doesn't stay open.
So let's go ahead and use another method.
| | 03:25 | We'll right-click over the indicator and choose
Add Animation Event that way, a single click.
| | 03:34 | And now we have our new marker, and we also have
a dialog that wants us to select the function.
| | 03:42 | Events are sort of like using send message.
| | 03:46 | They go out to a function of that name,
regardless of which component it's on.
| | 03:51 | So, we're going to click the dropdown
and our script has special event, that's
| | 03:58 | the one we want, and we
can go ahead and close this.
| | 04:02 | If we needed to edit the event, we
only want to click once on the marker.
| | 04:07 | A double-click will generate a new
marker in the same spot, which will leave you
| | 04:11 | wondering why it tells you
there is no animation assigned.
| | 04:14 | So be careful about that.
Let's test it.
| | 04:18 | Go ahead and close the Animation View,
and then we'll click Play, and we'll jump
| | 04:23 | the first-person controller at the Heart,
| | 04:26 | W key, spacebar to jump, and there we go,
and there's our bubbles. Here's the event.
| | 04:35 | So the bubbles might be kind
of hard to see in the game view.
| | 04:39 | Let's try a rock Prefab instead.
We'll use the small one, Rock3.
| | 04:44 | That one won't get stuck on the invisible walls.
| | 04:46 | I'm going to click Exit Play mode,
select the Heart, and in our script, instead
| | 04:54 | of Soap Bubbles, I'm going to
drag the Rock3 Prefab into it.
| | 05:00 | Let's click Play and try it,
W, spacebar, and there's our rock.
| | 05:07 | You've probably heard it ding twice.
| | 05:10 | That's because the heart's collider
isn't gone by the time the rock hits it.
| | 05:14 | So we really ought to add a check to make
sure that only the player gets the power-up.
| | 05:19 | Let's exit Play mode, and we're going to add
the Collider argument to the OnTrigger function.
| | 05:26 | So we're adding a local variable, and
we'll call this Collider, and it's of type
| | 05:33 | Collider, and then we'll add the
conditional that checks for the player tag.
| | 05:39 | Our conditional needs to be at the top,
and I'll tab over, and it's going to be
| | 05:44 | if (collider.tag == "Player"), then,
we get to do all the good stuff.
| | 05:51 | We need to add our closing curly bracket,
and I'm going to select the inside and
| | 05:57 | right-click and indent the
selection. So there we go!
| | 06:03 | Let's save the script.
We'll go ahead and click Play.
| | 06:09 | W, spacebar, and this time, we only got
one ding, and the rock didn't trigger it.
| | 06:18 | So let's exit Play mode, and there we go!
| | 06:21 | The addition of the event to call
another function during the timeline opens up
| | 06:26 | a lot of possibilities.
| | Collapse this transcript |
| Avoiding keyframing pitfalls| 00:00 | Let's look at one more keyframe animation-
related thing before we head on to imported animation.
| | 00:06 | It's a kind of serious gotcha that you may
run across with keyframe animation in general.
| | 00:11 | Let's start by cloning the
Heart object and naming it Heart2.
| | 00:16 | I'll select my Heart, press Ctrl+D,
and I'll name this Heart2.
| | 00:23 | Now, we are going to move
it beyond the first one.
| | 00:26 | I'll go ahead and move it up beyond the key.
Let's go ahead and click Play.
| | 00:30 | Make sure you trigger the first
heart before you go after the second one.
| | 00:34 | Play, W, spacebar, there is its rock,
and then we are going to go up and
| | 00:42 | trigger the second one. So wait!
What just happened? Let's exit Play mode.
| | 00:49 | As soon as the first-person controller
hit the second heart, that heart jumped
| | 00:55 | back to the spot where
the animation was created.
| | 00:57 | Any object that's a single object
created in Unity or imported as a single
| | 01:02 | object is going to have this problem whenever
its animation includes a position transform.
| | 01:09 | The solution is to put the object with its
animation in a group and then move the group.
| | 01:15 | Remember, children inherit the
transforms of their parents, and their own
| | 01:20 | animations stay relative to the parent.
| | 01:24 | So let's delete the moved Heart, Heart2,
right-click, and Delete, and we'll make
| | 01:31 | an empty GameObject in the
original Heart's position.
| | 01:34 | I'm going to double-click on
it to make sure it's focused.
| | 01:38 | GameObject, Create Empty, and I'm
going to name this one Heart Group.
| | 01:44 | Now, I'll clone the original Heart
again, Ctrl+D, and I'm going to put that
| | 01:51 | into the Heart Group.
| | 01:53 | Now, I'll zoom out a little bit, and I'm going to
move my Heart Group back where I had the other one.
| | 02:02 | Let's click Play and see how this works,
Play, W, spacebar, and spacebar.
| | 02:13 | Well, the heart did what we
expected it to this time, but the rock is
| | 02:19 | totally missing in action.
| | 02:21 | So, there's something else going on here.
Let's exit Play mode.
| | 02:25 | The rock was in the hierarchy, so we know it's
been instantiated, but it's nowhere to be found.
| | 02:31 | So it looks like we need to use the
parents transform as the instantiation spot.
| | 02:36 | That is of course if there is a parent.
So, we are also going to need to check for that.
| | 02:42 | Let's go ahead and open up the PowerUp
script, and we're going to change the
| | 02:48 | code in the SpecialEvent function.
| | 02:50 | So, I'm going to go out and grab
that code from the Snippets file,
| | 02:54 | Exercise Files10/10-07/Code_Snippets.
| | 02:59 | So this one, we're going to make sure
that if it doesn't have a parent, so if
| | 03:05 | no parent of that transform exists,
it's going to go ahead and instantiate it
| | 03:10 | in the normal place.
| | 03:11 | But otherwise, that means it does
have a parent, so now we're going to use
| | 03:16 | transform.parent.position and
transform.rotation is still okay.
| | 03:22 | So, I'm going to right-click and copy
all of this code, back into my script
| | 03:28 | editor, and in the SpecialEvent
function, we're going to replace the original
| | 03:32 | line with the new condition, Ctrl+V
| | 03:36 | Now we can save the script
and head back to the editor.
| | 03:40 | To be sure our new grouped power-up can
be cloned and still work, let's group
| | 03:45 | then duplicate the key and test it as well.
| | 03:49 | So I'll focus in on the key, double-
click it, create a new empty GameObject,
| | 03:55 | and name it Key Group, duplicate the key with
Ctrl+D, and move that one into the Key Group,
| | 04:08 | zoom out, select my Key Group,
and I'll move it over here.
| | 04:17 | And now we are ready to
click Play and test again,
| | 04:19 | W, spacebar, spacebar, spacebar, and
spacebar, and there we go. Everything is working.
| | 04:35 | So now would be a really good time to exit
Play mode and update our original to Prefabs.
| | 04:42 | This time, we're going to overwrite them
with the Key Group and the Heart Group.
| | 04:47 | So we'll drag Key Group into the Key
Prefab, and we'll say Replace anyway.
| | 04:56 | Then we'll drag Heart Group onto the
Heart Prefab and tell it to replace anyway.
| | 05:04 | Now, we can delete our two extra
objects in the Hierarchy and Delete.
| | 05:12 | So to recap--and this is another one of
those really important concepts--if you
| | 05:18 | want to move an object that has
keyframed animation on its root, be sure to put
| | 05:23 | it in a group or empty GameObject first.
| | Collapse this transcript |
|
|
11. Animating Skinned Meshes and Controlling CharactersImporting skinned meshes| 00:00 | So now that we've covered the basics of
native keyframed animation, it's time to
| | 00:04 | look at imported animation.
| | 00:06 | Let's start by selecting the
Imported Assets folder, and then import the
| | 00:10 | Lenny.FBX file with Import New Asset.
| | 00:15 | Imported Assets, right-click, Import
New Asset, and in our Assets folder, here
| | 00:22 | is Lenny, and we'll import.
| | 00:24 | Let's drag Lenny into the Scene
view from the Imported Assets folder.
| | 00:29 | Now we'll focus on the Heart and select
Lenny and use Move To View to bring him in line.
| | 00:35 | If we move him aside and zoom in,
we'll notice that he is pretty small.
| | 00:42 | Let's select him back in the Imported Assets folder
again, and change his import Scale Factor to 0.08.
| | 00:52 | Notice we're not generating colliders, but
we've made a change, so let's click Apply.
| | 00:58 | Now, we can rotate him 90 degrees on the Y,
and he is in line with the rest of our power-ups.
| | 01:05 | I'm going to zoom out, then I'll go
ahead and move them up above the upper ramp.
| | 01:10 | Let's click Play and watch his
animation, and exit Play mode.
| | 01:18 | If the teeth didn't clue you in before,
by now, we can see he is a threat to our
| | 01:23 | poor little first-person controller.
Let's hold Alt and click the root object.
| | 01:29 | The expanded hierarchy shows
several bones and a set of teeth.
| | 01:33 | Let's select him in the Project view again.
| | 01:36 | We've changed his Scale Factor,
we've decided not to generate colliders.
| | 01:41 | So the next thing is animations.
| | 01:44 | Since he has a hierarchy of bones that
deform his mesh, we need to use Store in
| | 01:49 | Root, and that's the
default, so we're good to go.
| | 01:52 | So, where is the animation stored?
Let's open him in the Imported Assets folder.
| | 01:59 | And at the bottom, we see
something called Take 001.
| | 02:03 | That's the default name for
animation clips generated on import.
| | 02:08 | By now, though, you've probably guessed
that we're going to break the original
| | 02:11 | clip into a couple of
clips, one for each behavior.
| | 02:15 | Unlike native animations where the
clips exist independent of each other--
| | 02:19 | at least from what we get to see--on import,
we'll see the object's entire timeline.
| | 02:26 | Our first task will be to separate it
into his behaviors, the animation clips.
| | 02:31 | So, right below the Split Animations
check box is the list of our clips, or
| | 02:36 | it will be shortly.
We'll start by clicking the plus button.
| | 02:40 | A new clip is generated.
The default name is idle.
| | 02:44 | We're going to make it a bit more
descriptive and rename it Lenny Idle.
| | 02:48 | In 3ds Max where I made him, I
was using 30 frames per second.
| | 02:53 | His idle behavior started
at 10 and went to frame 100.
| | 02:58 | Unity knows how many frames per
second were used when making the animation.
| | 03:02 | That information is included in the FBX file.
| | 03:05 | So now we need to set the
start and end to those values.
| | 03:08 | We'll set this one to 10 and the end to 100.
| | 03:14 | For Wrap mode, we want to choose loop,
and we'll check the Loop check box.
| | 03:21 | For our second clip, we'll once again
click the plus button, and this time
| | 03:27 | we're going to rename this one Lenny Attack.
| | 03:31 | This one goes to 160, and for a
Wrap mode we want to choose Once.
| | 03:38 | Now we can click Apply.
| | 03:40 | In the project file, the original
Take 001 clip disappears and the two new
| | 03:46 | clips take its place.
Don't try to move them from that folder.
| | 03:49 | Let's see what the clips in animations
look like in the animation component.
| | 03:54 | So we'll select Lenny in the
hierarchy again and see what we've got.
| | 03:59 | The array has been made, and it
contains both of our clips, and unlike the
| | 04:03 | native clips, our first clip is
already loaded as the default.
| | 04:07 | Let's go ahead and open the
Animation View now and see what we've got.
| | 04:11 | The first thing you'll notice is
that the clips we defined are Read Only.
| | 04:15 | We'll turn on the Record button so we can at
least scrub through the animation and see it.
| | 04:20 | I'm going to need to zoom
out to get the full idle.
| | 04:26 | Let's click Play and see
how it looks in real-time.
| | 04:29 | The animation is nice, but we really
ought to have him moving up and down to give
| | 04:34 | the player a chance to go
either under him or over him.
| | 04:37 | But the animation clips were Read Only.
| | 04:41 | Well, guess what. We can combine the scripted
animation with the keyframe animation.
| | 04:46 | Since we've already got the
V_PositionCycler script, let's drop it on Lenny
| | 04:50 | and see how it works.
| | 04:52 | I'm going to close the Animation View,
find my V_PositionCycler, and drop it onto
| | 04:59 | him, and I'll go ahead and
close Lenny while I'm at it.
| | 05:03 | It's set up to default to up and down
range of one, so if we click Play, we
| | 05:08 | should see the results immediately.
They work really well together.
| | 05:12 | Let's exit Play mode.
| | 05:14 | Next, we'll go ahead and
drop the PowerUp script on him.
| | 05:18 | Since we chose not to have a mesh
collider generated for him on import, we're
| | 05:21 | going to need to give him a collider as well.
| | 05:24 | Component > Physics, and this
time we'll use a Sphere Collider.
| | 05:29 | If we watch the animation, he pretty much stays
in a spherical configuration for the idle behavior.
| | 05:35 | So, we'll just set Is Trigger, and then we'll
adjust the Collider Radius and Position a little bit.
| | 05:41 | I'm going to set the Radius up to about 1.3,
and I'll move it up a little bit on the Y.
| | 05:48 | One more thing we'll need before we set up
the PowerUp script is an audio component,
| | 05:53 | so Component > Audio > Audio Source.
| | 05:58 | We've got a message telling us
there's two audio listeners in the scene.
| | 06:02 | We should go up to our camera and right-
click, and remove one of the extras.
| | 06:09 | So now we can go back to Lenny and
fill up his PowerUp script parameters.
| | 06:13 | For the Clip, we want Lenny Attack,
for the Point value, he is sort of a
| | 06:21 | power down, so I'm going to choose -10,
for the Score Keeper, I'll drag that
| | 06:28 | object into the parameter.
| | 06:30 | And for the Sound Effect, I'm just going to
use ChestOpen for lack of anything better.
| | 06:37 | We don't need an eventFX
for him, so we're good to go.
| | 06:41 | Let's click Play and see if we can
run our first-person controller into him
| | 06:46 | using my W button. And I
missed him, and there I go!
| | 06:54 | Now, problem is that Lenny has disappeared.
| | 06:58 | It would be really nice if he stayed
around to eat the first-person controller.
| | 07:02 | So let's exit Play mode and open
the PowerUp script in Script editor.
| | 07:09 | Let's make sure we're in the PowerUp
script, and then we're going to add a new
| | 07:13 | variable called dontKill.
| | 07:17 | This is going to be of type Boolean,
which will give us a check box in the
| | 07:23 | Inspector, and we're going to
initialize it to False, because most of our
| | 07:27 | power-ups we do want to
disappear after they've been hit.
| | 07:32 | Now, we're going to carry out our
dontKill option right above the yield.
| | 07:38 | So, if dontKill is true, we're
going to say, if (dontKill) return.
| | 07:45 | And as we saw in a previous script,
that's going to bump us out of the function
| | 07:50 | before we get to the destroy.
| | 07:53 | Let's go ahead and save the script
and Tab back to the Game editor.
| | 07:58 | It looks like the console is reporting an error.
| | 08:01 | If I select the Heart parent, I can see
that it has an extra PowerUp script from
| | 08:07 | when the Prefab was updated.
I'll just remove it and check the original.
| | 08:11 | Right-click, Remove Component, and
then I'll check the Original, and there is
| | 08:18 | our missing Score Keeper.
| | 08:21 | I'll take the Score Keeper object
from the hierarchy and drop it into the
| | 08:25 | correct parameter in the Inspector.
We'll also need to do that for the key.
| | 08:31 | Select the key, remove the extra power-up,
check its original key, and it's also
| | 08:39 | missing the score keeper.
| | 08:41 | So, in the hierarchy, we'll drag the
score keeper into the correct spot.
| | 08:46 | Now, there's one more thing we need to do.
| | 08:49 | Since we added the dontKill variable, we
need to select Lenny and turn his dontKill on.
| | 08:59 | So now we should be able to click Play
and run our first-person controller
| | 09:04 | through the power-ups. And there we go!
| | 09:11 | The heart and the key
disappear and Lenny persists.
| | 09:15 | Let's exit Play mode.
| | 09:17 | With imported character animation or
any objects with a hierarchy or linked
| | 09:22 | animated objects, we need to use Store in Root.
| | 09:27 | We can break the original Take 001 clip
into separate animation clips below the
| | 09:33 | Split Animation check box.
| | 09:34 | Well, we've also discovered that
keyframe animations and scripted animations
| | 09:40 | can play together nicely.
| | Collapse this transcript |
| Adding to imported animations| 00:00 | Lenny is kind of a colorful character. It would be
fun to make his animation even more outrageous.
| | 00:05 | Like maybe suspending the player input
while Lenny gnaws on him, that would be
| | 00:09 | triggered with an event.
| | 00:11 | Or maybe just a color
change while he is chomping away.
| | 00:14 | Either way we need access to that
attack clip, but it is part of the imported
| | 00:20 | asset, and we can't touch it--it is read-only.
| | 00:23 | We can, however, clone it.
Let's do just that.
| | 00:27 | Let's select the lenny attack clip
in the Imported Assets folder and use
| | 00:33 | Ctrl+D to duplicate it.
| | 00:34 | So the first thing that happens is the
clone is created outside of the Imported
| | 00:39 | Assets folder. That gives us
the opportunity to rename it.
| | 00:44 | I'm going to name this one lenny attack
e--for edited--and then I'm going to move
| | 00:51 | it to the folder with the
rest of the animation clips.
| | 00:54 | The first thing we'll need to do is
select Lenny, and we need to swap out our
| | 01:00 | new attack clip with the old one.
| | 01:06 | And we need to do it both in the
Animation component and in the PowerUp script.
| | 01:12 | Now when we open the Animation View,
Window > Animation and click the dropdown,
| | 01:20 | we see that we've got a lenny
attack e clip that can be edited.
| | 01:25 | So we'll select it.
| | 01:26 | In the LennyMesh child object we can
find the material Skin. Let's change the
| | 01:33 | color to red while it chomps then
back again, and so we don't lose it, we're
| | 01:37 | going to set keys for the color at the
start and the end of the animation first.
| | 01:42 | We'll select our RGBA color tracks. I'm
using my Control key to add to my selection.
| | 01:48 | And we'll click record.
| | 01:50 | And we're going to click Add Keyframe,
and now we have a key at frame 0.
| | 01:57 | His animation for the attack sequence
goes to about frame 59. By 50 I think he
| | 02:03 | should be back to his normal color.
| | 02:05 | We'll drag the time indicator over to
frame 50, and we'll click Add Keyframe again.
| | 02:12 | These two keys will
ensure his regular green color.
| | 02:16 | Now somewhere around frame 10,
let's select the LennyMesh object in the
| | 02:21 | Hierarchy view and change the skin color--also
known as main color--directly to a reddish-orange.
| | 02:29 | Here is our LennyMesh, here is our
Skin, we're in animation record mode,
| | 02:36 | and we're going to select his Main Color
and change it from green to a reddish-orange.
| | 02:43 | If we scrub through our time slider
now, he is green, he is orange, and he
| | 02:50 | goes back to green.
So there we go, we're all set to play.
| | 02:55 | Close the Animation View,
let's deselect him, and click Play.
| | 03:01 | And now we can run our character W
key, jump up, and we see it worked.
| | 03:10 | So there we go.
Let's exit Play mode.
| | 03:13 | So our main takeaway here is that we
can't change imported animation clips
| | 03:17 | directly, we need to duplicate them,
and then we can use the new versions.
| | Collapse this transcript |
| Dynamic parenting| 00:00 | While storing animations in the root
is perfect for characters where the top
| | 00:04 | parent in the hierarchy controls all,
sometimes we need to be able to access the
| | 00:09 | animation on different parts of
the imported asset independently.
| | 00:13 | Store in roots allows us to do just
that, even when the animations are at the
| | 00:19 | same place on the timeline.
| | 00:21 | In this video we'll import an old-
fashioned cage lift to move the player from
| | 00:26 | the compound up to the platform area.
| | 00:29 | Let's bring the Lift
Finish Package into the Project.
| | 00:34 | Right-click Import Package > Custom
Package > 11-03/Assets/LiftFinished,
| | 00:45 | and we will click Open, then Import.
| | 00:50 | Now let's take the LiftFinished Prefab
into the Hierarchy view and focus in on
| | 00:55 | it in a perspective view in and zoom out a bit.
| | 00:57 | LiftFinished, and we'll drag it in
here, double-click on it to focus in and
| | 01:04 | then just click on perspective on the scene
gizmo and zoom in a bit, and we'll click Play.
| | 01:13 | The lift animates between the lower
compound platform and upper will be
| | 01:17 | relocating our platform assets.
| | 01:21 | The appropriate doors open and shut to
allow them in at bottom and out at the top.
| | 01:28 | Let's go ahead and exit Play mode.
| | 01:31 | Let's select the Lift in
the Imported Assets folder.
| | 01:35 | In the Inspector under Animations we can
see that it's using Store in Original Roots.
| | 01:43 | Take 001 has been split into two clips,
elevator open and elevator closed.
| | 01:50 | Both door groups use the
same positions on the timeline.
| | 01:54 | So now, let's select the
LiftFinished in the hierarchy again.
| | 01:58 | Let's open the Animation View, Window >
Animation, and we'll use our F Key to
| | 02:06 | see the whole animation.
| | 02:08 | Besides the animations on the door that
came in with the imported asset, we also
| | 02:12 | have a lift operator clip that was
created in Unity, and we can see that it is
| | 02:18 | going to lift the whole group
on the Y up and then back down.
| | 02:24 | It also has four events that trigger the open
and close animations on the two door groups.
| | 02:30 | Let's close the Animation View now.
Let's get back to our right view in the
| | 02:36 | scene window, and I'm going to zoom
back a little bit because we want to see
| | 02:41 | where it comes out at the top.
| | 02:43 | So now we can click Play, and the doors
will be opening on the bottom, allowing
| | 02:49 | the player time to get into the lift,
and then it goes up to the top where it
| | 02:54 | pauses to allow him back out.
| | 02:58 | Let's pause the animation while it's
at the top, select the Platform asset's
| | 03:03 | Start group, and move it up to match.
| | 03:07 | Since we are in Play mode, this will not
be a permanent change, so we need to go
| | 03:11 | over to the Inspector and copy
the Y value, right-click and Copy.
| | 03:18 | We'll stop playback, then we go
back and right-click and Paste.
| | 03:23 | So our platform group is now up where
the elevator is going to be stopping.
| | 03:29 | Now we can take our Key, Lenny and Heart power-ups,
and drag them up to match. We're all set.
| | 03:37 | And we also need to relocate the first
platform, or it will be in the way of the lift.
| | 03:43 | So I am going to select it, and I'll just
move it over and maybe even a little downward.
| | 03:49 | When we drive the first-person
controller into the lift and let him take the
| | 03:54 | trip up to the top, we are going to see from
the Scene view that it looks pretty smooth.
| | 03:59 | But in the Game view when it starts to
rise--especially if we look up--we'll be able
| | 04:05 | to see a lot of camera jitter.
Let's go ahead and try that.
| | 04:09 | I'll click Play, drive my first-person
controller forward, and the doors will
| | 04:15 | close, and if we look up now
especially you can see a lot of jitter going on.
| | 04:23 | So let's exit Play mode and
figure out how to solve this.
| | 04:27 | Well, it turns out we can script the
first-person controller to be temporarily
| | 04:33 | parented to the lift.
| | 04:35 | So let's go ahead and create a
new script named Parent Manager.
| | 04:39 | From Game Scripts right-click, Create >
Javascript, and this one is going to be ParentManager.
| | 04:49 | I am going to go ahead and get the code
from it from the snippets file as soon
| | 04:54 | as I open it in the Script editor.
| | 04:57 | Exercise Files11/11-03/Code_Snippets,
and this is the code we'll be using.
| | 05:06 | So I'm going to right-click and Copy,
and then tab back to my Script editor, and
| | 05:14 | I'll replace the whole thing.
Right-click and Paste.
| | 05:18 | Our passenger is going to be the first-
person collider but we're going to do an
| | 05:23 | extra check just to make sure.
| | 05:26 | If the collider is marked as Player, then
we go ahead and parent the passenger to
| | 05:32 | the object this script is
on, which will be the lift.
| | 05:35 | When he leaves on trigger exit he
gets unparented, and that's pretty easy,
| | 05:40 | passenger.parent = null.
| | 05:43 | So let's save the script
and go back to the editor.
| | 05:46 | And we need to drop our script on
the LiftFinished, and there we go.
| | 05:53 | So now, let's keep the
LiftFinished Hierarchy open, I'll close up our
| | 05:57 | Platform Assets Start, and we want to
keep this open so that we can watch our
| | 06:02 | first-person controller and see when he gets
parented and unparented from the LiftFinished.
| | 06:08 | So I am going to click Play, drive him
forward, and you can see now he's now in
| | 06:16 | the LiftFinished group, and as soon as
he goes up to the top, we'll go through
| | 06:21 | and get a power-up and get out
of the lift at the same time.
| | 06:27 | Before I exit Play mode, note that once
again he is back where he belongs, and
| | 06:33 | now we can exit Play mode.
| | 06:34 | So we now have the means to
dynamically move our player around a scene on a
| | 06:41 | large assortment of vehicles.
| | Collapse this transcript |
| Exploring character controllers| 00:00 | Through scripting, Unity provides us with the
means of making all kinds of cool things happen.
| | 00:06 | Unfortunately, it means we're
stuck with the task of doing it.
| | 00:10 | Unity only ships with a few character
controllers preset and ready to go and
| | 00:15 | most are derived from the Lerpz
Tutorial available on the Unity web site.
| | 00:20 | If they happen to do what you
envision for your game, you're in luck.
| | 00:23 | Otherwise, you'll either need to learn
to write your own, find a programmer to
| | 00:28 | write them for you, or riffle through the example
projects available online and borrow their scripts.
| | 00:34 | Writing a character controller is beyond
the scope of the series, but we will at
| | 00:39 | least test out what
Unity gives us to start with.
| | 00:42 | Character controllers are usually
tightly integrated with camera control, so
| | 00:46 | let's get a fresh scene to play around in.
| | 00:49 | Let's start by importing the
Character Tests package, right-click, Import
| | 00:54 | Package > Custom Package and from 11-04/Assets
we're going to bring in Character Tests.
| | 01:04 | Open and Import. This one comes in as
a scene, so let's go ahead and load it.
| | 01:11 | Here it is on the Scenes folder,
Character Tests, and we'll double-click to
| | 01:16 | bring it in, and we can save our previous scene.
| | 01:20 | In the Hierarchy view, let's focus on the
Platform and then go ahead and disable it.
| | 01:26 | From the Standard assets folder, let's
open the Character Controllers folder and
| | 01:31 | select the Third-person controller Prefab.
| | 01:35 | Standard Assets > Character Controllers,
and here's our 3rd Person Controller,
| | 01:40 | and we're going to go ahead and
drag him into the scene, like so.
| | 01:45 | We want to drag him up out of the ground, so
let's go ahead and click Play and try him out.
| | 01:51 | As soon as we click Play, his own camera
comes into view, and we see him in the
| | 01:56 | game window, W-A-S-D, and if we click W
again, spacebar, he jumps and Shift to run,
| | 02:11 | and run and jump.
He is pretty entertaining. Okay, let's stop.
| | 02:18 | Then exit Play mode, and then let's
go ahead and see what makes him tick.
| | 02:23 | We'll do that by opening the
Third person controller script on him over in the
| | 02:28 | Inspector here is the script, double-
click it open, and it comes in first.
| | 02:35 | You can see by the size of the scroll
tab that it's a pretty lengthy script.
| | 02:41 | Let's go ahead and get down to somewhere
between 320 and 350 and look at something here.
| | 02:46 | What we see is animation.Crossfade.
That's how we can smoothly transition between
| | 02:53 | different clips, an idle to
walk, a walk to a run, et cetera.
| | 02:59 | So that's a good one to remember.
Let's tab back to the editor.
| | 03:02 | So here is the important question.
How useful would he be for our platform area?
| | 03:09 | We've seen when we make him go
forward and backwards the turn is usually
| | 03:13 | instant, but once we use the
strafe keys he moves in the direction he's
| | 03:18 | facing, for that we could use input.getaccess
to bypass the horizontal input,
| | 03:24 | but he's also got a camera
that's wired to his code.
| | 03:27 | For that we could probably disable the
camera script, but the crucial test is
| | 03:33 | can he ride a platform?
| | 03:35 | The platform in our scene already has a
rigid body, and it's set to kinematic.
| | 03:40 | Let's go ahead and activate it, and then
we'll need to move spin a little bit higher.
| | 03:45 | So we'll select the Platform and
activate it, we'll move our character a little
| | 03:51 | higher, and then we need to get some movement.
| | 03:55 | I've added the V_Position Cycler
script and the H_Position Cycler script.
| | 04:01 | Let's try out the vertical one first.
| | 04:04 | Let's click Play, and if we move him,
you can see he does go up and down, but
| | 04:13 | the movement activates his walk cycle.
Let's stop playback and switch from the
| | 04:18 | vertical to the horizontal and click Play.
| | 04:22 | And this time you can see it pretty
well has no effect on him whatsoever.
| | 04:28 | So let's exit Play mode. Clearly
platforms are not supported for the
| | 04:33 | Third-person controller in this version of Unity.
| | 04:36 | I'm hoping this one will be converted
to the newer motor system, but assuming
| | 04:40 | it hasn't yet been updated we'll do a bit
more tinkering to get something we can use.
| | 04:45 | So let's Save this scene, File > Save
Scene, Delete the 3rd Person Controller,
| | 04:52 | right-click, Delete, and we'll save
this for Character Test 2 for the next video.
| | 04:59 | File > Save Scene as in our Scenes folder
Character Tests2, and click Enter to save.
| | Collapse this transcript |
| Importing an animated character| 00:00 | Let's start by importing the
Platform Character package into the project.
| | 00:05 | Right-click, Import Package > Custom
Package, and from 11-05/Assets, we're
| | 00:14 | going to bring in PlatformCharacter.
And we click Open, and Import.
| | 00:21 | From the Prefabs folder, let's go ahead and
drag our PlatformCharacter into the scene.
| | 00:26 | And here he is right here, and I'm going
to drag him right on top of our platform.
| | 00:30 | He is just a simple character I
made with the CAT tools in 3ds Max.
| | 00:36 | Let's check out his import settings.
| | 00:38 | In the Imported Assets folder, Select
CAT2, and let's see what we've got.
| | 00:43 | Under Animations, Store in Root, and I've already
given him an idle, walk, jump, and run clip.
| | 00:52 | The Third-person controller didn't suit
our needs, so let's see what we can get
| | 00:57 | if we use the platform input
controller script to move this guy around.
| | 01:02 | This time, let's get our script from a different location,
Component > Character > Platform Input Controller.
| | 01:11 | This one can also be found
in the Standard Assets folder.
| | 01:15 | In the Inspector we brought in the
Platform Input Controller, but it also loaded
| | 01:21 | the Character Motor (script)
and the Character Controller.
| | 01:25 | Let's open the PlatformInputController
script to see how that happens.
| | 01:30 | We'll double-click on it, and at the
bottom of the script we see these funny
| | 01:36 | things here that have an
@ sign in front of them.
| | 01:39 | The RequireComponent is what adds
the component to the game object.
| | 01:43 | AddComponentmenu is what puts it up in the menu.
| | 01:48 | Let's go ahead and close
out a bunch of these now.
| | 01:52 | And I'll tab back to the editor.
| | 01:53 | So back to our PlatformCharacter, as you
can see his capsule is a little bit low,
| | 02:01 | so we need to move his collider up a bit.
| | 02:04 | So I'm going to move his
center up about a meter.
| | 02:08 | Now let's press Play and
test him with the platform.
| | 02:11 | I'm going to click on my
Platform and see which script is active.
| | 02:15 | Looks like the Horizontal Position one is.
| | 02:18 | Let's click Play, and sure
enough he rides the platform.
| | 02:24 | Let's go for the second test.
| | 02:27 | Let's turn on the Vertical
Platform Cycler, and there he goes.
| | 02:32 | Sort of looks like we have a winner.
| | 02:36 | If we stop playback, and turn off
both position cycler scripts, we can try
| | 02:42 | running him around the scene.
| | 02:44 | Like the other characters, he uses W-A-S-D,
spacebar to jump, and Shift to run.
| | 02:51 | Let's click Play and test.
W-A-S-D, jump, and we will skip run for now.
| | 03:04 | And let's exit Play mode.
| | 03:06 | This character controller was meant
for an environment using a 3D space, and
| | 03:11 | it has no built-in controls for managing the
character animation, but it does support platforms.
| | 03:17 | Let's tinker with the navigation first.
It's pretty close, but there's a couple
| | 03:21 | of things we still need to do.
| | 03:23 | So we'll select our character again, in
the Platform Input Controller (script),
| | 03:29 | double-click it, and in line 15,
we are going to rearrange the input.
| | 03:37 | I'm going to go out to my
snippet's file and get the replacement.
| | 03:41 | Exercise Files11/11-05/Code_Snippets 05.
| | 03:47 | So the only changes we're making
really is we're putting a 0 in the X axis,
| | 03:53 | we're moving our horizontal to the
Y, and we are leaving 0 in the Z.
| | 04:00 | And I've gone ahead and
commented out the one that we removed.
| | 04:02 | So I'm going to right-click and Copy,
back to my script editor, and we're
| | 04:10 | going to replace line 15.
| | 04:13 | Right-click and Paste, and
we'll move it over again.
| | 04:18 | Now Save the script, and
let's get back to the editor.
| | 04:22 | So basically what we've done is we've
blocked any input from the vertical.
| | 04:27 | Click play, and now the only keys that
should work are A and D or your left and
| | 04:34 | right arrow keys and
spacebar, you can still jump.
| | 04:39 | And let's exit Play mode.
| | 04:41 | Just out of curiosity, you might want to
know why this controller supports platforms.
| | 04:46 | If we open the CharacterMotor component
in the Inspector we notice it has moving
| | 04:52 | platform as one of the parameters.
Let's look in the script.
| | 04:57 | This is another really big one, but if
we go quite a ways down here at some
| | 05:02 | point we're going to start seeing
things about platform, activePlatform,
| | 05:06 | movementTransform, movingPlatform again, and if
we continue to look through it, MoveWithPlatform.
| | 05:16 | We've discovered that a pretty good chunk of
this script is about dealing with platforms.
| | 05:22 | Let's go ahead and get back to the
editor, maybe half or more of the script is
| | 05:27 | dedicated to the Platform option.
| | 05:29 | The bottom line is the velocity of the
platform is added to the velocity of the character.
| | 05:35 | And then there's all kinds of extra
equations to deal with jumping when on
| | 05:39 | platforms, landing while jumping
and all kinds of other fiddly bits.
| | 05:44 | So rather than trying to add platform
support to the Third-person controller, I've
| | 05:49 | opted to add some simple
animation controls that will work with the
| | 05:52 | CharacterMotor. That means it should work
with either the first-person controller
| | 05:57 | or the platform input controller.
We'll do that next.
| | Collapse this transcript |
| Activating the character animation| 00:00 | Next we'll add at least a little
bit of animation to our character.
| | 00:04 | From the exercise files folder
for this video, let's import the
| | 00:09 | CharacterMotorAnimation script into the scene.
| | 00:11 | We can do that with Import New Asset, and let's
make sure we add it to the Game Scripts folder.
| | 00:17 | Right-click, Import New Asset, and we
need to get to 11-06/Assets, and here it
| | 00:26 | is, CharacterMotorAnimation, and we'll Import.
| | 00:30 | And now we can go ahead and
drag it onto the PlatformCharacter.
| | 00:35 | Select him and at the bottom of the
Inspector we'll notice that it looks very
| | 00:41 | much like the Third-person controller.
| | 00:42 | We'll need to add each of these
animations into the proper slots.
| | 00:47 | Let's click on the browser and see
if we can find the Idle Animation.
| | 00:50 | Well, it turns out we've
got a couple to choose from.
| | 00:53 | So this is one of those times when
you better off to select it this way.
| | 00:59 | Click on it here, and now we know which
one it is, and we can drag it into the idle.
| | 01:06 | Go for the walk.
It selects it.
| | 01:10 | It looks like we'll be pretty safe
to go this way, walk, jump, and run.
| | 01:17 | So, how will this script know what to do?
| | 01:20 | Well, it will need four values
sent to it from the Character Motor.
| | 01:24 | It needs to know the character's
velocity for the idle and run animations, and
| | 01:30 | it needs to know if the
character is on the ground or in the air.
| | 01:33 | So, we can know whether to override
the idle or run animations with the jump
| | 01:37 | animation, and it needs to know
when the jump starts and stops.
| | 01:42 | For the last two, the Character Motor
already has a couple of send messages.
| | 01:48 | For the first two, we are going to
need to add a couple of more, and since
| | 01:52 | grounded and velocity are needed by the
CharacterMotorAnimation in every frame,
| | 01:57 | that's where we'll add the code,
inside the Update function.
| | 02:00 | I am going to go out to the
Snippets file and get the code we need.
| | 02:06 | Exercise Files11/11-06/Code_Snippets.
| | 02:12 | So basically, we have our gameObject.SendMessage,
and we are going to send it to
| | 02:18 | a GetGrounded function, and what
we're sending is the grounded variable.
| | 02:23 | In this one, GetVelocity, we're sending
movement.velocity, and the Character Motor
| | 02:30 | keeps track of these two variables throughout.
| | 02:34 | So let's right-click and Copy, back
into our editor and go ahead and open the
| | 02:41 | CharacterMotor script.
| | 02:44 | I've already done a search for the Update
function, and I've already found it at line 337.
| | 02:51 | So let's get down to that, and there
it is, the Update function, and we can go
| | 02:56 | ahead, give ourselves a little space
and paste our new send messages into it.
| | 03:03 | In case you're curious, the On Jump
message is at line 454 and the On
| | 03:09 | Land message is at 295.
| | 03:12 | Let's go ahead and save the
script and get back to the editor.
| | 03:18 | If you want it to open the
CharacterMotorAnimation script you would find the
| | 03:22 | GetGrounded and GetVelocity functions
are just setting flags that are used in
| | 03:27 | the Update function.
Let's go ahead and test him.
| | 03:30 | I'm going to deselect him, click Play,
and remember we aren't using W and S
| | 03:37 | anymore, we are using A and D.
| | 03:41 | So his run sequence works, let's
try jumping him, and there he goes.
| | 03:45 | He kind of gets out of frame, but that's okay.
| | 03:48 | I'll jump him way out here.
| | 03:51 | Run him back and jump, and we can exit Play now.
| | 03:57 | Unlike the Third-person controller, he has
just one speed, which is fine for a platformer.
| | 04:02 | I hooked it up to use the run
animation, and the speed matches the animation
| | 04:06 | pretty good, so we shouldn't need to adjust it.
| | 04:09 | The only thing we really noticed, though,
is it looks like when we jump he is got
| | 04:13 | a Jet Pack just like in the Lerpz Tutorial.
| | 04:15 | We need to make a few adjustments in the
Character Motor component, Jumping section.
| | 04:20 | So let's select him again, and in the
Character Motor section under Jumping we're
| | 04:27 | going to set his Extra Height to 0.1,
and that will get him down sooner, but now
| | 04:34 | he won't jump high enough so we need
to set our Base Height to about 3 or 4,
| | 04:38 | and you can test this on your own.
| | 04:41 | And then in Movement, let's go
ahead and set his Gravity to about 30.
| | 04:47 | And finally, in the Platform Input
Controller we're going to turn his
| | 04:52 | Max Rotation Speed way up.
I'm going to try about 2000.
| | 04:56 | This will ensure that he makes a
full turn anytime we which keys.
| | 05:01 | So let's click Play and test.
| | 05:03 | I am going to deselect him, try running
with the Arrow keys Left or Right or the
| | 05:10 | A or D keys, and then I'll press my
spacebar to see how he jumps, and you can
| | 05:16 | see his jump is much better now.
And we can exit Play mode.
| | 05:21 | So, there's only one more thing.
| | 05:23 | He is going to need to trigger the Power Ups,
and they are set to look for the Player tag.
| | 05:28 | So we need to set a new character,
PlatformCharacter and take him as Player as well.
| | 05:36 | So that should just about do it.
| | 05:38 | Let's go ahead and update the Prefab for
him by clicking Apply in the Inspector,
| | 05:43 | and let's be sure and save this scene.
| | 05:46 | So, we have found that we can tinker
with the existing controllers without
| | 05:51 | having to write pages of code.
| | Collapse this transcript |
|
|
12. Working with Cameras and LayersIntroducing cameras| 00:00 | In this chapter we'll be looking into cameras.
| | 00:03 | Unity's cameras have many of the
features you may already be familiar with, plus
| | 00:07 | several unique to game engines.
| | 00:09 | Let's start by opening the MainLevel
scene, and then we're going to activate the
| | 00:14 | camera and deactivate the Camera on
the first-person controller, and its
| | 00:19 | Children, and also let's go
ahead and turn the Terrain back on.
| | 00:23 | So let's adjust our Scene view to get
a nice view of the platforms, with a
| | 00:27 | little bit of the sky.
| | 00:29 | I'm going to select the platform,
focus in on it, and then use my Alt and my
| | 00:34 | middle mouse button to pan, and if you want
you can turn the sky on in the Scene view.
| | 00:39 | This is the Overlay button, and
so that's kind of a good view.
| | 00:42 | So now we're going to create a new
camera, and we'll name it Camera 2.
| | 00:46 | GameObject > Create Other >
Camera, and we'll name it Camera2.
| | 00:52 | It's drawn over the existing camera. Let's
try turning it off and on just so you can that.
| | 00:57 | Activate and Deactivate, and you can
see that it's drawn over the other one.
| | 01:02 | Now let's go ahead and use align
with view on our new camera, Camera2,
| | 01:05 | GameObject > Align With View, and it pretty
much matches the one we have in our Scene view.
| | 01:12 | As long as we've got it selected, let's
also deactivate its Audio Listener, so
| | 01:17 | we're all set to look into cameras.
| | 01:18 | The first thing we want to investigate
is Clear Flags. It's set to Skybox.
| | 01:23 | Let's choose Solid Color.
| | 01:25 | If you had assigned one, the Skybox is
turned off--it's a shader, by the way.
| | 01:30 | And now we can adjust the Background color.
| | 01:32 | We'll click on the Color Swatch, and
we can change it in the color picker.
| | 01:39 | And we'll close that.
Let's try the next one, Depth only.
| | 01:43 | This one turns the sky off altogether, and
guess what shows through. The other camera.
| | 01:48 | Turn this camera off and on to make sure
you can see that that's what's happening.
| | 01:52 | The next one is kind of
funky, it's called Don't Clear.
| | 01:56 | It's sort of combines everything
in an unpredictable manner.
| | 02:00 | The doc suggests it might be useful for specialty
shaders. Let's go ahead and switch back to Skybox.
| | 02:06 | The next parameter is Culling Mask.
| | 02:09 | Unity lets us assign objects to layers.
The cameras can be set to selectively
| | 02:13 | render different layers in different orders.
| | 02:16 | We'll experiment with that when
we get to the Depth parameter.
| | 02:19 | Projection allows you to choose between
a Perspective view where we can adjust
| | 02:23 | the field of view or an Orthographic
view, where there is no perspective.
| | 02:27 | With Orthographic you adjust its size
rather than the Field of view. Let's try it.
| | 02:32 | Instead of Perspective, we'll select
Orthographic, and we can adjust its Size.
| | 02:39 | I'm going to start with a value
of 10 and zoom it back and forth.
| | 02:44 | With orthographic cameras, objects in
the distance do not appear smaller.
| | 02:49 | We could opt to use Orthographic for a
platformer section since it takes place
| | 02:53 | pretty much on one plane.
| | 02:55 | But as long as we have 3D assets
adjusting the perspective will be visually more
| | 03:00 | interesting, so let's
switch back to Perspective.
| | 03:03 | The thing we see is Clipping Planes.
| | 03:05 | This tells the camera how far to
start and stop drawing the scene.
| | 03:09 | Let's turn off the other camera
before we try adjusting these parameters.
| | 03:13 | So I'm going to select Camera,
uncheck it, and then select Camera2 again.
| | 03:20 | With Near you can see the clipping planes
move through the scene in the Game view.
| | 03:25 | Let's set Far to 100 before we experiment
with it, and we'll drag this one, and
| | 03:30 | you can see the clip coming
closer and going back farther away.
| | 03:35 | Let's go ahead and reset these.
| | 03:37 | This one is at 1,000 and Near was about 0.3.
| | 03:41 | Far when used in conjunction with fog
provides a very cheap way to cull objects
| | 03:46 | and improve frame rate.
| | 03:47 | For the next section, Normalized view
Port Rect, allows you to dictate how big and
| | 03:53 | where you want this camera to render.
| | 03:55 | Let's start by setting the H and W parameters
to 0.5, and we'll set the X and Y to 0.45 each.
| | 04:05 | The camera now renders in the upper-
left of the screen. Position, by the way,
| | 04:08 | is calculated from its lower-left.
| | 04:11 | Let's see what happens if we
turn our other camera back on.
| | 04:15 | When we turn the other
camera on, our Camera2 is hidden.
| | 04:19 | But wait! The new camera used to
be rendered on top of the old one.
| | 04:22 | This is where the Depth parameter comes in.
It allows us to order the camera for rendering.
| | 04:27 | A lower number is drawn
before a higher number.
| | 04:30 | So let's set our Camera 2 to a Depth of 1.
| | 04:34 | Zero is the default, so when we set
this to a higher number it's drawn last.
| | 04:39 | Now it draws over the other camera
predictably, and you can see how this might
| | 04:44 | give you a nice mini map
superimposed over the main view.
| | 04:47 | Next, we'll being seeing how layers and culling
masks give us even more control with our camera.
| | Collapse this transcript |
| Working with cameras and layers| 00:00 | Now that we've seen how we can control
camera draw order, let's take it one step
| | 00:04 | further and find out how layers work.
| | 00:06 | Layers are similar to Tags in that
they are an ID system, but we use layers
| | 00:11 | mainly with lights and cameras.
| | 00:13 | Let's go ahead and select Camera2 again,
and we'll set its Normalized view Port
| | 00:17 | Rect X and Y back to zero,
and the W and H back to one.
| | 00:24 | In the Scene view, let's use Align view to
select it, GameObject > Align View to select it.
| | 00:32 | Now let's create a cube and scale it
up so it takes up about a quarter of the
| | 00:36 | view, GameObject > CreateOther > Cube,
and I'm going to scale it until it takes
| | 00:45 | up about that much room.
| | 00:47 | Now we're going to make a
Cube layer to put it in.
| | 00:50 | At the top of the Inspector click the
layers button and choose Edit layers.
| | 00:57 | Below the Tags array we can see the layers.
| | 01:00 | The first eight--and it started at 0,
remember--are used for Unity predefined layers.
| | 01:06 | Select layer number eight,
and we'll name her layer Cube.
| | 01:10 | As soon as we click in this area we'll
find the text entry area, Cube and Enter.
| | 01:15 | Now let's select the Cube again
and assign it to the layer Cube.
| | 01:21 | Let's select Camera2 and open its
Culling Mask dropdown, and we're going to
| | 01:25 | uncheck the Cube layer, the Cube disappears.
So now, let's make a layer just for the Cube.
| | 01:32 | We're going to duplicate Camera2 using
Ctrl+D, and we'll name this one Camera Cube.
| | 01:39 | We'll set its Depth to 2, so it draws
last on top of everybody else, change
| | 01:45 | its Culling Mask first to Nothing, the sky
will appear, then to Cube, now a cube appears.
| | 01:52 | Let's take a look at one of
the components, the Flare layer.
| | 01:55 | As you probably guessed, it allows
flares to be drawn by the camera.
| | 01:59 | We'd better turn this one off.
| | 02:01 | Okay, so now we can set the Clear
Flags to Depth only, and our Cube layer is
| | 02:07 | drawn on top of the other camera.
| | 02:08 | This is a technique often used to
prevent first-person weapons from going into
| | 02:12 | walls as the player gets too close.
| | 02:15 | The weapon is drawn on its
own layer with its own camera.
| | 02:18 | You're probably wondering what
happens when the view of the player from
| | 02:22 | the other layer moves.
| | 02:23 | Let's see what happens by selecting
Camera2 from the hierarchy and then
| | 02:27 | rotating it around in the scene window.
We'll switch to Rotate, and I'm going
| | 02:33 | to get a Top view here.
| | 02:34 | No matter where the Camera2 is looking, the
Camera Cube layer is always drawn on top of it.
| | 02:40 | Let's use Ctrl+Z to undo the rotations.
| | 02:43 | So the question is is the cube interactive?
| | 02:46 | Well, that depends. Our first-person
controller is nowhere close to it, so he
| | 02:51 | can't intersect with it physically.
| | 02:52 | But if we add our old RotationController
script to it, we should be able to pick
| | 02:57 | it and toggle the rotation
off and on. Let's try it.
| | 03:00 | Let me scroll and find the Practice
scripts folder. We'll open it, and here's our
| | 03:06 | old RotationController script,
and we'll drop that on the cube.
| | 03:11 | To refresh your memory, this one
should toggle the rotation off and on as we
| | 03:15 | pick it, so let's click Play,
immediately click Escape so we get our cursor
| | 03:19 | back, and try picking the cube.
| | 03:23 | I click, and it stops, I click again,
and it starts, and we can exit Play mode.
| | 03:30 | This means we can create things like
remote inventories, 3D menu interfaces, and
| | 03:37 | a lot of other cool stuff.
| | 03:38 | 2D GUI objects are often kept on their
own layers as well, only they don't need
| | 03:43 | a special layer because the
cameras also have a GUI component.
| | 03:47 | We won't do any test with these because
Unity's newer GUI is totally script driven.
| | 03:52 | We've got just a few more parameters,
so let's select our Camera2 again.
| | 03:56 | Rendering Path lets you override
whatever is set in the player's settings on
| | 04:00 | a per camera basis.
| | 04:02 | Target Texture allows Pro users to
render the camera to a texture, so it could
| | 04:07 | be applied elsewhere as a map; a surveillance
camera monitor is an example of that.
| | 04:13 | We'll try a simple one in a later video.
| | 04:15 | And finally, the HDR check box enables
High Dynamic Range rendering for the camera.
| | 04:21 | This is a pro-only feature, and you can find
more about it in the Manual/Advanced HDR.
| | 04:27 | Okay before we move on, let's
delete the Camera Cube and the Cube.
| | 04:32 | So I'm going to select Camera Cube, right-click
and Delete, select the Cube, right-click and Delete.
| | 04:38 | As you can see, cameras and the layering
system open a lot of new possibilities.
| | Collapse this transcript |
| Activating the platformer scene| 00:00 | At this point you're probably
wondering how to transition the player from the
| | 00:04 | first person to our platform character.
| | 00:06 | We could script it to turn one off and
the other on, but to make it easier for
| | 00:11 | ourselves we'll just turn the
platformer section into its own level.
| | 00:14 | Since we want some continuity in the
game, we'll change levels as soon as the
| | 00:18 | player gets out of the elevator,
so we'll get to see what he's in for.
| | 00:22 | Let's use Save Scene as and
name the duplicate Platformer.
| | 00:25 | File > Save Scene as, and in our
Scenes folder we're going to name it
| | 00:31 | Platformer, and we'll click Save.
| | 00:33 | Now we're going to delete everything
but all of the platform stuff, the Death
| | 00:37 | Zone, directional light, and the power-ups,
| | 00:39 | the heart, Lenny, and the key.
| | 00:41 | It's probably going to be quicker to
select all and then deselect the ones we need.
| | 00:45 | So I'm going to click BigTree and at
the bottom holding my Shift key I've got
| | 00:50 | everything selected. With my Ctrl key
I'm going to deselect the Death Zone, the
| | 00:56 | power-ups, Heart, Key, Lenny,
and our Platform Assets Start.
| | 01:02 | Do a quick double-check and
then right-click and Delete.
| | 01:07 | We don't want our platform character
to have access to the working lift.
| | 01:11 | It had too many animations to turn off anyway.
| | 01:13 | So we're going to import the static lift
package from this video's exercise files.
| | 01:19 | Right-click > Import Package > Custom Package >
12-03 > Assets and here is our LiftStatic, Open and Import.
| | 01:32 | Let's drag the LiftStatic Prefab into the Hierarchy
view from the Prefabs folder, and here it is.
| | 01:40 | Let's go ahead and focus in on it.
It should line up with the platforms.
| | 01:44 | Double-click, and I'm going to switch
to a perspective view and use my Alt and
| | 01:49 | left mouse button, and there we go.
So it looks about right.
| | 01:53 | Now let's go ahead and save our
platformer scene. File > Save Scene.
| | 01:58 | Next, from the Prefabs folder, let's
bring in our PlatformCharacter, and we're
| | 02:03 | going to put him in front of the lift.
| | 02:05 | So PlatformCharacter, and I'm going to
try and get him standing on the platform.
| | 02:11 | You want to double-check by hitting the
top view here, and yup, he looks good.
| | 02:15 | So I'm going back to perspective, rotating my
view a little bit, and I'm going to zoom in.
| | 02:21 | I want to move him back a little bit.
| | 02:25 | This is where we're going
to have our next spawn point.
| | 02:28 | So since he is likely to fall off at
some point, at least with me driving, we're
| | 02:32 | going to focus in on him now.
| | 02:34 | Double-click and make our new empty
GameObject, and we'll name it Spawnpoint.
| | 02:38 | GameObject > Create Empty, and
we're going to name this Spawnpoint.
| | 02:44 | Then we'll select our Death Zone, and we can
drag our new Spawnpoint into its Element 1.
| | 02:51 | Feel free to move the Death Zone up a ways so
the wait won't be so long if he does fall off.
| | 02:56 | I'm going to zoom back and check the
location of mine, and there it is way down there.
| | 03:01 | So I'm going to bring it up higher, and
I also need to increase the size of it,
| | 03:05 | especially the Z direction.
| | 03:11 | You might want to check it in the top
view as well, and I'm going to toggle off
| | 03:15 | my overlays button so I can see the
collider better, and it looks like I could
| | 03:20 | stand to shift mine a little bit.
| | 03:23 | Back to perspective view,
and we should be pretty good.
| | 03:29 | Next, we're going to need a camera.
So let's go ahead and create one.
| | 03:33 | GameObject > Create Other > Camera, and
it's going to need the main camera tag.
| | 03:39 | So over in the Inspector tag I'm going to
click the down arrow and select main camera.
| | 03:46 | A sophisticated camera for a platform
jumper game is probably as complicated as
| | 03:50 | a good character controller script.
| | 03:53 | There's a nice one in the 2D platform
or example project on the Unity web site.
| | 03:57 | It's several hundred lines of code.
We'll use a simple alternative.
| | 04:02 | Let's select the camera and rename it Camera
Platformer, and now let's create a new script.
| | 04:08 | We'll name that one Platform Camera
Manager, and let's put it up in the
| | 04:12 | Game Scripts folder.
| | 04:13 | Right-click > Create Javascript, and
this one is Platform Camera Manager, and
| | 04:21 | we'll go ahead and open it up.
| | 04:22 | Double-click and the first thing we'll
need to do is to tell the camera whose
| | 04:26 | transform it's going to be watching.
| | 04:28 | So let's add our first variable,
var camTarget of type Transform.
| | 04:34 | Now in the update function we're
going to add transform.LookAt(camTarget).
| | 04:41 | Let's save the script and
head back to the editor,
| | 04:44 | Alt+Tab, and we need to drag our
new script onto the Camera Platformer.
| | 04:49 | Select it, and we need to give it the target,
which is going to be the Platform Character.
| | 04:55 | Now we'll do a bit of a cheat.
| | 04:57 | Let's reduce the field of view to
about 5, and we'll need to rotate it -90 on
| | 05:03 | the Y, and we're going to adjust its
distance so it's about 210 on the X.
| | 05:09 | This is just a start.
| | 05:10 | In the top view, let's move the
camera about midway along the platforms.
| | 05:15 | So I'm going to click on Y, on the
scene gizmo and zoom out with my middle
| | 05:20 | mouse roller, and then I want to position my
new camera about midway from the right view.
| | 05:27 | So I'm going to click my
perspective and then get to a right view.
| | 05:33 | Zoom in a little bit, I want to make
it a little closer to the bottom of the
| | 05:38 | platformers rather than the top, and I
think that's going to be about right.
| | 05:41 | The sky cube image is inherited from
the scene render settings, but that can be
| | 05:45 | overridden on the camera.
| | 05:47 | So let's just set the clear flags to
solid color and use the background color,
| | 05:52 | and you might want to adjust it a
little by clicking on the color swatch.
| | 05:56 | We've already got our character
working off of A and D--or the left and right
| | 06:01 | arrow keys--but now we need to make sure
that he's going in the right direction with those.
| | 06:06 | So let's open the platform input
controller script, and we can find that by
| | 06:10 | clicking on our platform character.
| | 06:12 | Here's our platform input controller,
and we'll double-click to open its script.
| | 06:17 | Let's cut the 0 from the X position
using Ctrl+X, and put it after our input
| | 06:25 | control horizontal, Ctrl+V. This should
get him going in the right direction when
| | 06:30 | we use our virtual horizontal keys.
| | 06:32 | Let's save the script
and Tab back to the editor.
| | 06:35 | Okay, let's click Play and see how it goes.
| | 06:38 | There he is waiting for us, and I'm
going to use my Left Arrow key, and there he
| | 06:43 | goes, and we'll exit Play mode.
| | 06:46 | It's not perfect, but not bad
for just a few lines of code.
| | 06:50 | Feel free to make further
adjustments to the camera.
| | 06:52 | There is just one more thing we need to do.
| | 06:54 | I forgot to bring in my Score
Keeper object with the platformer scene.
| | 06:58 | So let's drag the Score Keeper Prefab
into the Hierarchy view and then assign it
| | 07:03 | to the Heart, the Key, and
Lenny. That should do it.
| | 07:09 | Now that we can get most of the way
through, you can see where all those offset
| | 07:14 | values on the cycler
scripts could come in handy.
| | 07:16 | You'd want a skillful player to be able to
make each connection without waiting around.
| | 07:21 | There's only one thing missing now.
| | 07:23 | We'll set up a physics push for
our character in the next video.
| | Collapse this transcript |
| Adding obstacles and pushing physics| 00:00 | While we were in the Platformer scene,
let's look at one more important concept.
| | 00:05 | You've probably noticed that your
character isn't able to push aside the rocks.
| | 00:09 | It's not that they have too much mass,
it's just that Character Controllers
| | 00:12 | aren't set up to be able to push things.
That would require a lot more overhead.
| | 00:17 | We can, however, give him a script that will
give in that behavior with a lot less overhead.
| | 00:23 | It finds out what direction
he's going when he hit something,
| | 00:25 | then it applies a physics force to
the object in the same direction.
| | 00:30 | This script comes straight out of the
docs when you search OnControlColliderHit.
| | 00:34 | Let's go ahead and look for that.
| | 00:36 | Help > scripting Reference, and we're
going to search OnControllerColliderHit
| | 00:43 | and enter, and we can see it says
it's called when the controller hits a
| | 00:47 | collider while performing a move.
| | 00:51 | This is the code we're going to be using,
but it doesn't have any carriage returns.
| | 00:55 | So I am going to go out to the
snippets file and get my version.
| | 00:59 | Exercise Files12/12-04/snippets.
I'll highlight them, right-click, and Copy.
| | 01:10 | Now let's tab back to the editor, create
a new script, and name it Platformer_Push.
| | 01:16 | In the Game Scripts, right-click >
Create > Javascript Platformer_Push and Enter.
| | 01:25 | We'll go ahead and open it up in the
Script editor, and we can just replace
| | 01:30 | what's in there and use Ctrl+V
to copy in our new script.
| | 01:34 | The first of var pushPower, that's going
to be the force we are going to use, and
| | 01:39 | then on the OnControllerColliderHit function,
| | 01:42 | we're going to feed in a
local variable hit, and that's the
| | 01:45 | ControllerColliderHi |
|
|