navigate site menu

Start learning with our library of video tutorials taught by experts. Get started

Unity 3D 3.5 Essential Training

Unity 3D 3.5 Essential Training

with Sue Blackman

 


This course is designed to provide new users with a strong design foundation in Unity 3D 3.5—a game engine for mobile and desktop games and real-time simulations—as well as an introduction to scripting and game functionality. Author Sue Blackman explores the major features in Unity and applies them in actual game situations. She shows how to add lights, texture, multiple views, and effects like fire and smoke to each scene and employ reusable assets. The end result is a sample game with a lush environment, fully animated characters, and some basic interactive gameplay.
Topics include:
  • Understanding game and level design theory
  • Organizing your project in Unity
  • Creating and transforming objects
  • Setting up the geometry
  • Painting in terrain, textures, and trees
  • Adjusting the render settings
  • Importing terrains
  • Creating a first-person controller
  • Building projectiles with JavaScript
  • Creating materials and shaders
  • Lighting the game
  • Working with cameras and multiple views
  • Animating characters and assets
  • Creating fire with particle systems
  • Managing the GUI (graphical user interface)

show more

author
Sue Blackman
subject
3D + Animation, Developer, Games, Game Design
software
Unity 3D
level
Beginner
duration
10h 51m
released
Jul 19, 2012

Share this course

Ready to join? get started


Keep up with news, tips, and latest courses.

submit Course details submit clicked more info

Please wait...

Search the closed captioning text for this course by entering the keyword you’d like to search, or browse the closed captioning text by selecting the chapter name below and choosing the video title you’d like to review.



Introduction
Welcome
00:04Hi! I'm Sue Blackman, and I'd like to welcome you to the Unity 3D 3.5
00:08Essential Training.
00:10Unity is a multi-platform game engine used to create mobile and desktop games as
00:15well as real-time simulations.
00:17In this course, we'll start off with the basics by exploring the Unity
00:20interface and getting familiar with the fundamentals of 3D space, navigation, and transforms.
00:27Next, we'll learn how to create lush environments using Unity's Terrain
00:30Editor and atmospherics.
00:33We'll ease into Unity scripting, and see how it's used to bring your art assets
00:37to life using physics and logic.
00:40Using a game environment created just for this course, we'll explore
00:44cameras, lighting, particle systems, and other popular components of level and game design.
00:50If you're ready to look at one of today's most popular game engines then let's
00:54get started with Unity 3D 3.5 Essential Training.
Collapse this transcript
Unity basics
00:00In this course, we will cover the basics of the Unity game engine.
00:04Unity comes in two versions:
00:06a free and a pro version.
00:08We'll be recording using the pro version, but most everything we cover can be
00:12done in the free version as well.
00:13I will let you know in the few videos where we cover pro-only features.
00:18The Unity game engine can be used on either Mac or Windows machines.
00:21As Unity game development encompasses an eclectic mixture of skill sets, I'll be
00:27working off the assumption that you have a passion for creating games but not
00:31necessarily experience in any or all of the fields we will be making use of.
00:36Knowledge of 2D texture making, 3D modeling and animation, programming
00:41and real-time game engines is a plus but not crucial to this essential training course.
00:47In Unity, most of the functionality has to be scripted, and while there is
00:51a massive amount of freely available scripts floating around in the Unity
00:54community, figuring out how and where to use them can be frustrating and intimidating.
00:59To that end, I've designed this course to take you through the basic Unity
01:03feature set while learning how to write scripts to tie everything together.
Collapse this transcript
Using the exercise files
00:00If you are a Premium member of the lynda.com online training library, you have
00:05access to the exercise files used throughout this title.
00:09The Unity project files are compatible with Unity 3.5.
00:14The exercise files are in the exercise files folders, which I've placed on the desktop.
00:19You can store them wherever you'd like.
00:22The exercise files for this course are very large,
00:25so we've cut them into smaller chapter folders so you can download them as needed.
00:29They reside in sub-folders named according to the movies.
00:34In the folders, you will find scripts, art assets, Unity packages, code
00:41snippets, and the Unity project.
00:44We have also provided code snippets in a free exercise files folder that is
00:49available to all subscribers.
00:51It is not necessary for you to use these files.
00:54Feel free to use your own files in place of them.
00:57When you open the files, Unity will not necessarily show the same view in the
01:01scene window that you will see in the videos.
01:04You may have to adjust your view using the basic viewport navigation controls.
01:09One more tip before we get started:
01:11be sure to save the scene and save the project at the end of each video.
01:19If you're a Monthly or Annual subscriber to lynda.com, you don't have access to
01:24the exercise files, but you can follow along with your own work.
01:28Let's get started.
Collapse this transcript
1. Exploring Unity 3D
Exploring the interface
00:00When you first start Unity, the demo project will automatically load,
00:04Angry Bots for this version.
00:06The Welcome screen has several useful links that you may want to investigate at a later time.
00:11I'm going to turn off Show at Startup and then I'll go ahead and close
00:14the Startup screen.
00:15Let's start with a brief overview of the Unity Editor.
00:18Unlike many of the button-heavy interfaces you may be used to, Unity's UI is fairly minimal.
00:24The Unity Editor is made up of several tabbed windows called views.
00:29With the default layout, we can see the menu bar, toolbar, Scene, Hierarchy,
00:37Project, and Inspector views.
00:40We can also easily tab to the Game view.
00:44This layout is referred to as the wide layout and is useful while the project is
00:48fairly small, or for showing the contents of the Scene view.
00:52On the right side of the screen, we've got the Layout dropdown and that will
00:56allow us to go between the 2 x 3 layout and the wide layout.
01:00We'll be using both those regularly throughout the series.
01:04The Scene view is the graphical representation of the currently loaded scene.
01:09In Unity, a game or project may consist of several scenes, but only one can be
01:14active in the Editor at any one time.
01:17You'll be able to see 2D and 3D assets as well as icons representing things like
01:22cameras and lights and other non-rendering scene objects.
01:27This is where you'll be able to populate your game and arrange the environment.
01:32Besides navigating the view and positioning the assets, the Scene view also has
01:36its own toolbar that controls how and what you will see and hear in the view.
01:40Tabbing to the Game window, you'll find the scene is viewed from usually the main camera.
01:47The Game view is a runtime environment where you'll be able to test your game
01:51play while still having access to its contents in the other views.
01:55You'll only be able to interact with it during Play mode.
01:59Close to the Scene and Game views, no matter which layout you're using, you'll
02:03see the Hierarchy view.
02:05It contains all of the game objects currently in the loaded scene.
02:09The arrows next to the object names indicate parented objects.
02:13At runtime, you will be able to see objects being dynamically added and
02:16destroyed in the Hierarchy view.
02:19The Project view is the repository of all your scene's assets.
02:23This includes textures, 3D assets, scripts, sound files, scenes--in other words,
02:29everything associated with your project.
02:32It mirrors the Assets folder in the Project folder created on your machine.
02:37Once an asset has been added to the project, you must never move it around
02:41outside of the Unity Editor.
02:43The Inspector view is where you'll be able to adjust and view properties
02:47or parameters associated with game objects, scripts, scenes, or the project in general.
02:53Most changes made during Play mode are only temporary, allowing you to
02:57experiment without the fear of losing your original settings.
03:01At the far left of the toolbar, you'll find the navigation tools.
03:05The leftmost button deals with the Scene view navigation, while the other three
03:10are for transforming objects in the scene.
03:13Several keyboard shortcuts can be used in conjunction with the mouse for scene navigation.
03:18The next set of buttons have to do with the coordinate systems and pivot points
03:21when transforming objects in the Scene view.
03:24The Play mode buttons allow you to go from Edit mode to Play mode, so you can
03:29test your game and tweak parameters to fine-tune it.
03:31Once in Play mode, the UI darkens to remind you that you are in Play mode and
03:36most changes made are temporary.
03:38The play button is toggled on an off as there is no stop button.
03:42The Layers dropdown allows you to select which objects are displayed in the Scene view.
03:47The Layout dropdown, as we've already seen, allows you to change the UI layout
03:52using presets, or manage custom layouts.
03:56The menu bar is where files are handled, projects and assets managed, game
04:01objects created and embellished, terrains created, and specialty features or views accessed.
04:08The Help menu will take you quickly to Unity's online help, user forum for
04:12general discussion, and other useful places.
04:16If you have a quick question that only requires a simple answer, try Unity's Answers.
04:21So, there is your brief overview of the Unity layout.
04:24We'll be starting our own project in the next video.
Collapse this transcript
Organizing your project
00:00When you first open Unity, it loaded the demo project.
00:04Once you've loaded a project, every time you open Unity from that point on, it
00:08will automatically load the last project.
00:11So, let's start a new project of our own.
00:13From the File menu, select New Project.
00:18Unity's Project Wizard opens to the Create New Project tab.
00:23Start by setting the location.
00:25I'm going to browse and I'm going to create mine in my chapter 1, movie 2,
00:31exercise file folder:
00:33Desktop/exercise files1_5/Ch01/01-02.
00:37At this point we need to create a new folder.
00:45So I'm going to right-click, New > Folder, and I am going to name
00:51this MyFirstProject.
00:58This is the name of your Unity project, by the way, this folder.
01:03And then we say Select Folder.
01:06Once again, this folder is the new project.
01:11Back in the Project Wizard, we'll need to import a few packages to start
01:14populating our project.
01:17Packages can contain just about any kind of asset, from scripts to art assets
01:22to readymade scenes.
01:24Let's start by choosing Character Controller, and we want Scripts, and let's
01:31grab the Terrain Assets.
01:33We'll be adding other packages, both Unity standard and custom, as our
01:39project progresses.
01:40For now, click Create.
01:42Now, we don't want to save changes made to the AngryBots scene, so we'll just
01:47click Don't Save, and wait for the packages to load.
01:51Whenever you load a new project, Unity closes and reopens with the new one.
01:56You cannot have multiple versions of Unity running on the same machine.
02:00The first thing you may want to do is choose the layout preset.
02:04Since we have nothing to look at in the Scene view, let's use the 2x3 to start.
02:08This is over in Layout.
02:10I'm going to choose the 2 x 3, right now. It's on Wide, and there we have 2 x 3.
02:15The next thing you may wish to do is change the color scheme if you're using Unity Pro.
02:22From the Edit menu, Preferences, under General, if you have Unity Pro, you can
02:30choose between the light scheme or the dark scheme.
02:38If you're not using Unity Pro, you will only be able to use the Light skin.
02:43I prefer the light skin, but I'm going to switch back to remind you that I'm
02:47using Pro since there are several features that are only available with Pro, and
02:51we can close this Preferences dialog now.
02:53Now that we've got a bit of the setup out of the way, let's look and see what we
02:58have available in our project at this point.
03:01So, we brought in several standard assets, and we can see a folder for each of
03:06those packages we brought in, over in the Project folder.
03:11Let's open them up and see what we've got:
03:13Scripts, Terrain Assets.
03:17Rather than opening each subfolder with its subfolders manually, we can expand
03:22them all by holding the Alt key while clicking the arrow.
03:25So, I'm going to close this up again, hold my Alt key, and now, when I open
03:30it, we see everything.
03:32We can close it and open again, and it's still expanded.
03:39But if you hold your Alt key and close it, next time you open it up,
03:44it's compact again.
03:46Let's take a few minutes to see what's in there. I'm going to drag the view wider to see things easier.
03:51Once again, I'll hold Alt key and expand, and as you can see, you can resize
03:59the views by clicking and dragging on the separator bars.
04:03Let's go up to the operating system and see what we have in the Project folder.
04:07When we created our project, Unity created four folders:
04:10Assets, Library, ProjectSettings and Temp. Let's go find them.
04:15I'm going to right-click here, open the Windows Explorer, find my Desktop, my
04:231_5 exercise files/Ch01/ 01-02. Here's my project.
04:31When I open that up, we'll see Assets, Library, ProjectSettings, and Temp.
04:38The only thing we're going to deal with is the Assets folder.
04:42When we open it up, we'll find Standard Assets, and the three packages we brought in:
04:49Terrain Assets, Scripts, and Character Controllers.
04:54The Assets folder is the only folder we will be dealing with, and the only thing
04:58you can do with it, outside of the Editor, is to drop new assets into it.
05:02See all those extra cryptic folders?
05:04Let's go back up here.
05:07Library, ProjectSettings, and Temps.
05:09That's where the paths and relationships between scripts, meshes, materials,
05:14textures, and everything else are stored.
05:17If you do any rearranging of assets through the operating system rather than the
05:21Unity Editor, the relationships will not be updated and things will get broken.
05:25We'll go back to the 01-02 Folder.
05:29The next thing to understand about your Unity project is that to create a backup
05:33of it or to take it to another machine, you'll need to duplicate or move the
05:37entire project folder.
05:39The Unity project was designed to be used in conjunction with a sub-versioning
05:43system such as SVN or Unity's own Asset Server, where each time the project or
05:49scene is saved, a backup of the original is automatically saved.
05:54Since the majority of casual users in small studios probably can't justify the
05:58expense of a sub-versioning system, you may occasionally want to save off
06:02versions of the project manually.
06:05Let's close this out.
06:07Let's go ahead and save the current scene, even though it's only got the
06:10default camera in it. File > Save Scene.
06:15Back in the Editor, from the File menu, choose Save Scene. Name it MyFirstScene
06:21and save it in the default location. MyFirstScene.
06:28Before we close and reopen the project, let's deal with the warning message that
06:32popped up at the bottom.
06:34Click and double-click the message to bring up the console.
06:36So I'm going to click, and I want to double-click the message in the console,
06:42and that will bring up the Script Editor.
06:45We'll see a lot more about the console later, but for now, we just need to fix the problem.
06:50In line 193, it looks like it needs an extra bar.
06:54So add the bar, save the script, and close the Script Editor.
07:03Our message goes away, and now we can close the console.
07:09So, let's go ahead and save the project and then close Unity.
07:16Now, you can open a Unity scene through the operating system,
07:20Windows Explorer or Mac Finder.
07:23Back in the operating system, we need to open our folder, locate our
07:29project, MyFirstProject, and then you need to open it up, and from the
07:35Assets folder--which by the way is the Project folder, when you're inside the
07:40Editor--we can find MyFirstScene.
07:45Click on the newly created scene.
07:47Unity opens with that scene loaded.
07:50As a final tip, if on the rare occasion your project is somehow gotten corrupted
07:56and Unity is not able to open it, your best bet is to manually open another
08:00project through the operating system.
08:03At that point, it may be necessary to clear some of those cryptic cache folders,
08:07but only as a last resort.
08:09So now you've created your first scene in Unity.
Collapse this transcript
Exploring Scene view
00:00Since we do not yet have anything in our test scene, let's open the demo project
00:04so we'll have something to explore the Scene view with.
00:07From the File menu, select Open Project, and the Unity Project Wizard comes open.
00:14What we want to do this time is we want to select from a recently open project. We want AngryBots,
00:21but if you've got a different demo project, just open it.
00:24So, select it and Open, and Unity loads the new project.
00:29Switch to the wide layout so the Scene view will take up lots of real estate.
00:33If you remember, it's over on this far dropdown, I'm going to switch over to Wide.
00:38Notice that the Hierarchy view shows only the default camera of the new scene.
00:44In the Project view, locate the Scene icon for the project and click on it to load the scene.
00:50Here it is, right here, so we'll click it in.
00:54If you are using a project other than Angry Bots, you may need to go looking
00:57for a scene to open.
00:59In Unity, scenes are like levels, so there may be several of them and the author
01:03may have created a Scenes folder to hold them.
01:05Scenes may also contain nothing but menus, so you may need to open a few before
01:10you find one with level-type content.
01:13In Angry Bots, you will see something like this.
01:16Let's experiment with the Scene view toolbar.
01:19At the left, you will see it set to Textured for the Display mode.
01:24Let's click on that and experiment with some of these.
01:28Wireframe is going to leave you with a bunch of black wires. Sometimes it's useful.
01:35And Text-Wire--that's the other one that we'll probably be using occasionally--
01:39is going to show both the objects, the textures, and you can also see the
01:44wires in there as well.
01:45So those are two we are going to use most often:
01:48Textured and Text-Wire.
01:49We're going to go ahead and switch that back to Textured now.
01:54The next button is the RGB dropdown, and it offers several other options.
01:58The next one though is the Lighting toggle.
02:02In Angry Bots, if I toggle the Scene Lighting icon off and on, there's very
02:06little difference, indicating most of the lighting has been baked into textures
02:10or that the lights in the scene have been limited in range or will only be
02:14activated at certain times.
02:16The next button, the Game Overlay button, toggles things like background and 2D
02:21objects off and on in the view.
02:23In Angry Bots, the background images toggles off and on and the grid appears.
02:30To the right of the Overlay button is the icon that toggles sound off and on.
02:34You will only hear the sound if an object with an audio component is selected.
02:38The Gizmos dropdown on the right-hand side lets you see which 2D icons are
02:45being used to represent things like lights, cameras, and other objects, as well
02:49as letting you assign custom icons.
02:52You can allow scaling of icons or adjust the size.
02:58If I increase the size, you can see that there are actually lots of lights and
03:02other icons in the scene.
03:03Enabling scaling prevents the icons from cluttering the scene and blocking
03:08out the 3D geometry.
03:09In the next video, we'll be going over scene navigation.
Collapse this transcript
Navigating Scene view
00:00You're probably itching to start looking around the scene.
00:03Navigating the Scene view is easily done with keyboard and mouse.
00:07Position the cursor inside the Scene view, and to pan, hold the middle-mouse
00:11roller down and move the mouse back and forth.
00:15Note that the Pan button becomes active up on the navigation toolbar.
00:20If you have no middle-mouse roller, click on the icon, hold the left-mouse
00:25button down while moving the mouse.
00:28Hold the right button down while moving the mouse and you can look up, down, and around.
00:35This time the button changes to the Orbit icon.
00:39To zoom the viewport, hold the Alt key plus the right-mouse button and move
00:45the mouse up and down.
00:50For Flythrough mode, hold the right-mouse button down, and use the W, A, S, D keys.
00:58W, A, S, D. Plus Q and E for up and down.
01:06Q, E. This puts you into a quick first-person view navigation.
01:14You can also select an object in the Hierarchy view and press the F key.
01:19Let's find the Player.
01:22So, if I click on the Player, and I press my F key, as long as my cursor is in
01:27the viewport, it zooms right to him.
01:30This centers the Scene view and pivot point on the selected object.
01:35The arrow keys allow you to move around on the X and Z planes:
01:39left, right, up, down.
01:45For CAD and Max users, Y is up in the world rather than Z. I would recommend
01:51that you use a three-button mouse, but if you only have a one-button mouse
01:55available, you can check the Unity manual for more instructions.
01:58We'll go there quickly.
02:01Help > Unity Manual. And we want to look up Scene View Navigation, and you can
02:09look through that for different options.
02:13So we'll close that. And back in the Unity Editor, the Scene Gizmo--this little
02:18guy up here--lets you switch between perspective views and orthographic views.
02:23If I click on this one, it swings around. And you can keep your mouse in one
02:29spot and get the different views:
02:33top view, back view. And you can go back into perspective by clicking on the center cube.
02:41At this point, I would encourage you to spend some time navigating around the
02:45scene to get comfortable with the controls.
02:47In the next video, we'll be creating some Unity objects of our own.
Collapse this transcript
Creating objects
00:00Unity allows you to create several different types of primitive objects.
00:04Primitives are objects that can be described by a set of parameters such as a
00:08sphere's radius, a cylinder's height, or a plane's length or width.
00:12In Unity, you won't be able to change the number of segments or modify the
00:16primitives, but they can be quite useful as is.
00:19Let's open the project we started in the earlier video, or open the project from
00:24this video's exercise files folder through the Open Other button. So File >
00:31Open Project, and you can either open it here if you have your own file or if
00:38you are using the exercise files folder, Open Other, locate it, and in chapter
00:4801-05, MyFirstProject.
00:52When we are opening this way, we don't have to open the scene; we are opening
00:56the entire project, so Select Folder.
00:59And we don't need to save the AngryBots scene.
01:03We won't be adding very many objects, so let's use the Wide layout.
01:08We are already in it on this one, so we are good to go.
01:11Make sure the Game Overlay button is toggled off.
01:16And now we can see the grid. Let's start by making a plane.
01:19From the GameObject menu, select Create Other and click on Plane.
01:25If you haven't messed around in the Scene view yet, the plane will be created at
01:290, 0, 0, as can be seen in the Inspector, in the Transform section.
01:35In the last video, we learned how to navigate the Scene view in general, and
01:39while that's useful, as soon as we start dealing with objects on an individual
01:43basis, we will want a more direct way to zoom in on them.
01:47Now that we have an object that we want to work with, we can do just that.
01:51Select the plane in the Hierarchy view and double-click it.
01:56The plane becomes the focus of the Scene view, and you can zoom closer if you
02:01need to, using Alt and the right mouse.
02:08You can also use the middle-mouse roller to zoom back and forth.
02:17At this point, if you orbit the view-- Alt+Left Mouse--it orbits around the plane.
02:26If you are new to 3D, you will also notice that when you tip the view to look
02:30under the plane, you can no longer see it.
02:34In polygon modeling, objects are represented by surfaces only and are
02:38not actually solid.
02:39The surface is drawn only on one side: the face normal side.
02:44A normal is an imaginary line which is perpendicular to the surface of the face
02:48or triangle, and its direction indicates the side the surface will be drawn on.
02:52Another way to focus or find an object in the scene is to use the F key on your keyboard.
02:58Pan the view, hold down the middle- mouse button. and shift the view so that the
03:05plane is still selected in the Hierarchy view but is off to the side.
03:09Make sure that the plane is still selected in the Hierarchy view and the cursor
03:13is in the Scene view, and then click the F key on your keyboard.
03:18Once again, the view changes to focus in on the plane.
03:22Before you start adjusting the view, let's create another object.
03:27From the GameObject menu, this time select Create Other > Cube. Create Other > Cube.
03:35As long as you didn't change the view after you focused in on the plane, the
03:39cube will come in at 0, 0, 0, just like the plane.
03:42But since, unlike the plane, it has a height,
03:45it is buried halfway through the plane.
03:48Let's see what happens if we shift the view.
03:49Zoom and pan so the objects are off to one side.
03:57Create another cube: GameObject > Create Other > Cube.
04:03Instead of being created at 0, 0, 0, it appears in the current center of the Scene view.
04:09If we look over the Transform section of the Inspector, we can see that it
04:13is not at 0, 0, 0.
04:14The other thing to note is that Unity does not increment game names of new objects.
04:21If you look over at the Hierarchy view, we now have two cubes.
04:25If you have 123 rocks in your scene, you probably have no reason to give
04:30them each unique names.
04:32If, however, you do need to be able to access a particular object, you will
04:36want to rename it.
04:37Select the latest cube in the Hierarchy view.
04:40In case, you can't remember which it is, as long as you are not in the viewport
04:44navigation mode, the object's transform gizmo will let you know which one
04:48you've selected. And here is the transform gizmo.
04:53Left-click on it in the Hierarchy view to put it into Rename mode.
04:57Give it a unique name to differentiate it from the original cube.
05:01I am just going to add a 2.
05:04When you have a large number of objects in your scene, you will also be able to
05:08use the Hierarchy search feature to find objects.
05:11Click in the field next to the Q and type "cube."
05:15So if I type "cube," when you press Enter, the hierarchy is filtered to show
05:21objects with cube in their name, and the Scene view grays out all
05:25non-filtered objects.
05:26Since ours was gray covered to begin with, it doesn't look much different.
05:31The main point here is to think about your naming conventions.
05:34They can help you to quickly locate objects in a large scene.
05:37Go ahead and turn off the filter by clicking the little X to the right of the field.
05:42Although Unity doesn't have any formal alignment system, there are a few options
05:47for moving objects to the same place.
05:50The most obvious and most tedious is to copy and paste the transforms of
05:55one object to another.
05:57When we get to hierarchies in parenting, you will find that this method
06:00won't always work.
06:01The quickest way to get an existing object over to another's location is to
06:06select the target object. In this case our target object will be Cube2.
06:11This time I am going to double-click on the cube's name in the Hierarchy
06:15to focus in on it.
06:16Now I am going to select the original Cube and to move this guy over to Cube2, I
06:24am going to go to GameObject > Move To view.
06:28And now our cube is sitting in the same exact spot as Cube2, as we could tell
06:36if we pulled it away.
06:38And I am going to do an undo to pop it back into the same spot by
06:42clicking Ctrl+Z to undo.
06:45This won't align the orientation to match, but usually you only want to get an
06:49object close so you can manually finish its placement.
06:53Unity has a very nice set of snapping tools that we will investigate in a later
06:56chapter when we are building with imported modular objects.
07:01Before we save the scene, let's look at the title bar.
07:04It says Untitled.
07:06Since it was just an empty scene, you probably didn't notice when we reopened
07:09the project that we neglected to open the scene that we saved last time.
07:13So this time we will use Save Scene As to overwrite the first one.
07:18So from File > Save Scene as, we'll chose MyFirstScene, and we'll overwrite it.
07:26And yes, we want to replace it. And from File > Save Project as well.
07:33In the next video, we will delve into transforms and coordinate systems.
Collapse this transcript
Transforming objects
00:00If it's not already open, let's open our MyFirstProject from Ch01, video six.
00:08And we are going to open the project file first and then the Assets folder, and then
00:15we look for our scene with the icon next to it.
00:19Double-click it and our scene will eventually open up.
00:23Check the title bar to make sure MyFirstScene is loaded.
00:26If not, you'll need to find it in the Project view and double-click it to open in there.
00:31Our little scene is pretty minimal now, so now is a good time to learn about
00:36transforms and coordinate systems.
00:37Transforms are position, rotation, and scale.
00:41The concept of position as a location of an object in 3D space and rotation--
00:47its orientation in 3D space--is easy to grasp as being discrete from the actual object.
00:54Scale is a bit more confusing, as an object that has been scaled to half height
00:58could look the same as an object that was that height to begin with.
01:01An object that was scaled to half height, or 0.5, can be returned to its original
01:07height with a scale value of 1.
01:10Let's start with the position transform.
01:12First off though, we've got two cubes in here and I think we want to get rid of one of them.
01:18If we click on Cube number 2 and right-click, we can click on Delete.
01:25You can also delete it by using the keyboard once it's selected.
01:29Now if we click on the cube in the viewport or the Hierarchy and we are not in
01:33Scene navigation mode, we can see its transform gizmos.
01:38If you are in navigation mode, you will need to press the Transform button on
01:42the toolbar to get into navigation mode.
01:45The gizmo is color-coded were RGB equals XYZ. In other words, red represents
01:51X, green represents Y, and blue represents Z. If you grab, say, the Z, or blue,
01:59arrow, and drag, the cube is constrained to moving along the Z direction.
02:05Let's try moving the cube in the three directions with the gizmo arrows.
02:08While you are transforming the cube's position, watch the Position values change
02:17in the Inspector over here.
02:24Note also that an active arrow turns yellow.
02:27Now take a look at the colored squares in the center of the gizmo.
02:31These will constrain the movements to two directions, indicated by the plane
02:36the square lies on.
02:38If we look at the colors, the color of the square indicates the only direction
02:42the object can't go.
02:47If I select the red one, we can go up into the Z, but it can't move forward
02:54in the X. If we drag the green square, the cube moves in both the X and Z
03:00directions, as you can see by watching the Position values change in Inspector again.
03:04Moving an object on the X or Z along with the Y can often produce unwanted
03:12results in the perspective view,
03:13so don't be shy about switching to an orthographic view to help
03:17position objects.
03:18I am going to click the Scene gizmo to put myself into an orthographic viewport.
03:25Now when I move the X and the Z, I know exactly where the cube is going.
03:31And when I am finished, I can click the center cube to put me back into Perspective.
03:36Middle-mouse pan brings my cube back into the viewport.
03:41Let's take a look at rotation next.
03:44With the cube still selected, switch to the rotation by clicking the Rotation
03:48button in the toolbar or pressing the E key.
03:54The rotation gizmo appears as several circles.
03:57The colors represent the axes the object will be rotated on.
04:01Start by rotating the cube on the Y axis--
04:04that's the green circle-- about a quarter of a turn.
04:06The Inspector reports the rotation in degrees.
04:12So I have just rotated this guy about -43 degrees.
04:16With the introduction of rotation, we are faced with the concept of
04:20coordinate systems.
04:21In Unity, the choice is simple: World or Local, as in local to the
04:26selected object.
04:28If you toggle the coordinate system button, you can see that in World the
04:33gizmo is aligned with the scene gizmo, while in Local, it's aligned with the
04:37object itself.
04:39We are going to go up here. Tight now it's in Local and there it is in Global.
04:44So in Global, it's aligned with the world.
04:47In local, it's aligned with the object.
04:50The gray outer circle, which we might be able to see better if we zoom out a
04:55bit--there we go--the great outer circle will rotate the object on a plane
04:59parallel to the viewport.
05:01Note that once the object has been rotated on more than one axis, all numbers
05:05will change with each additional rotation.
05:07So if I rotate this guy and then that guy, now every time I rotate one, the
05:16rest all rotate as well.
05:19Let's put the cube's rotation back to its original value.
05:23Enter 0 in each of the rotation fields by clicking to highlight the current
05:27value and typing 0. So click, type 0; click, type 0; and click, type 0.
05:40Unity will add the decimal point when necessary.
05:43The coordinate system used for stationary objects is usually not an issue since
05:47most can easily use either Local or World for rotation.
05:52If a stationary object rotates off Y in World space or Z in Local space to give
05:58the same result, we really don't care.
06:00We just need to be aware of which we are using.
06:03An object that is not stationary, however, will almost always be transformed
06:07in local space.
06:09Let's select the cube again and set the coordinate system to Local space.
06:14In this case we already are there.
06:16In the Inspector, let's set its Y Rotation to 45,
06:22switch over to Move, and move the cube in the positive X direction, the
06:29direction the arrow points.
06:33Rotate the cube in the Y again.
06:36This time I am going to position my cursor over the Y and I can drag in the
06:41Inspector to rotate it.
06:43And then we'll move it forward in the X position again.
06:48No matter which way the cube is facing, in Local coordinates it will always move
06:54forward with the same arrow.
06:56As you can guess, this is extremely important for transforming
06:59characters throughout a scene.
07:02The last transform to look at is Scale.
07:04You've probably got the hang of the X-Y-Z stuff by now.
07:07Selecting and dragging any of the three colored cubes will produce a
07:11non-uniform scale.
07:12So let's turn on Scale and non- uniform in the X, non-uniform in the Y, and
07:21non-uniform in the Z. I am going to use my middle-mouse button to pan back
07:25into the center again.
07:26There is currently no way to scale two axes at once though, so your best bet is
07:32to do a uniform scale first--uniform is the center one--and then do a non-uniform
07:38scale on the single axis to achieve the result you are going for.
07:43Try making a large load box.
07:46You may have noticed that the coordinate system is grayed out and set to Local.
07:52If you think about it, performing a non-uniform scale on a rotated object would
07:56produce a skewed result,
07:58so Unity removes the temptation by removing the option.
08:02Next to the coordinate system is the Pivot button.
08:04Since Unity's native objects all have the pivot points in their centers, we'll
08:08hold off on pivot points for now.
08:10To recap, transforms are position, rotation, and scale.
Collapse this transcript
2. Exploring the Terrain Editor
Setting up the terrain geometry
00:00Let's continue with MyFirstProject.
00:03We're going to be using the Terrain Editor in this chapter, so let's go ahead
00:06and make a new scene in the project.
00:08From the File menu, select New Scene. And next we're going to go ahead and save
00:17our scene: Save Scene As.
00:19We're going to name this scene TerrainTest. Enter.
00:28And we'll let it save in the default location.
00:31So now here's our new scene, TerrainTest, and our original Scene, MyFirstScene.
00:38And if you didn't notice it before, it's now pretty clear that the Project view
00:42is always listed alphabetically.
00:43As you create your game, it will be up to you to keep your assets organized,
00:48so let's get started by creating a folder just for scenes.
00:52If we right-click in the Project view we can bring up the Create menu, and
00:59we're going to create a folder.
01:02So let's name this new folder Scenes.
01:08Now we can drag our two scenes into the folder.
01:14Okay, let's make a terrain.
01:16From the Terrain menu, select Create Terrain, select the terrain in the Hierarchy
01:23view, and then let's find or focus it by double-clicking on it.
01:29The first thing worth noting is that it comes in at 0, 0, 0.
01:33And its pivot point, though, is at a corner rather than its center.
01:37Let's get a closer look.
01:39Put the cursor over the terrain in the Scene view and press the F key.
01:45We're zoomed in to a very close view of the terrain.
01:48If we move the cursor off the terrain again and press F, it zooms out so we
01:54see the whole terrain.
01:56If you look in the Inspector, you'll find nothing that tells us how big the terrain is,
02:00so that would be the first thing we want to set up.
02:04From the Terrain menu, we're going to select Set Resolution.
02:13This is where we will determine the size and height of the terrain plus the size
02:17of the various bitmaps that will be used internally to keep track of the
02:20topography, terrain meshes, and texture placement.
02:24The terrain defaults to 2000 by 2000 by 600 for the maximum height.
02:30In Unity one unit is considered to be one meter, or about three feet,
02:36so the default is a pretty big chunk of terrain.
02:39It's tempting to start with a large terrain just because you can, but remember,
02:44your player would need to traverse it, and preferably not by placing a soda can
02:48on one of the arrow keys.
02:51So let's go ahead and reduce the size of our test terrain to 200 by 200 for the
03:00width and length, and we will use maybe 400 for the height.
03:03We'll leave the rest of this stuff on the default numbers.
03:08And we'll go ahead and hit Set Resolution. And then I'm going to use middle-
03:12mouse roller to zoom in. And you can even double-click on the middle-mouse button
03:22to zoom in on an object in the viewport.
03:25The next step is crucial.
03:28We need to decide how deep we want to be able to paint depressions for lakes,
03:32rivers, pits, or any other low-lying features.
03:35From the Terrain menu, we're going to select Flatten Heightmap. And we'll set the
03:44Height to 100 and click Flatten.
03:51What this means is that when we're painting a terrain lower it cannot go any
03:57lower than 100 meters.
03:59The crucial thing about this step is that if you do it after painting your
04:04topography, all of your hard work will be lost,
04:08so remember to do this one right after setting the resolution.
04:13Okay, now we're ready to start creating our environment.
04:16We'll do that in the next video.
Collapse this transcript
Painting the topography
00:01In this video, we'll be using the first three terrain editor tools to
00:04create some topography.
00:05Let's select the terrain and get started.
00:08In the Inspector, move the cursor over the toolbar to see the tooltips for each tool.
00:14We're going to be using the first three.
00:16So let's use the first one, raise and lower the terrain height.
00:20I'm going to zoom out so I can see all of my terrain to start.
00:24As you can see, there are lots of brushes to start with.
00:27We may as well start with the default, but let's adjust the size of the brush
00:31before we get going.
00:33And I'm going to make it large so we can see it and when I bring it into the viewport,
00:37you can see it goes blue.
00:39This shows the brush size.
00:41We'll go ahead and start painting by holding the mouse button down--
00:44that's the left mouse button-- and moving the mouse around.
00:48The Opacity setting controls the strength of the brush, so I'm going to reduce it a bit.
00:53Now when I paint, the results are not so drastic.
00:57You can also see that painting is additive.
01:00If we keep painting over something, it gets higher and higher.
01:04Let's check out a few of the other brushes.
01:06Many are very good at adding texture to the terrain when the opacity is quite low.
01:12Let's try this one.
01:13A simple click gives kind of a nice result.
01:17You may have noticed that when you first click with the brush the texture has
01:21more definition than after you let go.
01:23Unity's Terrain Editor has a built- in LOD, or Level of Detail, feature.
01:27Not only is the terrain polygon resolution adjusted for the features we paint on
01:31it, it's dynamically adjusted according to the distance from the camera.
01:35As you get further away, the terrain mesh is reduced.
01:39Most meshes show their wireframes when selected, but the terrain mesh does not.
01:44To see what's going on with it, we can change the viewing mode to Tex-Wire.
01:49Now you can see the resolution increase when you zoom in and out, as well as when you paint.
01:57Let's set the viewing back to Textured and try some depressions.
02:08For depressions we hold the Shift key down. And that is also additive, but it
02:14will bottom out at the 100 meters that we set in the flattened heightmap.
02:20The next tool over is the Set Height tool.
02:23This one allows you to specify height limits within the maximum height we set
02:27when we set first set up the terrain.
02:29Under the height, you can see that the range will top out at 400 meters, the
02:34height we specified.
02:36This one though I'm going to set to about just over a hundred and now when I
02:41paint, we'll get a nice low plateau.
02:45You can also find out where you are on this one. With the Set Height tool
02:51when you hold your Shift key, it will sample the height range that your cursor is over.
02:57So if we watch over in the Inspector and I move my cursor over this mountain
03:02peak and click Shift, then it sets it to whatever height that was.
03:07So it's an easy way to find out how high you are before you start painting again.
03:11Note that the brush size and opacity are retained between these two tools.
03:16The next tool is the Smooth Height tool, perfect for softening edges of jagged
03:20peaks left over from the other tools.
03:22So here is the relax. And if we turn the Opacity up, you'll see much more result
03:29here. Then it sort of lowers and flattens things.
03:34If you have gone beyond the point of no return, like I sometimes do, feel free
03:38to flatten the heightmap again for a clean slate.
03:41And we'll set this to 100 again and Flatten.
03:47We still need our terrain,
03:48so I'm going to press Control+Z to get it back again.
03:52In the next video we'll start painting textures on our terrain.
Collapse this transcript
Painting the terrain textures
00:00Unity has several very nice terrain textures included in the terrain assets
00:04package we included when we first set up the project.
00:07If you don't see the Terrain Assets folder inside the Standard Assets folder,
00:12you can easily get them through the Assets > Import Package > submenu.
00:18Assets > Import Package, and the submenu shows it right here.
00:26Ours is here, so we can go ahead.
00:29If you wish to use your own images for the terrain, make sure they tile in all
00:33directions, are based to size such as 512 by 512, and are already loaded in the
00:39project, either through the operating system or through Assets > New Assets.
00:45Once inside the project, you may wish to create a folder for your own textures.
00:50The first texture we add to our terrain though will fill the entire surface,
00:54so we need to choose accordingly.
00:56Once again, we select the terrain, and in the Inspector we are going to use
01:02Paint Terrain Texture.
01:03And the first thing we need to add is a texture.
01:08So under Edit Textures, we click on Add Texture.
01:14The first thing we need to do is select the texture.
01:19The Asset Browser opens up and we see a bunch of textures here.
01:23In the Asset Browser you can choose how much detail you want to see on your
01:29assets, whether they're textures or whatever.
01:32And you can do this by moving the slider over here.
01:35I'll put it back to about this one.
01:38Let's start with the cliff layer.
01:39Now remember, this is the first texture we are adding so it's going to cover
01:44the entire terrain.
01:45I can double-click it in and now I have to click Add and now our entire terrain is
01:53covered with that particular texture.
01:56Let's load a few more textures to paint with.
01:58Once again, Edit Texture > Add Texture, browse for a new texture--this time I'm
02:08going to choose Grass--double- click it in, and click on Add.
02:13Now we've got two textures in here, and the one that's blue, or blue-rimmed, will
02:19be the one that you're painting with.
02:21So now let's paint with the grass.
02:22And I will choose one of the other brushes. And now might be a good time to zoom in,
02:30so I'm going to hit my F key and it zooms me in closer, and now I can continue
02:37painting with this texture.
02:39Besides all of our usual brushes, brush size, and opacity, we also pick up a new
02:47parameter called Target Strength.
02:49Opacity is additive just like the topography painting, but Target Strength gives
02:54you a way to cap the opacity.
02:57For places where inorganic meets organic--say a pebbly path through a grassy
03:01meadow--you'll probably find that full strength and opacity plus a hard-edge
03:05brush will give a better result than a soft blend of textures.
03:09Let's take a minute to look at the mechanism that Unity uses to store
03:13the painted textures.
03:15To do so, first we need to save the scene.
03:18Take a quick look in the Project view before you do.
03:21There's our terrain and there's our two scenes. Terrain, two scenes.
03:28Now save the scene: File > Save Scene.
03:33Now you'll see an arrow next to the new terrain in the Project view.
03:37If we click on that, we find SplatAlpha O. The splat map is a mask that uses RGB
03:46values to save the textures.
03:49By selecting it, we can see it in the Inspector.
03:53The red is my original texture and the green bit is where I painted the grass texture.
04:00You may think that we are limited to only three textures--RGB: red, green,
04:05blue--but that's not so.
04:07Unity will continue to create more splat maps to handle the overflow, but at the
04:13cost of another 1.3 MBs.
04:17If we look down here, we can see that's how big this particular map is.
04:22Also be aware that splat maps are stored in the Project view and unless you're using
04:26versioning software, you won't be able to revert back to an earlier version
04:31that you remember liking better.
04:33The terrain may be used in a particular scene, but it is an asset that resides
04:38in the project.
04:40For my third texture, I'm going to load an alpha channel map.
04:43So I'm going to switch back to the Terrain and I'm going to Edit Textures > Add
04:49Texture, go to the browser again,
04:52and this time I'm going to use one of these alpha channel maps. Totally
04:58inappropriate for a terrain, but we are going to see some stuff with it.
05:02I'm going to say Add, and go ahead and select it. Notice it reverted back
05:07to this guy.
05:08So I need to highlight this one. And now I can paint with this texture.
05:18Notice that it ignores the alpha channel.
05:21So what about tiling?
05:23As long as we kept to the texture specifically created for terrain painting, the
05:27textures are all nicely propionate to each other using the default tiling size.
05:32My totally inappropriate grass clumps will be easy to experiment with.
05:37To edit the texture's Terrain properties, we select the texture--mine is already
05:42selected--we go to Edit Textures, and click on Edit Texture.
05:48The Tile Size X and the Tile Size Y are a bit misleading.
05:52Where normally we may be used to adjusting the number of tilings, in this case we
05:57are adjusting the size relative to the world,
06:00so the results will be consistent no matter how big or small the terrain is.
06:05Bottom line is, the smaller the tiling number, the more tiles, or smaller the
06:10images on the terrain.
06:12We can see that if I change these to 5.
06:17Now you can see my totally inappropriate grass structure is tiling higher.
06:21Then we'll go ahead and click Apply.
06:27Now if we decide we no longer want a texture, which I'm pretty sure we
06:30don't want this one, we can select it and in Edit Textures, we can click on
06:37Remove Texture.
06:38And when we remove it, it reverts back to the original base texture.
06:43There's one last thing to be aware of.
06:47Any edits we make on the terrain-- topography, textures, et cetera--in Play mode
06:52will not be lost when we go back to Edit mode.
06:56So that's something to be aware of when you add anything, whether it's trees,
07:01textures, or topography in your terrain.
07:04In the next video, we'll start painting some trees on our terrain.
Collapse this transcript
Painting trees and forests
00:00Let's continue with our test terrain.
00:02Select the Terrain and click on the Place Trees tool in the Inspector.
00:07Let's start by taking a peek into the Terrain Assets folder to see what
00:10trees are available.
00:12We'll open up Standard Assets > Terrain Assets > Trees Ambient-Occlusion. Here we go.
00:21It looks like we've just got one choice, a palm tree, so let's go ahead and load it.
00:25Just like textures, we need to load the trees we plan to use in the Terrain Editor.
00:30This time the button is named Edit Trees, as you would expect, but the drill is
00:33the same: Edit Trees > Add Tree, click the target to find the available assets,
00:40and click the tree in.
00:43Before we click Add, let's look at the tree parameters.
00:46There's only one associated with individual trees: Bend.
00:49The rest are applied to trees in general.
00:51We won't see the Bend in action for a while yet, but you can go ahead and give
00:55it something like 0.2. A little goes a long way with Bend.
00:59Then click Add to finish the loading process.
01:05Our new tree is loaded and ready to paint.
01:08We no longer have lots of brushes to choose from, so Brush Size and Density
01:11are the main controls.
01:13Let's set the Brush Size and Density low to start with and try painting some trees.
01:20And that should be fairly safe. Now we start painting.
01:24Okay, so there's only a few trees painting.
01:26I'm going to move the Density up a little higher, and now we're starting to get some trees.
01:37Unlike the tools we've used so far, painting is not additive.
01:40To get more trees, we need to turn up the Density and paint again.
01:44As soon as you begin to orbit the Scene view, you will start to see something
01:48odd happening: the trees will seem to pop up and down further back in the Scene window.
01:55There they go.
01:58With trees, there are two levels of LOD.
02:01With the terrain mesh we saw polygons being reduced the further away we got.
02:05With trees we get two levels of LOD. At the first, at the closer distance, the
02:113D trees are swapped out for planes with an image of the 3D tree, the same
02:15image that was generated as a preview as soon as you loaded the tree in the Terrain Editor.
02:20The plane is billboarded, that is, it rotates to always face the camera.
02:24The second level of detail removes even the billboarded version once that
02:29distance is reached.
02:31If you zoom way out from the terrain, you would eventually see the
02:33billboarded trees disappear.
02:36The culling distance is set to 2000 meters as a default, so ours will hang in
02:40there for quite a while.
02:41We'll take a look at the settings later on.
02:44The tree parameters all work pretty much the same way.
02:47You won't see the changes until you paint new trees.
02:50To get additional terrain assets, you can go to the Unity web site:
02:54www.unity3d.com/support/ resources/assets/terrain-assets.
03:07Put the downloaded package in a handy folder outside of the Project folder.
03:11Then import the new assets into your scene through Assets > Import Assets > Custom Package.
03:16While these maybe freely used for commercial and non-commercial use, they may
03:21not be redistributed,
03:22so I'll be using a package with some assets I made or altered so we can give
03:27you the projects for each video.
03:29Back in the Editor, I'm going to go ahead and import the extra terrain assets
03:33from the exercise folder for this video: Assets > Import Package > Custom
03:40Package, and for the 02-04 video, ExtraTerrainAssets. Import. And now we have
03:52a few more folders:
03:53Terrain Meshes, Terrain Textures, and Ambient Occlusion Trees.
03:58Now we can add our extra tree--Edit Trees > Add Tree--and we'll see our new tree,
04:07BanyanOld, in the Asset Browser. Click it in, Add.
04:14Before I start painting, notice that that the palm tree is still selected.
04:17Let's select the new tree, BanyanOld, and paint a few of those guys around the scene.
04:26Okay, now we can test the Erase functionality.
04:29As the instructions say, hold down the Shift to erase trees, hold down the Ctrl
04:35to erase the selected tree type.
04:37Well, we've got the Banyan selected now, so I'm going to hold Ctrl and if I
04:42erase, it only erases banyans.
04:46If I hold my Shift key, it erases everybody.
04:50Okay, save the scene and save the project.
04:53Next up, we'll be painting details.
Collapse this transcript
Painting grass, shrubs, and 3D geometry
00:00The next tool in the Terrain Editor is the Paint Details tool.
00:03With it we can paint the grass, shrubs, and other details that help flesh out our
00:08terrain environment.
00:09It consists of two main types of objects or features: grass and detail meshes.
00:15The first, grass, is created is created solely from textures that are placed on
00:20internally created planes, just like the billboarded trees.
00:22There are a couple of good grass textures in the terrain assets package we
00:26loaded, so we'll start there.
00:29Let's click on Terrain, and in the Terrain Editor we'll move over to Paint Details.
00:36As expected, we need to click on the Edit Details button first.
00:41From its menu, let's choose Add Grass Texture.
00:45A nice, somewhat familiar dialog pops up, and we can load one of the
00:48grass textures.
00:51Let's go for Grass.
00:55Remembering that it will be generating planes for the image, most of the
00:59parameters are pretty self-explanatory.
01:01Noise Spread is the clumping parameter.
01:03A large number will result in more isolated clumps.
01:07There are two colors that get added into the mix as well.
01:10The default Healthy Color is a bit too saturated for me, so I'm going to tone
01:14it down a little.
01:21The Dry Color will be used around the edges of the grass clusters.
01:25When we bake light maps for the terrain, the Shadow Color on the terrain
01:29will also be added in with the other two colors so the grass will appear to
01:32be shadowed as well.
01:34As a default, the planes will be billboarded, but you also have the option
01:38to turn that off.
01:39Let's go ahead and click Add and see what else we've got to work with.
01:43Our interesting choice of brushes is back and can be very helpful in placing the grass.
01:48Brush Size may seem rather small, but it's really easy to go overboard
01:52when painting grass.
01:53To start, I recommend setting the Opacity to 0.1 and the Target Strength
02:02nearly the same.
02:05And my Brush Size down. No, I think I'll leave my Brush Size up.
02:11So I'm going to zoom in with my middle- mouse roller to find a place I can paint
02:14on, and start painting.
02:20And this is using a single- click method. And it's pretty dense.
02:24Okay, now paint by holding your key down. And I'm going to zoom out again.
02:32And at some point, you'll be painting and you won't see anything happening.
02:37That's because the LOD for grass is different than the LOD for trees.
02:42Grass is set to a default of about 80 meters.
02:46So if we zoom in to the far side where we were painting, you can see the
02:50grass now appears.
02:53If we zoom out, it disappears quickly.
02:59As with the other tools, holding Shift while painting removes the grass. And I'm
03:03holding my Shift key and down and removing my grass.
03:09Unlike trees that are limited in density, grass allows you to keep adding more.
03:14If I load the Grass2 texture, under Edit Details > Add Grass Texture, and I
03:22choose Grass2 this time and Add,
03:27I'll select my Grass2 and it will let me paint Grass2 right in with Grass1.
03:37If we zoom in, we'll be able to see that better. So this one is
03:45definitely additive.
03:46Feel free to add more grass to your terrain, and remember to zoom in when you
03:51are working, just so you can tell if you've actually painted or not.
03:54And now we can go ahead and save the scene and save the project.
Collapse this transcript
Painting detail meshes
00:00The second type of detail we can paint onto our terrain is a detail mesh.
00:04We have two options here.
00:06The Detail object can make use of alpha channel bitmaps and relatively simple
00:10polygons such as you might want for shrubs or other leafy plants,
00:14or it can be a solid mesh, such as a rock or cactus or something that doesn't
00:20need to use opacity.
00:22Besides the restriction on texture type, there are a couple other pretty big
00:25differences that we'll be seeing.
00:28So let's get started.
00:29We already have a few detail meshes from the Extra Terrain Assets package
00:34from an earlier video.
00:36Let's take a peek at the new folders to see what we've got.
00:40In the Extra Terrain Meshes folder, we've got a rock, a banana plant, and
00:45something called StripeyPlant.
00:47That should be plenty for us to experiment with.
00:50Select the terrain and the Paint Details tool.
00:54Click Edit Details and this time choose Add Detail Mesh.
01:00Let's start by loading the StripeyPlant.
01:05The Healthy Color is a little too bright for my taste, so I'm going to tone it down a little.
01:11In fact, this is a detail mesh, so I'm going to make it all the way white.
01:15And we'll keep the Render mode to Grass, and then we'll click Add.
01:20This is still a detail with a close LOD so let's use F to zoom in on the terrain
01:24before we start painting.
01:25I'll just clear a little grass area here by using our Shift key, and then we'll
01:37select our new plant, StripeyPlant. And I'm going to make sure that my Opacity and
01:44Target Strength is pretty low.
01:46A little goes a long way with the detail meshes. And we'll click and there we
01:54have detail meshes.
01:56Let's click play and see how this thing behaves.
01:59Since we haven't added a camera yet, we're going to need to switch back to the
02:03Scene view, but now you can see that detail meshes will also react to the wind.
02:13I'll go ahead and stop.
02:15So everything that is a grass detail and all the detail meshes set to Grass
02:20Render type will sway in the breeze.
02:24Right about now you're figuring out why there are two options with our Detail meshes.
02:28We obviously don't want our rocks or solid objects swaying in the breeze.
02:33Speaking of rocks, let's go ahead and add one to our plant library.
02:37So Edit Detail > Add Detail Mesh, and this time we're going to choose the rock.
02:47And here is where we change the Render mode.
02:50If it's grass, it's going to sway.
02:51We don't want it to sway, so we are going to choose VertexLit, and then we'll click Add.
02:58This is another one where you want to keep your Opacity and Target Strength down.
03:02Now if we click, we need to remember to switch over to a rock.
03:09And there we go, rocks.
03:11Our rocks are kind of green, so I'm going to go back into my Edit and I'm
03:16going to turn the Healthy Color down to white and the Dry Color, and then we'll click Apply.
03:26And now my rocks are, well, they sort of blend in, but if we zoom in using the
03:31middle-mouse roller, you can see that we've got lots of rocks.
03:35You may be thinking that the Terrain Editor would be a good way to add boulders
03:39to your environment, but the problem would be that just like the grass, they
03:44would be distance called by LOD mechanism.
03:47In case you are curious, let's try a plant mesh using the VertexLit option.
03:52We'll load the StripeyPlant in again, Add Detail Mesh. We'll grab our
03:58StripeyPlant. And this time we are going to set it to VertexLit and Add.
04:09This time when we put StripeyPlant-- and I'm going to remember to change my
04:13selection this time--
04:15I've just planted a bunch of StripeyPlants.
04:17If we zoom in closer, we can see that the Opacity is not respected on the
04:22VertexLit plants. So I'm going to undo, Ctrl+Z, and get rid of these.
04:28And of course I'm going to go to my Edit Details and remove my
04:32VertexLit StripeyPlant.
04:36So the things to remember about detail meshes are one, in Grass Render mode
04:42they may use alpha channel textures and will be affected by grass type wind, and
04:47two, in VertexLit Render mode, alpha channels are ignored in textures and the
04:53mesh is not affected by grass type wind.
04:55In the next video, we'll be looking at the Terrain Settings tool.
05:00Save the scene and save the project.
Collapse this transcript
Adjusting terrain settings
00:00The final tool for the Terrain Editor is the Terrain Settings section.
00:04This is where you can adjust LOD settings for terrain features, as well as a few other things.
00:10Let's select the terrain and head over to the Inspector again.
00:14Our last button is Terrain Settings.
00:17While fine-tuning these settings is more of an advanced task, it's good to know
00:22they exist and where they're located.
00:24If you're new to real-time game engines, dispelling some of the mysteries may
00:28make the learning process less intimidating.
00:31By now you've heard me mention LOD several times.
00:34When making real-time games or simulations, part of making them fun, challenging,
00:39or interactive is making sure that frame rate is fast enough to allow the play
00:43not to be plagued by laggy choppy graphics and game play.
00:48LOD is all about keeping the poly count low so that the engine doesn't have to
00:52render unnecessary geometry.
00:54So let's take a look and see what's in here.
00:56Under Base Terrain, Pixel Error is the setting that affects the terrain mesh.
01:02To experiment with this, you would want to use the Text Wire setting in the scene display.
01:08It controls the overall mesh density.
01:11Base Map Distance has to do with mipmapping and where the original resolution
01:15texture is swapped out for blurrier mipmapped versions.
01:20You may think more resolution is better, but at some point back in the scene you
01:23may get artifacting.
01:25This is one of the settings I usually leave as is, unless the problem
01:29becomes noticeable.
01:30If the ground texture becomes too sparkly as you move through a scene, you may
01:34want to use a lower setting so the blurrier version happens closer.
01:38The next setting, Cast Shadows, is about whether the terrain itself should cast shadows.
01:44When checked it doesn't mean it will; it just means it can if shadows are
01:48being used or calculated.
01:51Draw turns off and on all the stuff we've painted on our terrain with the
01:55Terrain Editor. Pretty useful if you need to do some remodeling on the terrain
01:59after you've already foliated it.
02:02Detail Distance is the distance in which the details--that's the grass and detail
02:07meshes--are longer drawn.
02:08Detail Density gives you an option to sort of thin them out at a distance
02:13before they're fully culled.
02:15Tree Distance is where the trees are no longer drawn, and Billboard Start is how
02:20far away the mesh trees are swapped for the billboard versions.
02:24Max Mesh Trees allows you to overwrite the billboarding distance without having
02:28to bother with the relevant settings.
02:30To see what the Wind Settings do, we can hit play and switch back to the view
02:35settings and experiment.
02:37So we are going to hit play and we'll switch back over to Scene, and now let's
02:44adjust the Wind Settings.
02:48There is a high setting. Pretty rough.
02:52Lower. And you can adjust a lot of this stuff.
02:56Be warned that changing these settings during runtime will not revert when we
03:00switch back to Edit mode.
03:02So if we keep an eye on our settings and stop, they're still the same.
03:10So there you have a brief run-through of the Terrain Editor settings.
03:14You may not need to tweak any of them for a while, but hopefully you have a
03:18better idea of when they might prove useful.
03:20Go ahead and save the scene and save the project.
Collapse this transcript
3. Creating the Environment
Adding sun, sky, and fog
00:00Let's add a few more important things to our test scene.
00:03So far, we've added lots of trees and detail meshes to the environment.
00:07And while that's pretty empowering, it still doesn't look as good as it should.
00:11The addition of a light to the scene will make things look much better.
00:14We'll be adding a directional light to our scene.
00:17Directional lights emit rays that are parallel to each other.
00:21They're not location-dependent so will light the scene equally wherever they are.
00:26From the GameObject menu, Create Other, let's create a directional light.
00:32To see the light's effect in the Scene view, we need to have the Toggle Scene
00:36Lighting button turned on.
00:37Mine is, but yours might not be.
00:40So let's double-check. And there we go!
00:43Now, we can rotate the light until we like the effect.
00:47I'm going to zoom out a little bit first, and then I'll switch over to Rotate.
00:52And as I rotate the light, you can see it has an effect on the scene.
01:00I'm going to use that one.
01:02If I switch over to Move and switch to Global, you can see that we can pull the
01:09light around wherever we'd like and it doesn't affect the scene at all.
01:13Remember, directional lights are not location-dependent.
01:18So the light makes things look better, but now we need a sky.
01:21The traditional way to make a sky was to use a hemisphere and map an image to it.
01:27A more modern way is to use a cube map with a shader to apply the six sides'
01:32images in the background.
01:34First off, we need to import the Skyboxes package.
01:37So, from Assets > Import Package, we are going to choose Skyboxes.
01:45Import. And you'll find these guys in the Standard Assets folder, and you can
01:56find the skyboxes in the Skyboxes folder.
02:01In the Inspector, you'll be able to see the component parts of the cube maps
02:04that are being used for them.
02:05If we click on one of them over here in the Inspector, and we can see the six
02:12images that are being used.
02:14To add the Skybox to the scene though, we're going to need to Edit > Render
02:19Settings, and load it in through there.
02:23Skybox Material. We click on our little target.
02:26And this is one time when if we were looking at images, here are some of our
02:34skyboxes, and you can see the images really don't give as much information.
02:38So, I'm going to switch it back down to names and I'm going to choose Sunny1 Skybox.
02:47To see it, we'll need to toggle on the Game Overlays button, which is right next
02:53to the Lights toggle.
02:55Now, if I rotate my view and zoom back a bit with my middle mouse, you
03:01should eventually see, ah! There it is, our sunny sky.
03:08So, as long as we are in the Render Settings, let's go ahead and try out some fog.
03:11Up at the top, we have the Fog button.
03:15So we want to use fog.
03:17We can change its color. The nice thing is we can see it happening in the
03:25view as we are changing it.
03:29And depending on your mode, you can add density-- oops, that's overkill--and get it just how you like it.
03:39You can try the different types of fog modes. With either Exponential, you can
03:43change the density. With Linear Falloff Type, you can adjust the start and end
03:47parameters to get the look you want.
03:49I'll let you try that on your own.
03:52So, our scene is starting to shape up nicely but is lacking one important thing: shadows.
03:56We will cover lights and baked lighting later, but we can have a quick
04:01sneak peek at it now.
04:03Shadows tend to be resource hogs even at the best of times,
04:06so first we'll need to tell our directional light to cast them.
04:09So we select this guy, and over in Shadow Types, if you are using Pro, you can
04:17tell it to use hard or soft shadows.
04:24From the Window menu, open the Lightmapping dialog.
04:29Here it is right here, Lightmapping. And we're going to switch over to Bake.
04:36If you are using Pro, you can leave Dual Lightmaps on, but if you are using the
04:40free version, you will want to use Single Lightmaps.
04:44Then all we need to do is click Bake Scene. And that's probably going to take a while.
04:51And there we go! So, we can close the Lightmapping dialog and now we can see shadows in our scene.
04:58If you are using Pro, your dynamic shadows may turn off at this point.
05:02To fix that, you guys can go to Edit > Project Settings > Player, and under
05:14Other Settings, make sure you change your Path from Forward to Deferred Lighting.
05:20Now that we have baked shadows, we can see how the baked shadows are added to
05:25the grass and detail meshes, even as they sway in the wind.
05:29Of course we'll have to start Play mode, and then we'll switch back to the
05:34scene. And I suppose I should move this over to find some of our grass.
05:44And there we go: dynamically swaying grass with shadows.
05:49In the next video, we'll get a chance to experience the environment firsthand,
05:54so go ahead and save the scene and save the project.
Collapse this transcript
Using the First Person Controller
00:01So far, we've only looked at our scene in the Scene view.
00:04To see it in the game window, we'll need a camera.
00:07Fortunately, we have already got one,
00:09so all we need to do is adjust that default camera that was made when we
00:12created the scene.
00:13If we select the camera in the Hierarchy view, we get a small preview of it
00:19over in the Scene view.
00:21We can see where it's pointed, but better yet, now we can move it to match the view.
00:26We do that by going to the GameObject menu and choosing Align With view, and
00:32the camera is positioned to see the view we are currently enjoying.
00:36Now when we click Play, we can stay and watch the scene from the game window.
00:42Pretty, but it's kind of boring.
00:43So I think it's time to experience our scene firsthand, or first person as
00:47the case maybe. Let's toggle back into Edit mode.
00:50Unity is designed to let you script any kind of controller you want, but does
00:56come with both a first-person and a third-person controller to get you up and
01:00running around your scene.
01:01In the Project view, Standard Assets Folder, we see a folder called
01:05Character Controllers.
01:08Let's start by dragging the first-person controller into the Scene view.
01:12It's represented by a capsule.
01:13So we're going to grab the first-person controller and drag it into the scene.
01:20Now is a good time to switch to the 2 x 3 layout so we can see both where the
01:24controller is and what he is seeing at the same time.
01:27We'll switch our layouts.
01:29Up here, we were using Wide; now we are going to be using the 2 x 3 layout.
01:35You might have noticed that the Scene view changed.
01:37That happens when you change the layout.
01:39But it's easy to select the main camera again and use the Align view to
01:43select it again.
01:45So, we'll select our main camera, go to GameObject menu,
01:49and this time we'll use Align view to Selected. And we get back to our
01:53Camera view.
01:55Now, we can see that the Game view is definitely different from the view
01:58from the main camera.
01:59Let's see what's going on.
02:01If we click the down arrow on the first-person controller, we can see that
02:04it has its own camera,
02:06and from the looks of it, it takes priority over the original default camera.
02:10If we click play, we can look around the viewport by moving the mouse.
02:14In the Scene view, if we select the first person's main camera, we can also see
02:19the camera's view gizmo moving.
02:22By clicking in the Scene view, we can move the character with the
02:24Transform Gizmo.
02:26To drive through the scene, we actually need to click back in the Game view.
02:30Then we can use our mouse to look the direction we want to move and use our W,
02:35A, S, D keys to move through our scene.
02:43Let's stop Play mode for a minute and look at the status line.
02:46So we'll click up here and stop. And in the status line we see there are two
02:51audio listeners in the scene.
02:53Please ensure that there's always exactly one audio listener in the scene.
02:57To use any audio in your scene, you must have an audio listener.
03:01To see anything in your scene, you must have a camera.
03:04So, Unity automatically adds the listener to cameras whenever they're created.
03:08Since we may or may not keep the original main camera, let's remove the
03:12audio listener from it.
03:13So we'll select our original main camera, and over in the Inspector, here is our
03:19Audio Listener, and we can right- click and say Remove Component.
03:25At some point, the message will go away now.
03:28Before clicking play again, let's try Maximize on Play from the Game window.
03:34Now click play and enjoy the scene all on its own.
03:41We can drive around just like we did before, W, A, S, D, using the mouse to look
03:49up and down and around.
03:52Let's toggle back to Edit mode.
03:53With something of interest in the Game window, we can look at a couple of
04:00more of its tools.
04:01From the first dropdown, we can change from Free Aspect to various other aspect ratios.
04:07Stats, over here, lets us see where the game's resources are being used,
04:12including the frame rate.
04:14If we turn off Stats and look at Gizmos, we can see things that are usually not
04:19rendered in the game window.
04:20Here, we can just barely see the camera's view range.
04:24So now that we are finally mobile in the scene, we are going to take a look at a
04:27few more options for creating terrain in the next video.
Collapse this transcript
Publishing project settings
00:00Now that we've got the bare essentials under control, let's see how easy it is
00:04to build and publish a Unity scene.
00:06To start, always make sure you've saved your current scene.
00:10Now, we can go to the File menu, select Build Settings, and add our
00:17current scene to the build.
00:19We do that by clicking on Add Current.
00:23Now, here it is, our TerrainTest scene.
00:26Next, we are going to choose our target platform.
00:29I'm using Windows, and I want to make sure I'm on PC and Mac Standalone.
00:35I've selected PC and Mac Standalone, but you can see there are several
00:38other options as well.
00:40Next, we want to make sure our target platform matches, and this is Windows so
00:44we are good, and I'm going to click Build And Run.
00:48First thing we need to do is to decide where we are saving it.
00:51We probably don't want to save it in with the first project, so I'm going to go
00:55up a folder, and give it a name, and let's call it testRun.
01:03I'm saving it here in my exercise files; you can obviously save it
01:06wherever you'd like. And here we go!
01:11This is our startup screen.
01:13You notice that we can change the aspect ratio or the graphics quality, and we
01:20can even remap the keys for input.
01:23Let's go ahead and click play just to see if it worked.
01:28There's the splash screen, and here we are!
01:30And now can drive around using our W, A, S, D keys just like we could in the Game view.
01:37Let's go ahead and close this.
01:38We'll close the Build Settings.
01:44Now that we've seen how easy it is to publish, let's see what else we could
01:48do with the project.
01:50From the Edit menu, select Project Settings > Player.
01:57In the Inspector, we now get a bunch of choices.
02:01Under Icon, either here or here, we can add an image, and I'm going to choose
02:07one for my Extra Terrain Textures, something like my colocaleaf, and now
02:16we've got our icon.
02:18And then remember the splash screen that came up? We could select the splash
02:22image for it, and under Other Settings, we can change things like the Rendering
02:28Path from Deferred Lights to Forward Rendering.
02:32And in Resolution and Presentation, we can disable Display Resolution dialog;
02:38that prevents the player from being able to change many of the game settings.
02:43If we now go back over to File > Build Settings, and Build And Run, we'll save
02:52it in the same place, and yes, we want to replace it,
02:59now, when the game runs, we no longer get the Settings dialog;
03:02we go directly into the game itself.
03:05Let's go ahead and close the game. Close the Build dialog.
03:10We'll make it enabled again.
03:17We'll go back to the Build Settings, and Build And Run again, and you'll see it come back.
03:24Save. Yes, we want to overwrite, and there it is! All right!
03:30So we are just going to quit at this point.
03:33So now you've seen how to go ahead and build a game in Unity.
Collapse this transcript
Introducing the game environment
00:00Up until now, we've covered the basics of creating an environment.
00:04Next, we are going to create a new project that, with the help of a few
00:08extra assets, will become the framework for a game that we'll be creating in this course.
00:13So let's start by creating a new project.
00:16As we saw earlier, its name will appear in the Configuration dialog and on the
00:20title bar of the stand-alone.
00:22So let's name it something clever like UnitySampler. File > New Project >
00:29Create New Project. And I'm going to browse to the Desktop where I've got my
00:37folders. 03-04. And remember in Unity, the folder is the project, so I'm going
00:48to right-click and say new folder, and I'm going to name this UnitySampler, and
01:01select the folder.
01:04Now for this game, for this project, we are going to need the Character
01:09Controller, the Scripts, Skyboxes, and the Tree Creator, and so we we'll create.
01:24Creating a nice terrain can take a while, even at the best of times, so I've
01:28saved out a Unity package with the terrain already created for you.
01:33Let's right-click. Import Package > Custom Package. And in the exercise files
01:42folder for this video/Assets, we're going to bring in MainLevel.
01:52I'll click Open and then Import.
01:54And when we look in our Project view, we can see that it even has a scene for us.
02:01So let's double-click the MainLevel scene.
02:05We don't need to save the default.
02:09And here is our new scene. It comes with a terrain.
02:19And then the next asset we're going to need is some structures.
02:22So right-click again, Import Package > Custom Package, and from the Assets
02:32folder again, bring in structures. And click Import again and here it goes.
02:43This time we have an imported Assets folder and we are going to bring Structures
02:49for Scene into our Hierarchy view.
02:53This adds them to our scene and if we zoom up close, we can see that we've added
03:00a building and a few barricades.
03:06Our game, because it's really more of a game sampler, may be a bit silly, but it
03:10will be more fun than a disjointed set of technique videos.
03:13So here is a quick rundown of the project.
03:16It starts with three areas in a canyon-like space,
03:23a staging area--you can just see it here--a nature area.
03:31The next one will be a dry rocky blasted- looking area with the dog leg so we can
03:36eventually hide a sentry system behind it.
03:39The next feature will be a stone-face building or compound, which we can see
03:44here. And then we've got a deep chasm and finally, a tall peak with a little
03:52ledge at the very top.
03:54So let's look and see a couple of things that are added to this.
03:58I've added a directional light so we can see the shadows.
04:04If you're using Pro and you zoom in, you'll be able to see the dynamic shadows.
04:09If you zoom out, you can see they fade out.
04:13Besides the trees you've already worked with, we have a new addition in
04:16the nature area.
04:17It's a tree created with the Tree Creator.
04:20We'll cover the Tree Creator later in the series, but we'll make good use of the
04:23sample tree that came in with it.
04:25In the next video, we'll revisit the first-person controller to make sure that he
04:30can get around in our new scene.
Collapse this transcript
Fine-tuning the First Person Controller
00:00Now that we've got our fancy new terrain, we'll need a first-person controller.
00:05Let's go ahead and add a first-person controller from the Standard Assets folder.
00:08Here is our Standard Assets, Character Controllers, and our First Person Controller.
00:14If we are careful, we can drag him straight into the compound area and then we
00:19can rotate him, if we zoom in a little bit here, to face the compound.
00:34And if you want to move him a little more to get him kind of in front of the steps,
00:39that will be even better.
00:41So first off, we need to focus in on him,
00:44and we can double-click him. And we want to make sure that I am using my Alt key
00:49to rotate the view, make sure that he is not struck in the ground, because we
00:53want to prevent a free-fall accident.
00:56And now we can go ahead and click play and drive up the front steps.
01:05So I've just used my mouse to get oriented in here, and I am going to go ahead
01:10and move him by pressing my W key.
01:13We try to go in here and we get blocked.
01:17So the first-person controller goes smoothly up the steps, but when we get to
01:21the doorway, the ledge seems to block us.
01:24You can jump over it using a spacebar, but we'll have the same problem with the
01:28rest of the stairways inside the building.
01:31So there are two things at work here.
01:33Let's go ahead and exit play mode, and if you open the Structure's folder in the
01:39Buildings group and find something called Stair ramp, we can see that it has its
01:47Mesh Renderer turned off.
01:49Let's click that on for a minute, and now we can see, especially in the Game view here,
01:54that there is actually a plane there that covers the steps and makes
01:58navigation smoother.
01:59This is a fairly common trick, especially in real-time applications such as
02:03architectural walkthroughs.
02:05Let's go ahead and turn the Mesh Renderer off.
02:08The rest of the stairways don't have ramps, so we are going to need to make some
02:12adjustments to the First Person Controller's parameters.
02:16Select him in the Hierarchy view and over in the Inspector, we are going to look
02:22at the Character Controller section.
02:25And we want to change the Slope Limit to 90 degrees.
02:31If we click play and try it now, it move easily into the area and navigates
02:36the stairs with ease.
02:37And we go up here, and it goes right on in.
02:46I have also left gizmos on, so I need to turn that off as soon as we get out of Play mode.
02:54So I'll exit Play mode. The first thing I'll do is turn off gizmos, and I am going
03:00to turn off Maximize on Play, and let's try one more thing.
03:04Now I'll click play again, and this time we've got a problem.
03:11Not only can he get up the steps, but if we click the spacebar to make him
03:17jump, he can also climb straight up the sides of the cliffs, and that's
03:22probably not a good thing.
03:24So let's exit Play mode, and we need to change our Slope Limit again.
03:29If we set the Slope Limit back to 45 and set the Step Offset to say 1, he will
03:35be able to go over steps shorter than one meter high, but he still won't be able
03:39to go up small inclines.
03:41So the best solution for easy navigation without full access in this environment
03:46is probably going to be a compromise between the two.
03:49Let's go ahead and set the Slope Limit to 60 and then Step Limit to 0.5.
03:57Now we would be able to click Play and explore the inside of the compound but
04:02not be able to climb the Canyon walls.
04:05Let's click Play and explore the rest of the terrain.
04:09If we head out from the compound, you'll soon hit a little crevice that we can
04:13jump by hitting the spacebar.
04:16If you are not a very good navigator like me though, you might want to put a plank there.
04:20Let's exit Play mode and in the Structures for Scenes, you'll find something
04:26called Bridge Plank.
04:28If we double-click on it and use Alt to orbit our view a little bit, we
04:36should be able to drag him right into place so that we no longer have to
04:40force our player to jump.
04:41Feel free to move it wherever it works best for you.
04:44Now the problem is those pesky doors and the barriers.
04:48We haven't seen them yet, but before we even get there, we may as well turn them off.
04:53Open barrier 1, select sliding door left, and uncheck it in the Inspector.
05:00This deactivates the door. And the same with door right, we'll deactivate it.
05:07And in Barrier 2, we'll do the same with solid door.
05:13So now if we click play and head out, hitting my W key here, this time I
05:20don't have to jump.
05:21I can drive over my plank, and the doors are open, and I can go ahead and drive
05:28into my little nature area.
05:30Okay, now we're all set to go.
05:32So those were some of the obstacles you might face when setting up a
05:36first-person controller.
Collapse this transcript
4. Introducing Unity Scripting
Exploring Unity scripting
00:00Now that we've got a nice little environment to run around in, it's time to
00:04start making it interactive.
00:05Interactivity is, after all, what sets our games or real-time simulations apart
00:10from passive media such as movies.
00:12If we had to break them down, we could say there are two types of interactivity:
00:17physical, where an object might move or fall over when hit by a projectile; and
00:23logical, where we wouldn't be able to open a door if it was "locked."
00:28In the latter, there's no physical locking mechanism so we would need to keep
00:32track of its state, a sort of virtual lock, and then trigger the appropriate
00:36response when the player interacts with it.
00:39You might think that the former example, the projectile, would seem easier.
00:43But even there we're going to have to make decisions about what happens to both
00:47the projectile and its target on impact.
00:50To do this, we will need to write scripts to tell the Unity engine how to behave
00:55in any given situation throughout the game.
00:57Let's take a projectile, for example.
00:59The projectile would have a script that would tell it how to behave when it
01:03hit another object,
01:04while the locked door would have a script that kept track of its state so it
01:08would know what to do when the player interacted with it.
01:11In case you are feeling a bit spooked at this point, don't panic.
01:15Unlike traditional programming, which might have thousands of lines of code
01:18in one spot, in Unity you'll have separate scripts that are put on objects
01:23to do specific things.
01:25Some may only be a few lines long.
01:27So, what's involved with scripting?
01:29Well, to start, a language.
01:32Unity supports several languages:
01:34Python, Boo, C# and JavaScript.
01:39But we will only be using JavaScript since most of the examples in the Unity
01:42Help files and most of the tutorials are written using it.
01:46It's also a lot more forgiving.
01:48If you're already familiar with JavaScript from web programming, you're off to
01:52a good start.
01:53But be warned, Unity's version of JavaScript is slightly different than the
01:57JavaScript you may be used to.
02:00If you've never done any kind of scripting, don't worry.
02:03There are some syntax rules to follow, but unless we're using some obscure
02:06functions, it's usually pretty readable.
02:09Best of all, there are lots and lots of examples and sample code in both the
02:13Unity docs and from the Unity community.
02:16A large portion of the scripting concerns specific Unity game functionality and
02:20can be accessed from the Help menu > Scripting Reference.
02:25The Unity docs are also available online, which is usually a lot quicker way to
02:29find what you're looking for.
02:31For the basics of JavaScript in general, you will need to do a search on the
02:34web to find out about particular topics, get yourself a good reference book to
02:38keep handy, or both.
02:41Another worry you may have is about your math skills.
02:44Most of the scripting we will be doing will not go beyond high school math.
02:48We will be using code from other sources occasionally that gets in to the scary
02:52math category, but just like driving a car, you don't need to know how it works
02:57to make good use of it.
02:58The last thing we'll need is a script editor.
03:01Theoretically we could write all our script in a simple text application like
03:04Notepad and save the files with a JavaScript extension,
03:08but script editors have a lot of features that will make scripting much easier.
03:12Unity ships with a few different editors, but now the default is the Mono
03:16Develop, so that's what I'll be using.
03:19If you prefer something different, you can set it up as the default editor
03:23through Edit > Preferences > External tools.
03:28So let's go ahead now and jump right in.
Collapse this transcript
Using variables
00:00Since a good part of scripting is about keeping track of our logic, we will
00:04need a way to manage or store all those pesky bits of information. Enter the variable.
00:10Variables hold values--usually just one: the state of a door, the current
00:15color of your shirt, the number of rounds of ammunition you have left, just
00:18about anything.
00:20It might be a value that will change regularly or it maybe something that
00:24doesn't change but that different scripts will need access to.
00:27Let's try making a few just for practice.
00:31First though, let's create a new scene in our Unity Sampler Project. File >
00:36New Scene, and then we'll save the scene as, and we'll do it just in the default
00:41area right now.
00:42We'll save it as Scripting Tests.
00:46In the interest of trying to keep organized, let's also make a folder to hold
00:50our practice scripts.
00:52Right-click in the Project view, Create > Folder.
00:57And we'll name this folder Practice Scripts.
01:01And then we can go ahead and create our first script.
01:05With the new folder selected, right-click again, but this time
01:09select Javascript.
01:12That creates a new JavaScript named NewBehaviorScript.
01:16And it's immediately put into rename mode, so we are going to name
01:20ours VariablesTest.
01:22Notice there is no spaces in the name.
01:25When naming scripts, we need to avoid spaces.
01:28So you can separate your words with underscores or as you'll see most often in
01:32Unity, no space, but capitalize the first letter of each word.
01:38If you look in the Standard Assets folder and find a folder named Scripts,
01:42you'll see that this is the convention most used.
01:46You can still be descriptive with meaning and it's still easy to read.
01:49Back to our first script. Now that it's properly named, we can go ahead and open it.
01:55When it's selected, we can see its contents in the Inspector and we can open it
02:01from there by clicking the Open button.
02:04We can also open it just by double-clicking it in the Project view.
02:08Either way, it opens up on the Script Editor, in this case MonoDevelop.
02:13In it, we see something cryptic at the top, #pragma strict. We'll come back
02:19to him later.
02:20We see two empty functions.
02:23We'll delve into functions in the next video.
02:25Variables are usually declared at the top of the script, just beneath the
02:30pragma strict declaration.
02:32I am going to give myself a little bit room here by clicking Return a couple of times.
02:38We have to start by telling Unity it's a variable, and that is var, and we give a space.
02:48Then we add the name of our variable. We'll call this one health.
02:52And let's pause a second and talk about naming variables, because there is lots
02:57of rules and conventions to follow.
03:00Number one: variable names can't start with numbers or several specialty
03:05characters like exclamation points, backslashes, et cetera.
03:08There are a few exceptions, but better to keep to letters.
03:12Two: do not capitalize the first letter; we save that convention for
03:17naming functions.
03:19And three: no spaces are allowed in the variable name, so use underscores or
03:25better yet, capitalize the first letter of the rest of the words.
03:28You'll see why we want to use that method in just a few minutes.
03:32Then we need to tell it what type of variable it will be storing.
03:36So we'll add a colon.
03:38I am going to click space first and then add my colon.
03:42Then the type. In this case it's going to be an int, so I type in I-N-T. Then
03:49I'll finish my line with a semicolon.
03:52Before we go any further, let's talk about types.
03:55Typically, these are things like integers, and that's shorten to int as we
04:00just saw. Integers are whole numbers like 1, 50, 0, -25, and then we have
04:07floating-point numbers.
04:09Those are numbers with decimal points like 3.745, -0.62, things like that.
04:17And then strings of characters, these are always put between quotation marks.
04:23In case you like to cut and paste from your favorite text editor, they need to
04:26be the plain vanilla upright quotation marks, not the fancy slanted characters.
04:31So let's get back to types.
04:34Boolean is a two-state variable type.
04:36It either uses true or false, both lowercase. Checkboxes always use Booleans.
04:42And then Unity also has several types that are unique to it. They are
04:46always capitalized.
04:48You'll rarely ever see them initialized in the declaration.
04:51We'll hold off on those for a while.
04:54So what's initialized? We go ahead and assign a value to the variable at the
04:59same time we declare it.
05:01I have made code snippets available, so we can just copy and paste our code
05:05into the editor.
05:06I am going to go out to the desktop now and grab my first one, from my exercise
05:11files folder, Ch04/04-02, and there is my Code_Snippets.
05:18I have also made them available for everybody in the free exercise file.
05:23Let's go ahead and open this one now.
05:24So I have given us a whole bunch of examples of variables with different types.
05:30Let's go ahead and copy them and then we'll open up Unity again and the Script Editor.
05:37In the Script Editor, we are at the end of the health of type int line. Let's go
05:42ahead and hit Enter and then I am going to Ctrl+V to paste in all my new ones.
05:48Some of them already have values assigned to them and some of them don't. Most
05:54importantly, you can see each declaration has the semicolon at the end.
05:58This is really important.
05:59It tells us when the end of the declaration is.
06:02If you forget the semicolon, Unity will throw an error.
06:05So now that you've seen how to declare a variable, let's solve the pragma strict mystery.
06:11Remember I said that JavaScript is pretty forgiving?
06:15It turns out it's pretty good at figuring out what type your variable is, as
06:19long as you initialize it.
06:21If you are developing for mobile, you must declare your variable types. pragma
06:27strict forces a check to make sure that all variables are typed when the code is compiled.
06:32In Unity's JavaScript it won't necessarily throw an error, but it does force
06:37the type to be found.
06:39Let's save our little script and test it in our scene.
06:43To save it, I am going to go up to the icon on the toolbar and click Save.
06:48Now we can minimize the Script Editor and go back into Unity.
06:52We can see that the script is updated in the Inspector.
06:56Here comes the fun part.
06:58Let's add a cube to the scene.
07:00So GameObject > Create Other > Cube, and now we are going to drop our little
07:06script onto it and see what happens.
07:09Here is our script, VariablesTest, and we are going to click and drag and
07:14drop it on the Cube.
07:16Now when we select the Cube over in the Inspector, we can see our new
07:21script, VariablesTest.
07:24Our variables all show up in the Inspector.
07:26They look a little different though.
07:28The words are all capitalized and separated, except for the one with
07:32the underscore.
07:33Let's do a little test.
07:35Let's change the My Speed parameter to 25.5.
07:40So My Speed is 10, and we are going to change it to 25.5. Then we are going to
07:48open the script again by double- clicking on the script in the Project view and
07:53when we look at it, we see that the value for My Speed hasn't changed.
07:58It's still 10. We'll minimize this again.
08:02Let's go ahead and make a sphere and drop our same little script on it.
08:06So GameObject > Create Other > Sphere, and we can move it aside if we want.
08:13And we'll drop our same little VariablesTest script onto it by clicking and
08:18dragging. And this time on this one, we'll change its My Speed parameter to 15.
08:26If we go back and look at our Cube, it's still 25.5.
08:31This means we can reuse the script on any object we want, customizing
08:36the variables for each.
08:38If we click play and change the values during runtime--so I've got my Cube
08:44selected and I am going to change My Speed to 1 and click Enter--and then we
08:49stop, so we exit Play mode, note that the value reverts back.
08:56So changes made during runtime are not permanent; they always revert back to
09:01whatever we have them set to in Edit mode.
09:04So now there is just one other thing we ought to cover while we are talking about
09:08variables and that's how to keep them from showing up in the Inspector.
09:12Let's open our script again and once again I am going to double-click on it
09:16in the Project view.
09:18If we put "private" in front of the var, and save, we'll no longer see the
09:23someObject parameter.
09:25So in front of someObject, let's insert and say private, all lowercase, and
09:32save. Remember the icon in the upper- left here, Save the active document, or you
09:38can also use Ctrl+S. Then I'll minimize and get back into Unity. And now as soon
09:45as I come back, if I click on an object to bring the focus back to the editor,
09:50now we look over here and we have Some Setting and Some_Name, Some String, but
09:55we no longer have someObject.
09:57A few point releases ago, Unity changed the functionality so that not even other
10:03scripts could see private variables.
10:05This can cause problems in older scripts and tutorials.
10:08A better solution is to use internal.
10:12This way the parameter is only hidden from the Inspector, but still
10:15accessible from other scripts.
10:17So let's go back and change that.
10:19Once again, double-click on the VariablesTest script, and this time we are going
10:25to change private to internal.
10:29Save the script. We'll minimize again, activate the Cube, and once again there
10:36is no Some Other.
10:37So that works just as well.
10:40So let's do a quick recap on scripts and variables.
10:43When naming scripts, do not use any spaces;
10:46use underscore or caps.
10:47Let's open up the Script Editor again. And for variables, no spaces either, plus
10:55you must start the variable name with a lowercase letter.
10:58You may not start with numbers or several of the specialty characters.
11:02The syntax for declaring a variable is var some_Name : type and then semicolon.
11:11To declare and initialize, we add equals and the value and then the semicolon.
11:18Commonly used types are int, float, string, and boolean.
11:23Back in the Inspector, variable names are separated by spaces at each uppercase
11:30letter, values typed into the inspector overwrite values assigned in the script,
11:36values changed at runtime are not permanent, and finally, internal or private
11:42keeps the variable from showing up in the Inspector.
Collapse this transcript
Discovering functions
00:00Now that we have a way to keep track of our stuff, we need a way to make
00:04things happen.
00:05This is where functions come in.
00:07There's a few different types of functions. Some take care of user input and
00:11other events, and some, like the two empty functions we've seen preloaded in the
00:16script, take care of system stuff.
00:19And then there is the user-defined functions where we can design whatever we need.
00:23If you're new to scripting, let alone game engines, it can be pretty challenging
00:28to find what you're looking for.
00:29So this is a good time to visit the Scripting Reference for a
00:33little enlightenment.
00:34From the Help menu, we're going to select Scripting Reference, and we're going to
00:40search for "monobehavior" in the upper- left and click Enter. And it tells us it
00:47found one match, so we'll go ahead and click on it.
00:51Remember the default name assigned to the new script?
00:54It was New Behavior Script.
00:56That's because all JavaScripts derived from the MonoBehavior class.
01:01We don't really need to worry about classes, but an example of a class could
01:05be a bicycle class.
01:07Inside the class we'd have variables or parameters that help describe the
01:10bicycle: type of handle bars, number of wheels, color, and maybe functions,
01:17functions such as go forward, on crash, cause flat tire.
01:23If we had a class called vehicles, our bicycle class would inherit more generic
01:27properties and functions from it.
01:29That's sort of what the MonoBehavior class is.
01:32And if you've noticed up at the top, it inherits from another class as well.
01:37In the Overridable Functions section-- and we'll just scroll down here a little
01:41ways--you will find a lot of really useful functions.
01:46With their handy short descriptions, it's a good place to start looking for the
01:50basics, especially for interaction-type stuff.
01:54Let's look at the first two functions preloaded in the new script.
01:58The Update function is called every frame.
02:02This is where we put things that need to happen or be monitored every frame.
02:06It's one of the most commonly used functions.
02:09But since it's called every frame, it could cause things to happen at different
02:12rates depending on the speed of the machine the game is running on, or even at
02:16different times during the games since frame rates vary.
02:20Things that involve physics are usually called from FixedUpdate, so the
02:25resulting action will be about the same across platforms.
02:28While the Update functions are called throughout the game, the Start function
02:34is called only once: at the start of the game and before any of the Update functions.
02:39This is where we often initialize variables such as start times that need to be
02:43dynamically assigned.
02:44Remember that variable of type game object?
02:48We can't just type in the object's name to assign it to a value because its name
02:53is just one of its properties.
02:54But we can let the engine search for a game object with the name or some other
02:59property and assign the one it finds to that variable.
03:03That's another task we might think to put in the start function.
03:07Here's the catch though:
03:08the start function is only called when the object is activated.
03:12So the start functions in the scripts on things like projectiles aren't even
03:16called when the game starts up, but when the objects are instantiated or
03:21created during the game.
03:23To make sure objects can be found whether they are activated or not, we use
03:27the Awake function.
03:29It's always called before the Start function but after all of the objects
03:33have been initialized.
03:34Getting back to the docs, we can see that most of the event-triggered functions
03:39start with On. We'll be revisiting several of these throughout the course.
03:43We'll take a look at syntax in the next video, then start making things happen.
03:48But first, let's do a quick review.
03:51Functions are where we make things happen.
03:53They can be system type called on startup, like the Start function, or
03:58every frame, like Update.
04:00A list of functions, including the event-driven function like OnCollisionEnter,
04:06can be found in the Scripting Reference by searching MonoBehavior.
Collapse this transcript
Using syntax, punctuation, and the console
00:00So we have had a general look at some of the overall characteristics of a
00:03few useful functions,
00:05and we know how to declare and assign values to standard variables.
00:09Now that you've been introduced to the concepts, it's time to learn about
00:13syntax, punctuation, and tracking down errors, because computers are funny about
00:18wanting things exactly correct.
00:20In the last video, I mentioned something about Unity throwing an error if you
00:25forgot to add the semicolon to the end of the variable declaration lines.
00:29Tracking down mysterious errors is a large part of scripting, especially
00:34if you're new to it,
00:35but Unity's compiler is pretty good about reporting many different mistakes. Let's try a few.
00:42As you can see, we're in the Scripting Tests scene.
00:45Let's go ahead and double-click the VariablesTest script to open it in the Script Editor.
00:49So let's delete a semicolon to start.
00:52This is an easy thing to forget to add if you're cutting and pasting code.
00:56I'll try this one right here. And delete. And whenever you make changes in your
01:01script, you need to remember to click over and save.
01:06Now if we minimize the Script Editor, an error appears in the Status line at the bottom.
01:14Let's click on that, and that opens up the Console. The Console is where we
01:19will be seeing errors reported, but we can also send messages out to be printed there.
01:25The error message tells us which script has the error--VariablesTest.js--what row
01:31and what column it's at, and if we're lucky like this time a message that's
01:37useful in telling us what the problem is.
01:39Here's the nice bit.
01:41If we double-click the error message in the Console, the Script Editor opens up
01:47to the exact line, and now we can fix it.
01:50We'll add our semicolon back in and save.
01:57Let's see what else can go wrong.
01:59Let's try a capital T for true.
02:01So I'm going to click, turn that into a capital T. Notice the color changed.
02:08And let's not forget to save, minimize the Script Editor, and now our error message
02:16tells us that there is an unknown identifier called True.
02:21Once again, it tells us where it is, so we can double-click.
02:24It opens up the Script Editor, and we can just set that back to a lowercase t, and save.
02:33Well, what happens if string is not capitalized?
02:38Let's go to this variable right here,
02:40this type, and we'll make this guy a lowercase s, save the script, and let's minimize.
02:49This time the name string does not denote a valid type.
02:54So this time it doesn't even have a clue.
02:56So we are not always going to get Unity telling us what was wrong, but at least
03:01it will take us to where the problem is.
03:03So we'll double-click on it, and this time it's up to us to figure out what it
03:07is, but fortunately, in this one we know.
03:12You may have picked up something else here.
03:14Let me move my cursor away to close the tooltips.
03:17So you may have picked up on something else here.
03:20The words are color coded.
03:23When we change the S to a lowercase s, the word String went from blue to black.
03:29And all of our variable names that we made up are black. It turns out reserved
03:35words are shown in blue.
03:38This is great for people like me who can't type or spell.
03:41If the color is wrong, double-check the spelling.
03:44Okay, let's see what happens if we forgot to close the string with the second
03:49set of quotation marks.
03:50And we can go up to either of our String examples to do that. Highlight, delete. Once
03:57again we save and minimize.
04:02This time the error is different.
04:04It was expecting quotation marks, but it found a carriage return instead.
04:08Let's double-click to open our Script Editor again, and we'll go ahead and fix
04:13this guy, by putting our quotation mark back. And never forget, you need to save.
04:23So, what about spaces?
04:25Let's put a few extra ones in and then maybe delete one.
04:29So I'm going to go over here and maybe I'll delete this space right here and
04:34maybe an extra one here, and let's save and see if we get any errors.
04:38Save, minimize, and no, no errors. So guess what?
04:46Spaces aren't crucial.
04:49Let's open the VariablesTest again or bring up the editor. And I do want to
04:56show you one thing here.
04:57If we had two spaces in this string that wouldn't be the same as the string with one space.
05:06The reason you will see script editors using that ugly sort of Courier font is
05:10so that you can clearly see if there was a space or not.
05:14This is really important.
05:16Spaces and punctuation do count in strings. Okay.
05:20To recap, the Console will report errors, identify their location in the script,
05:26and occasionally make suggestions about correcting them.
05:29In the Script Editor, reserved words are shown in blue and finally, spaces are
05:35not crucial unless they're part of the string.
Collapse this transcript
Looking at function syntax
00:01Let's go ahead and look at function syntax next.
00:04Opening our VariablesTest script by double-clicking on it, we can check out the
00:10two functions that are already there.
00:12The word "function" tells us what's coming up, and then we have the name, and opened
00:17and closed parentheses.
00:18Occasionally, you will want to pass an argument into a function.
00:23In the case of an object that just got hit by a projectile, we might need to
00:27know if it was a bullet from a machine gun or a rocket from a rocket launcher.
00:32So, a function that calculates damage knows how much to add.
00:35Inside the parentheses is where we pass that kind of a variable.
00:39After the parentheses, we see an open curly bracket and then further down, a
00:45closed curly bracket.
00:47Everything inside them belongs to that function.
00:50If you click right behind the opening one, you can see that the closing one
00:56will be highlighted.
00:57Deleting one of those generates a bunch of errors.
01:00Let's try it and see.
01:01I am going to highlight and delete this one. And of course I will save, and then we
01:08will minimize and see what the Console tells us.
01:12I'll click it to open, and now it's giving us an Unexpected token message.
01:17So, double-click on it to bring our script back up, and we can put it right
01:22back. Open curly bracket.
01:25Because of the errors that can cause, when we start writing new functions, we
01:30usually create it empty, but fully correct to start with, just like the Start
01:35and Update functions.
01:36Let's go ahead and try one of our own.
01:39Down below the function Update, I am going to click and do a couple of line
01:44feeds with enter, and then I will type "function." And notice that in a Document
01:52Outline, as soon as we start typing, it goes blank; as soon as it's correct again,
01:58that's going to come back.
01:59So a function--and I am going to name this function JustATest. And remember, the
02:05first letter of your function name needs to be capitalized.
02:09After the name of the function, I am going to give myself a space, although
02:14that's not totally necessary, and I am going to make my opened and closed
02:18parentheses, my open curly bracket, couple of enters for line feeds, and I will
02:27go ahead and put closed curly bracket.
02:29So, let's go ahead and click Save and minimize and make sure that the Console
02:34is happy. It is; there's no errors reported.
02:38So we'll go back into that, and now we are going to try something different.
02:42So far, we have seen a starting curly bracket up on the same top line.
02:47This time I am going to click Enter and drop it down.
02:51Now let's save and see if that's still okay.
02:55Click Save, minimize, check out our Console, give it a second to refresh if it
03:00needs to, and guess what? That still good.
03:03We'll open this again.
03:04So believe it or not, this is a serious issue.
03:08It's correct either way, but many companies will have strict conventions for
03:13using one way or the other,
03:14even to the point of fines. The issue is readability and continuity of style,
03:19so don't even try to win an argument about why your way is better.
03:22But you'll see it both ways.
03:25To recap, the syntax for functions is, function, the function name, open
03:31and closed parentheses, where the argument is optional, and open and closing curly brackets.
03:38And finally, remember the position of the curly brackets can vary.
Collapse this transcript
Printing to the console
00:00Okay, I think it's time to make something happen.
00:03We are going to add a command to print something out to the Console.
00:07So let's open our VariablesTest script again, and we can double-click it from the
00:12Project view or we could open it from the Inspector.
00:17In the Start function between the curly brackets, give yourself a couple of line
00:21feeds, and this is just for cosmetic purposes.
00:24And now I am going to go out to my Snippets file and copy the first line
00:30Exercise Files/Ch04/04-06, and I am going to open the Code_Snippets.
00:39And here is my first line, so I'll copy it, and we'll pop back into the Script Editor.
00:49Now I can paste it inside my Start function.
00:52This line prints a message to the Unity Console. Let's go ahead and try it.
00:57Save the script and we'll minimize. And we've already got our script on two
01:05objects, so I am going to click play and watch down at the bottom.
01:12On our Status line, we can see the message.
01:15If we click it, we can open the Console, and we see it twice.
01:20That's because we have the same script on both the Cube and the Sphere.
01:26Let's close this for a minute, get back to our Script Editor, and we are going to
01:32look at another way to do this. That's the proper way to print to the Console.
01:36But you'll also see people using this method.
01:39Print, parentheses, and I am going to write "ditto" in here, close my quotation
01:50mark, close the parenthesis, end the line.
01:55So you'll also see this used.
01:57It doesn't follow the usual rules of function names being capitalized, and it
02:02doesn't turn blue like a reserved word should.
02:05But remember our friend Mono?
02:07Well, that's the framework Unity is built on, and that's where this guy comes from.
02:12Let's try it and see if it works.
02:14Save, minimize, and let's get out of play mode and start again, and there we can see ditto.
02:28If we open the Console, we can see that it worked for both objects.
02:33Here is our Debug Log and here is our print.
02:37Here is the other Debut Log and here is the other print.
02:40Now let's go ahead and put a message in the Update function.
02:43So let's close this. We can turn this off for now, bring up our Script Editor again.
02:50Now let's put a message in the Update function.
02:53We can just copy this guy, paste him in the Update function and instead of
03:01Start, we'll go ahead and tell ourselves that it's Update. But we need to
03:07remember that Update is called every frame.
03:10So it won't be surprising that after we save and click Play, then open the Console,
03:22that that message is repeated over and over.
03:25Okay, that's probably enough of that.
03:27But rather than delete it, let's try something new.
03:30Let's comment it out.
03:33So we'll turn off Play mode. We'll go back to our VariablesTest.
03:39The two forward slashes tell the engine to ignore everything after them on that
03:43line--in other words, all the green stuff.
03:47If you save and run, you can see that the message from the Update function will
03:51no longer be printed, so let's try that.
03:53Save, minimize, and we'll leave the Console open this time, and we'll click Run.
04:02And there we go. We still have our two print message from the Start function,
04:07but nothing from Update.
04:08While this works great for temporarily hiding code, its main use is to enable
04:14you to make comments to your code to remind you, or anyone else who might see
04:18your code, what it does.
04:20So let's add a real comment after one of those variable declarations.
04:23I am going to go out to my Code_Snippets and find a nice handy one. //test
04:30string to see how they work,
04:32that's a good one. So copy it, get back to our Script Editor, and after one of
04:41our strings, I am going to paste it in.
04:44I won't be adding comments onscreen to the code very often because of the
04:49limited resolution, but the scripts that are included in the exercise files will
04:54have plenty for you.
04:55The next thing to try is a message in the JustATest function.
05:00So let's go out and cut one of those and paste it in.
05:04This is a good one, print message from the JustATest function.
05:09So I'll copy and I am going to paste it into here.
05:16When we save, minimize, stop, and then click Play again--by the way notice we
05:25have Clear on play here. We could also clear it before we start.
05:29We'll click Play. The Start message has printed again, but not the JustATest message.
05:37It turns out we need to call the function for it to be run.
05:43Let's call it from the Start function.
05:45So we'll exit, get back to our Script Editor, and here is how you call a function.
05:51This is the one we want to call, so we can just copy its name. And we need
05:57the two parentheses.
06:00So we'll copy and in the Start function, I am going to make myself a little bit
06:05more space and paste.
06:08We are missing one thing, the semicolon.
06:13Now we can save, minimize, Clear, and click play.
06:24And now there it is, Message from the JustATest function.
06:28And finally, as a little review of variables and bit more fun, let's use the
06:34variable called some_Name.
06:37So we'll go back into our Script Editor, and we'll change our message from JustATest.
06:43I am going to pick up my last bit of code here, copy it, and let's just exchange
06:53the original message in JustATest for the new one.
06:57Strings can be added or concatenated together with a plus sign.
07:03Let's go ahead and save our script and see what happens.
07:09Minimize. We'll start over again. And now we see our new message: Hi, Fred, glad
07:18to have you aboard.
07:19Fred, if you'll remember, was the value for our some_Name string.
07:26Back in the Inspector, we can go one step further.
07:30Let's turn off play mode and on the Cube, let's name this guy to somebody else.
07:40We'll call this one Alice.
07:45And over on the Sphere, let's change it to, how about Floyd?
07:54Now when we click Play, if we open the Console, you'll see that we don't have Fred anymore.
08:04One of the scripts is saying hi to Alice and the other one is saying hi to Floyd.
08:09So the same script is used on both objects, but the variable, some_Name, loaded
08:15in the Inspector is unique to each and overwrites the name we initialize the variable with.
08:21Test messages are useful for tracking what our program does, especially when it
08:26isn't doing what we expect.
Collapse this transcript
Exploring rotation and time functions
00:00You are probably ready to see a bit more action by now.
00:04Transforms, move, rotate and scale are the basis of a lot of game action,
00:09so we'll start there.
00:11Since we'll finally be interacting with the Game window, make sure you're
00:14already in the 2 x 3 layout.
00:16Now we'll go ahead and set the Cube at 0, 0, 0.
00:22So we'll select the Cube and in the Inspector, click, type 0, click, type 0, and one more 0.
00:34Now let's focus in on the Cube, and we can double-click it to bring it into the
00:38view. And then we need to get the Main Camera looking at it by selecting the
00:43Camera and from the GameObject view clicking Align With View.
00:49With only ambient lighting, it's pretty hard to see our cube,
00:53so let's go ahead and add a directional light while we're at it: GameObject >
00:58Create Other > Directional Light.
01:03We can rotate the light until our cube shows up nicely in the Game view.
01:12Now let's make a new JavaScript.
01:14Remember to select the Practice Scripts folder first, then right-click, Create > Javascript.
01:24And we'll name it TransformTest and click Enter.
01:35Open it by double-clicking. And in the Update function, we are going to cut and
01:41paste a little bit more code.
01:43So I am going to go out to find my Code_Snippets, Ch04/04-07/ 04-07Code_Snippets.
01:54I am going to copy and paste my first line and then go back to my Script Editor,
02:03and I am going to paste it into my Update function.
02:07If you want, you can give it a little more space. And usually we end up indenting
02:15everything inside a function,
02:17so I have just tapped that over one.
02:20Let's go ahead and hit Save and back in the Unity Editor, we'll go ahead and
02:27drag our TransformTest script onto the Cube.
02:31When we click play, the cube rotates.
02:37So we might want to change the speed.
02:40If we hard code it in the script, we'll see the change after we save the script
02:45and return focus to the editor. Let's try that.
02:48I am going to stop, and this time let's set it to, let's try 0.6.
02:56Save the script, minimize, click play again, and this time the cube is rotating, well,
03:05about twice as fast.
03:06Usually though, we are going to use variables that can be changed in the
03:12Inspector when we want to be changing values.
03:15So let's do that this time.
03:17Stop. We'll get back into the editor. And now I am going to go over and pick up
03:25my next bit of code.
03:27I want this one. Copy, and I am going to right-click and copy.
03:33Then we'll go back to the Script Editor. And let's give ourselves a little bit of
03:38space here using Enter, and we'll paste our new variable here. var rotationSpeed
03:46of type float, and we are initializing it to 20.
03:50Now because we have a variable, we are going to copy that variable name,
03:55copy--that's a right-click--and we are going to paste it in the Y position
04:03where the 0.6 used to be.
04:07Let's save our script, minimize, and click Play.
04:12The cube is spinning pretty fast.
04:16If we click on it in the Hierarchy view, we can see the value we first gave it: 20.
04:22Let's go ahead and exit Play mode.
04:25So this works fine except for one thing.
04:28The Update function is called every frame. That means if your machine is faster
04:33than mine, your cube will be spinning faster.
04:37Now, it might seem logical to move the code into the fixed update, but Unity
04:41has a better solution.
04:43Let's get back into the Script Editor and have a look.
04:48Let's go get our next bit of code, and we want this one right here.
04:54And we'll right-click, copy, and we are going to replace the original transform
05:01line with a new one, using Ctrl+V. Notice we are now multiplying our
05:08rotationSpeed by Time.deltaTime.
05:13By multiplying by Time.deltaTime, Unity ensures that now the objects with this
05:18script will be rotating the specified amount per second.
05:24Let's make the change, save, minimize, and we'll click Play.
05:30Now with the same rotationSpeed it's rotating much slower.
05:35In case you are wondering what's happening, remember, before we were rotating
05:40every frame, and if we look at the Stats in the Game window, it's about 70 frames per second.
05:48So before, our rotationSpeed of 20 was happening every frame;
05:54now it's happening every second.
05:57Let's go ahead and exit Play mode.
06:00So why use Time.deltaTime instead of fixed update?
06:04Chances are the frame rate will be better than the fixed update, which must be
06:09less than the fastest rate,
06:11so the action will be smoother.
06:13If you happen to have changed your speed during runtime, as soon as you stop,
06:18it will revert back.
06:20That's kind of a double-edged sword.
06:22You have to remember the settings you want to keep, but at least you won't mess
06:26up something and not remember what it was before you tweaked it.
06:29Let's try one more test while we're here.
06:32So far, we've been able to change the value of our variable during runtime
06:36through the Inspector and see the changes.
06:39That's because the rotation code is in the Update function.
06:43It gets read every frame.
06:45Let's see what happens if we make the variable internal and change the value
06:50of script at runtime.
06:52So we'll go back to our script and we'll make our rotationSpeed an internal
06:59variable. Let's go ahead and hit Save and click play. The speed is reverted to
07:12the value we originally assigned in the script.
07:15If we go back to the Script Editor and change the speed here, save, and go back
07:25to the editor again, there is no change in the speed in the viewport.
07:31That makes perfect sense because the variables are declared and initialized when
07:35the game is started.
07:37Any changes made to them in the Start function are added afterwards.
07:41Those two procedures happen only once, on startup.
07:44So any time we change values assigned to variables or assigned in the Start
07:49function and not exposed in the Inspector, we will need to restart Play mode
07:55to see the changes.
07:57Okay that's a lot of things to remember, so let's review.
08:02Transform.rotate rotates an object; Time.deltaTime converts the code to per
08:09second instead of per frame; and changing values in the Start function during
08:16runtime will only show the change when the scene has been restarted.
Collapse this transcript
Scripting basic functions
00:00Let's see if we can get the cube moving the same way we got it rotating.
00:05First though let's deactivate the Sphere over in the Inspector.
00:09So we're going to select this Sphere. We can't see him in the viewport, but he
00:13is still there, and in the Inspector we're going to uncheck the Activate button.
00:20Now let's go ahead and open the TransformTest script again. And we're
00:25double-clicking on it as usual.
00:28To start, we're going to comment out the rotation line with our forward slashes,
00:36and then I'm going to go out and grab a new bit of code from the exercise files:
00:40Ch04/04-08/Code_Snippets.
00:48And we're going to start with this one. Right-click, Copy, and then I'm going
00:58to tab back to the Scripting Editor. And I want to add this line of code just
01:03below the first one.
01:04I'll go ahead and Tab over first, paste, Ctrl+V. And we've got
01:10transform.Translate(speed * Time. deltaTime, and then the usual zeros.
01:18So it's pretty much like our first line.
01:21We've got Translate instead of Rotate, and we've also got a different variable.
01:26So let's pop over and get that one as well.
01:28Here is our speed variable, right-click, Copy, and we'll tab back over to the
01:38Script Editor, and we'll add this guy up at the top, or near the top, and paste.
01:45We can go ahead and click Save now, minimize, and when we click Play, the cube
01:53will probably scoot out of the view pretty quickly. And we'll try that. And there it goes.
01:59So we'll exit Play mode and in the Inspector we'll reduce the speed, and we have
02:06to select the cube to see the TransformTest script in here, in the Inspector.
02:12And so we are going to reduce the speed.
02:14I'm going to reduce it to about 5.
02:17And then we also should use the middle- mouse roller to zoom back in the viewport
02:24so we'll have a better chance of seeing it when it starts moving.
02:28Now we can click Play again and it moves slowly off.
02:35Now in case you are wondering what would happen with both lines of code active,
02:41we better check that out.
02:43So let's back into the Script Editor and uncomment or remove our forward slashes.
02:51We can save again. Back in the Unity editor if you click on the cube,
02:57over in the Inspector we don't see the Rotation Speed.
03:01If you remember, we left it as an internal variable. It looks like we'll have to go
03:06back out and fix that.
03:08I'm going to tab over to the Script Editor and remove internal. Delete
03:17and remember to save.
03:19Now we can go back to the Unity Editor and as soon as the focus is changed, our
03:24Rotation Speed variable turns up again.
03:28And I want to set that to about 50.
03:32Now let's click play and see what happens. We should have both the rotation and
03:37the transform happening.
03:38And sure enough, our cube is rotating and moving at the same time.
03:46Now if you're a little bit unsure of what's happening here, there's two
03:51things you need to do.
03:52First make sure the cube is selected, which it is. We can see our Transform
03:57gizmo, but here is the trick. Instead of Global we want to see Local.
04:06With Local turned on, now you can see wherever the X axis is pointed,
04:12that's where our cube is moving.
04:15Now we can see that the Translate function moves an object along the
04:21object's local axis.
04:24Wherever the cube is rotated to face, the cube moves forward in that direction.
04:30Let's go ahead and exit Play mode. So far so good.
04:37We can animate an object to move or rotate using transform.Rotate and
04:42transform.Translate.
04:45And in case something about those looks familiar, yes, they are functions and they
04:50belong to transform.
04:52But what if we just wanted to put an object in a different location, not animate it?
04:57For that we will need to change the object's transform parameters.
05:04Take a look at the cube's Transform values in the Inspector as it animates.
05:08So we'll turn it on for a second again. We can see the object's Transform is
05:13moving in the Inspector.
05:16Let's exit Play mode again.
05:17All the Transform values are variables: Position, Rotation, and Scale.
05:24The parameter names are capitalized in the Inspector, just like our own variable
05:28names were, but since they're really just variables, they won't be capitalized
05:33when we assign our own values to them.
05:36Let's have our own script give us the position of the cube this time.
05:41So let's open up the Script Editor again.
05:44This time we'll comment out both of the transform lines. And here is something
05:50that's a little new:
05:52if we right-click, in the right- click menu we can Toggle Line Comments.
05:57That way we get them both at once.
06:01Now in the Update function, let's add another bit of code that we'll go out and grab.
06:08This time I'm going to copy, tab back into my Script Editor, and paste, and this
06:18time we're going to have it print (transform.Position).
06:24So now we can go ahead and save, get back into the Editor,
06:29and now when we click play, if we move the cube around, we should be able to see
06:37its position being reported in the status line. And sure enough, there it is.
06:46The position is reported as a three-part variable, a Vector3 type.
06:52We'll go about setting position in the next video.
06:55So to recap, transform.Translate moves an object using its local coordinate system.
07:02Vector3 type contains three values-- x, y,z--and transform.Position will report
07:09the location of an object.
Collapse this transcript
Combining transforms
00:00In the last video we found that translate.position was a three-part variable, a vector3 type.
00:08So how do we assign a value to a particular transform?
00:11Easy, transform.position.x. This is called dot notation.
00:18It's a way of referencing where functions and variable definitions come from.
00:22So transform has a variable called position and position in turn has a
00:28variable called x. If we look up transform in the scripting reference--Help >
00:35Scripting Reference--and we choose Transform, we can see both the functions
00:45and variables we've been using. Here is position.
00:51Under Functions we can find Translate and Rotate.
00:56Also note the first line: "Every object in a scene has a Transform."
01:02This means we can put our script on any object and get or set its transforms, or
01:09if we wanted, use the Rotate or Translate functions on it.
01:14Let's test the position.
01:16Let's get back into Unity, open our TransformTest script, and I'm going to go out
01:24to the exercise files again to copy our next bit of code.
01:27In exercise files, Ch04/04-09/Code _Snippets, and let's go ahead and take
01:38the first two lines.
01:41Right-click and copy and tab back to our Script Editor, and we want to add these
01:48guys in the start function.
01:50I'm going to press Enter a couple of times to give myself more space and then
01:55Ctrl+V to paste them in.
01:57Since they are already defined by Unity, we don't need to tell Unity that
02:01they are variables or even what type they are.
02:04So now if we save the script and head back to the editor and then hit play, we
02:11will eventually be able to find the cube off of its new location.
02:16And there it goes. We might have to look for it, but it's definitely moved.
02:24If we double-click, we can find it.
02:28As soon as we exit Play mode, it's going to return to where it originally was.
02:33I'll double-click again to locate it in the Scene view.
02:37So this is worth noting.
02:38As soon as we exit Play mode, it reverts back to the original location.
02:44So just like translating, transforming an object with position during runtime is not permanent.
02:52Let's try one more experiment while we're here.
02:55We still haven't actually interacted with the cube in the Game view.
02:58Traditionally, we have interacted with objects in our games using the mouse for
03:03part of the navigation, and for firing weapons--
03:06well, along with the keyboard.
03:08With today's move towards mobile where there is no mouse or keyboard, it's more
03:13likely we will be using touch to trigger events for interaction.
03:16Since you may not have a touch-enabled monitor, we'll do a simple test using the
03:21mouse button and the OnMouseDown function.
03:25So back in the Script Editor, let's go ahead and comment out all of the code in
03:31our Start and Update functions, and then we'll head over to the snippets and
03:40grab the entire function here.
03:44Highlight, right-click to Copy, and then we'll tab back to our Script Editor.
03:53And this one we're going to add underneath the Update function.
03:57So Ctrl+Paste, and we have our new function.
04:01This one, OnMouseDown, we saw briefly when we were looking at the
04:05original MonoBehaviour.
04:07We've put in it transform.position.z = 1;
04:11and transfor.position.x = 5, so when we click on our mouse button, that's where
04:19the cube will be moved.
04:21Let's go ahead and save our script, tab back to the Unity Editor, and give it a try.
04:29I'm going to go ahead and zoom back first though, on the off chance that I might
04:34find it after it's moved.
04:36Now we can go ahead and click Play.
04:39This won't move until we actually click on the cube in the Game window and as
04:44soon as I click, it's transformed off to its new location.
04:49Let's go ahead and exit Play mode.
04:52In Unity, MouseDown is set to work off of a left-mouse click.
04:56If we created variables for x and z, then you could change their values in the
05:02inspector, and each time you click the cube, it would move to the new location.
05:08So to recap, dot notation allows us to access functions and parameters; we can
05:14set location by assigning a value to an object's position parameter; and we
05:19were introduced to the OnMouseDown function as a means to interact with an
05:24object in runtime.
Collapse this transcript
Setting transforms
00:00So we've seen a little about how to transform objects, both by setting their
00:04transforms and animating them.
00:07But even using the OnMouseDown function, we aren't really doing anything game-ish yet.
00:12So what's missing?
00:14What makes a game different than, say, an architectural walkthrough?
00:18The answer is conditionals.
00:20If the door is locked, rattle it; else it is unlocked, so open it.
00:26If the monster's health is less than 25, kill it;
00:30else reduce its health by 30.
00:33The if statement is the most important of the conditionals.
00:37We might be evaluating an amount like health or strength, or we might be
00:41evaluating a state like locked or unlocked.
00:45Let's try controlling the rotation of our cube with a MouseDown.
00:49So let's create a new JavaScript and then we'll name it RotationController.
00:54Remember to highlight your Practice Scripts folder first, right-click, Create >
01:01JavaScript. And we're going to name this guy RotationController.
01:14We'll go ahead and open it in the Script Editor, and then we're going to need to
01:20create a variable to keep track of its state, its rotation state.
01:26I'm going to head out to the snippets folder and pick up the new bit of code.
01:29Ch04/04-10, and here is our Code_Snippet.
01:41So this is the one we're going to want right here.
01:44Highlight, right-click, Copy, and then we'll tab back over to the Script Editor.
01:54And this is a var, a variable, so I'm going to give it a little more room up
01:59here by clicking Enter. And I'll paste it into that area using Ctrl+V. Since it'll
02:05either be rotating or not, we're going to use a Boolean type for the variable.
02:11It only takes a byte's worth of memory for storage, as opposed to an integer
02:15that takes a lot more.
02:16And then we're going to need a variable for speed, so I'm going to tab out and
02:23collect that one as well.
02:26Highlight, right-click, Copy, and then we'll tab back to our Script Editor, and
02:34we'll add it just underneath the first one. Paste.
02:38We already have one named rotationSpeed, but since it's on a different script, we can reuse it.
02:45It's sort of like two guys named Bob Smith: same name but different people.
02:50If we do ever need to refer to them in the same script, we just specify where
02:54they came from: Maple Street.Bob Smith and Shady Lane.Bob Smith, where the
03:01scripts would be Maple Street and Shady Lane.
03:04Now in the Update function, we'll need to tell it rotate the object that the script is on,
03:10but only if the rotation state is true. Let's go out and grab that bit of code.
03:16This is the one we want right here.
03:20Right-click and Copy, tab over, and since that's the Update function, I can just
03:28paste it on top of the one that's already there, with Ctrl+V. So now we're seeing
03:34the if statement for the first time.
03:36If is the reserved word, and after that we have the clause that gets evaluated to
03:42see if it's true or false.
03:44Inside the curly brackets are the instructions for what to do if the condition is met.
03:50Now there's something new inside the conditional clause.
03:53A single equals sign is the assignment operator, but the double equals sign is
04:00the equivalency test.
04:02That's the one we use in the conditional, and we can see it right here.
04:07There are other tests we can do, depending on what we're checking.
04:11We could use not equals, where we use an exclamation point next to the equals
04:15sign, we can use less than, greater than, less than and equal to, or greater than and equal to.
04:25All these return true or false results when the code is evaluated.
04:30Now we need a way to set the rotation flag.
04:32A flag is just another name for a variable. So out in the snippets file we'll
04:38select our next bit of code, and as you can see, it's an OnMouseDown function, so
04:48let's right-click and Copy, tab back over to the Script Editor, and we'll add it
04:55beneath the Update function.
04:58Order isn't really important in the scripts, but conventionally we always add
05:02the rest of our functions below the Start and Update functions.
05:07Let's go ahead and save the script and head back to the Editor.
05:10Our cube already has all of the earlier scripts on it, so let's delete it and
05:15make a new one for our new script.
05:17First I'll double-click on it to bring it into focus.
05:20Then I can right-click and chose Delete.
05:25Now from GameObject > Create Other, I'll add a new cube, and it's added in the same spot.
05:34This one is nice and clean though.
05:36So let's add our new script to it and then we'll click play and test it.
05:40RotationController, and you can either drag it onto the cube in the hierarchy or
05:46you can drag it onto the cube in the scene view.
05:49Either way it turns up here in the inspector.
05:53So let's click play and see if it works.
05:55I click play and it's rotating and according to our script, if it's rotating and
06:03we have a MouseDown, it should stop.
06:06And sure enough I click and it stops.
06:09If I click again, it starts up again.
06:14So let's go back into the Script Editor and really look at our code.
06:18I'll exit Play mode first.
06:20Right now the code in our OnMouseDown function is pretty easy to read: if
06:25rotationState equals or is equivalent to true, set rotationState to false; else
06:33if rotationState is false, set rotationState to true.
06:38We've also got a print statement in there so you could watch the state as it
06:41changes, down in the status line.
06:43But this is kind of a long-hand way of writing this.
06:47While this is considered good practice, you'll also see it in its more
06:50abbreviated form. And let's sort of look through it and see what we could do to it.
06:55First off, rotationState is a Boolean;
06:59it's either true or false.
07:01So we could get rid of this part.
07:07And because we only have one thing to do, if it does evaluate to true, we
07:13could get rid of the curly brackets, and even put it onto the same line. Both curly brackets.
07:23And because there is only two possibilities--it's either going to be true or
07:27it's not--we don't even need the second if.
07:33And what's more, it's only doing one thing so we could get rid of the
07:37curly brackets as well.
07:39So this function, as it stands now, if we click play and tried it out, would work
07:45just as well as the original.
07:48But to keep things more readable, we're going to go ahead and use Ctrl+Z to bring
07:54our OnMouseDown function back to its original state. And there we go.
08:02So save and then we can tab back to Unity.
08:08Okay, that's a lot to think about, so let's have a quick review.
08:12The if statement evaluates the contents of its conditional to see if it returns
08:17true or false; if true it will do whatever instructions follow it.
08:22If there is more than one instruction, they must be inside curly brackets.
08:26If the condition evaluates to false, we need to use an else to tell it what
08:31instructions to carry out in that case.
Collapse this transcript
Using conditionals to create gameplay
00:00Let's carry on with conditionals.
00:02It turns out we can get pretty selective about what goes on inside our conditionals.
00:07Open the RotationController script again, and we'll double-click it to bring it
00:12up in the Script Editor. And we are going to start by decreasing the speed each
00:17time the cube is clicked.
00:19We'll do this in the OnMouseDown function by doing a little bit of math.
00:23In the OnMouseDown function I am going to comment out the print statement, and
00:29underneath that I am going to go ahead and reduce the rotation speed.
00:37I can right-click and copy my variable and then down inside the OnMouseDown, I'll
00:44paste it, Ctrl+V. And I want to set rotationSpeed equal to rotationSpeed, and I'll
00:54paste it again, -.5, or we could put 0.5. Either way works.
01:02And we need to use a semicolon to finish the line.
01:08Notice that we don't have to declare its type again.
01:11In fact, if we tried, we'd get an error.
01:15Variables only get declared once in a script.
01:19And here is something else you'll see too: you can abbreviate this one and make
01:23it 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:40Ctrl+Z to get back to our original version.
01:45Let's go ahead and click Save and we'll switch back to the Unity Editor and give it a try.
01:51We'll click play and each time we click our cube, the rotation speed will slow
01:58down so that the next time I click and start it up again, it's slower.
02:03Click to stop, click again to start, and I'll just click it a few times here
02:10and you can see each time it starts up again, it gets slower and slower.
02:19And we'll exit Play mode.
02:20So once the speed gets below about five, the rotation hardly shows.
02:26So let's go ahead and turn it off.
02:29Here is how to add the additional condition.
02:32So we'll go back into our Script Editor and in our condition rotationState =
02:38true, we also want to stipulate that the rotationSpeed has to be greater than
02:44five, and here is how that's done.
02:47Two ampersands and then we want to make sure that rotationSpeed--and I'll
02:56double-click and Copy and paste it into here with Ctrl+V. So we are going to
03:03check that the rotationState is true and--this is our ampersand, our double
03:09ampersand--the rotationSpeed is greater than five.
03:16And now we can save the script, go back into Unity, and click Play. And this time
03:23I'll click the cube several times quickly, and at some point it quits rotating
03:35at all, and I am clicking several times now. So, that works.
03:39Let's exit Play mode.
03:42Next let's reward the player for being tenacious.
03:45If the speed gets down below zero, we'll reset it to the starting speed.
03:51The only problem is, what if the speed we set in the script was overridden in the Inspector?
03:57If we look in the cube, our rotation speed starts at 20, but maybe someone came
04:03in and changed it to 10.
04:07So we are going to need a way to make sure that we get the latest value for the rotationSpeed.
04:13By the time the Start function has been called though, the override number
04:17will have been read in.
04:19So we can grab it from the start function and store it then.
04:23Let's open our script again, and now we are going to need a new variable.
04:28Let's call this one startSpeed, of type float.
04:32So var startSpeed and that is of type float. And let's not forget our semicolon.
04:46But it shouldn't really be visible in the Inspector, so I am going to go ahead
04:51and go back here and make it an internal variable.
04:58And finally, we'll add the conditional that brings the speed back up.
05:02So let's go out and get that one from the snippets file.
05:05Ch04/Code_Snippets. And our last conditional is, if the rotation speed is less
05:21than 0, well, then we are going to reset it to the startSpeed.
05:27We also need to set the startSpeed in the start function,
05:32so let's go ahead and copy that one first, tab back over to our scripting editor.
05:43So we want to add that one in the start function so it sets the startSpeed to
05:49whatever was left in the Inspector, and now we'll tab back over and get our final condition.
05:58If the rotationSpeed is less than zero, we are going to set it to the
06:03startSpeed. Right-click and Copy, tab over, and that one we are going to add
06:12after the rotationSpeed has been changed. And I am going to pop it in here,
06:18Ctrl+V, and there it is.
06:23So we'll click Save and see what happens.
06:27Back to the Unity Editor. We click Play.
06:31I'll click my cube a bunch of times. And now it's almost at a dead stop, so
06:39pretty soon--if we watch over here Rotation Speed, it just got reset to 10. So there we go.
06:51It reduces and you can watch it over there in the Inspector, but when it gets
06:56down to zero, the next time I click, it goes back up, so our player is rewarded.
07:03Let's exit Play mode.
07:05So there go, a bunch of logic used to control not only speed but whether the
07:10object is even allowed to rotate.
07:12A good part of gameplay will depend on how thorough you are when working
07:17out this kind of logic.
07:19And that's when variables and if statements come in extremely handy.
07:22Enough of this theoretical scripting. In the next chapter we'll start working
07:27on our actual game.
07:30So a quick recap. Math functions are often abbreviated by putting the operator
07:35before the equals sign, and to increase the conditions that must be met in an
07:40if statement, we can use double ampersand for "and," and we can also use the
07:46double bars for "or."
Collapse this transcript
5. In-Game Scripting
Exploring distance and local variables
00:00Mouse picks and screen touches may be okay for some situations, but a lot of things, especially
00:05in first-person shooters, happen by collision or even directional proximity.
00:10The code for this stuff gets a little more complicated, but it will be worth it.
00:15The tradeoff is we won't have to worry about logic and states so much; we'll be letting
00:20the games physical world do most of the work for us.
00:23We'll need more than the cube to test the stuff out on, so this time we'll be going
00:28back to our game scene.
00:30Let's go ahead and load the MainLevel scene.
00:33We can find it our Project view and double-click it in, and there we are.
00:38We'll also be using the wide layout for this one, so I am going to switch from 2 by 3 to Wide.
00:46Let's start by creating a new script in there Practice Scripts folder.
00:50Let's go over here and find it.
00:52Here is our Practice Scripts, right-click, Create > JavaScript.
00:58And this one we are going to name ReportDistance.
01:03And we'll go ahead and open it in the Script Editor.
01:06The first thing we need to do is give it a variable that will hold the object we are checking on.
01:12Notice I said object, not the name of an object.
01:16This is a key concept in Unity.
01:19We'll start by calling our variable targetObject. So I am going to go up here, give myself a
01:24little bit of room with the Enter key.
01:27We start with var, and we are naming this one targetObject.
01:34And here comes the tricky part. We need to decide what type our variable needs to be.
01:40So let's think about it.
01:41We need to know its position to be able to calculate the distance from the object that
01:47has the script on it.
01:48A while back when we were looking up transforming the docs, we found that every object has a transform,
01:55and from that we can get its position information.
01:58So for type we are going to choose Transform.
02:03:Transform, and we'll finish our line with a semicolon.
02:10Next we need to get the distance.
02:12Since distance is something that should be calculated every frame, we are going to need
02:17to put our distance-checking code in the update function.
02:20This one is a little trickier so I am going to go out and find my code snippets and copy
02:25and paste from there.
02:27From my exercise files folder Ch05/ 05-01, there is our Code_Snippets.
02:35Here is our variable.
02:36I type that in manually this time, but this is the line that we want.
02:41Highlight, Right-click > Copy, get back to the Script Editor,
02:47and this one, as I said earlier, is going to go into the update function.
02:51Give it some space and Ctrl+V to paste it in.
02:57So let's look at what we've just added.
02:58We are little short of space here, so I am going to reduce the other sections.
03:04And let's see what we've got.
03:06We have our if statement, then our variable name all alone as the condition, if (targetObject).
03:15Before we saw if a variable was a Boolean type it was true or false, and we are checking
03:20the conditional to see if the expression in it evaluates to true or false.
03:25So what's the deal?
03:26It turns out that if we try to get the distance from an object that did not exist, we'd get an error.
03:33If we wrote the conditional out long-hand it would look something like this.
03:38targetObject is not equal to null.
03:44So if the targetObject wasn't equal to null, it would evaluate to true.
03:50Don't confuse null with zero; null is nothing.
03:54If a variable does not have a value, its value is null.
04:00Let's look at the next line.
04:01var means we are declaring a variable and its name, well, in this case is dist, short for distance.
04:09Next, we are feeding two positions into the Vector3.Distance to get the distance, targetObject.position
04:18and this.transform.position.
04:22Remember that our targetObject is already a transform.
04:26One more thing about our dist variable: because it was declared inside a function, it is considered
04:34to be a local variable.
04:36That means it's created each time the function is entered and destroyed as soon as the function is exited.
04:43So this one being in the update function is created and destroyed every frame. And there
04:50is one other thing: because it doesn't exist outside its own function, a local variable
04:56is not accessible to any other functions in the script.
05:01Let's save the script and test it.
05:03I'll click Save and back to the Unity Editor.
05:08And now we need to figure out what to do with it.
05:12To make it interesting, at least one of our objects needs to be moving, and the only mobile
05:17object we have so far is the First Person Controller.
05:21So let's drag our script, ReportDistance, on the Bridge Plank and use the First Person
05:27Controller as the target object.
05:29I'll need to open my structures for seeing to find the Bridge Plank. Here it is.
05:35So I'll drag and drop it right onto the Bridge Plank.
05:39Now if I select it and I look almost at the bottom--here it is, Report Distance--we notice
05:44it is looking for the targetObject, and it has a None in it,
05:48but it's expecting a transform type.
05:51Here is how we load it.
05:53We just drag the First Person Controller from the Hierarchy view onto the targetObject
05:59value field, and there we go.
06:02First Person and if we drag this out, we can see the whole name here.
06:09And we are ready to test. And we are going to be watching the status line down here as
06:13it reports the distance.
06:16Let's click play. We are now showing the game window, and I am going to click W. And watch
06:22the target distance down in the status line and we'll head out towards the Bridge Plank.
06:28And the closer we get, the smaller the number becomes.
06:32Its pivot point is on the far side, so right about there it's almost zero.
06:39Let's exit play mode and look at one more thing.
06:42If we have a lot of objects with the same script that need the same targetObject, it
06:47might get tedious dragging and dropping it onto each one.
06:52If the targetObject is always the same for the script, you can find it and assign it in
06:57the Start function.
06:59Let's open the script again and add the next line to our code.
07:04Over to my snippets code, and I am going to grab the entire start function and right-click,
07:10Copy, tab back to the Script Editor, and I'll replace the existing function start with the
07:19code that I copied from the snippets. And Ctlr+V to paste.
07:26So now what's going to happen is, we have our targetObject variable, but in the start
07:31function, it's going to go out and it's going to search the entire game to see if it can
07:38find something called First Person Controller.
07:41And then it's going to get its transform and it's going to feed all of that back into our variable.
07:47Theoretically, we don't need the variable to show up in the Inspector anymore, but I
07:53am going to leave it here just so we can check and make sure it actually did find it.
07:57We'll go ahead and save our script, tab back to the Unity Editor,
08:03and just to make sure we can see that it's doing its job, over here in the targetObject--
08:09remember, we have the Bridge Plank selected--
08:12I am going to open the browser and set this to None.
08:17When we click play, keep an eye out over here and as soon as it starts, it should find the
08:23First Person Controller.
08:25So let's click play and there you go;
08:28it found our First Person Controller.
08:31So we can go ahead and exit Play mode now.
08:34In this video we found out how to both load and find a game object for use in a script,
08:40which is a mainstay of Unity game authoring.
Collapse this transcript
Raycasting
00:00So we have been experimenting with distance checking, but there will be times
00:04when the only thing we care about is what is in front of the player or in the
00:07case of a mouse pick or touch event, what is under the cursor or finger.
00:12To do that, we need to cast a ray into the scene.
00:15If you think that sounds suspiciously like vector math, you'd be right.
00:19But don't panic; Unity will take care of the calculations for us.
00:22The cool thing about ray casting is that we get a bunch of useful information
00:27back when something is detected.
00:30You may wish to double-click the First Person Controller to get a better view in the Scene view.
00:34This time, in the Practice Scripts folder, let's create a new script and call it RayCaster.
00:41Practice Scripts, right-click > Create > Javascript, and we're going to
00:47name this guy RayCaster. And we'll open him up in the Script Editor by double-clicking.
00:54Let's make sure we're over in the RayCaster script, and in the update function
00:59we're going to need lots of code,
01:01so I'm going to copy it from the snippets file.
01:04I'll tab out. From the exercise files folder, Ch05/05-02, I'll open my Code
01:13Snippets, and we want to take the whole first section here. Right-click and
01:19Copy, and then we'll tab back over to the Script Editor, give ourselves a little
01:24room, and paste it in.
01:27Let's see what we've got this time.
01:30The first line uses the RayCaster function from the physics class to see if
01:34there is anything straight ahead and within ten meters of the object the script is on.
01:38And since the whole kit and kaboodle is in the if statements condition, we're
01:42having it tell us when it evaluates as true--in other words if it has detected
01:47something ten meters.
01:49Let's go ahead and save our script, head back to the Editor, and then we can
01:54apply it to the First Person Controller.
01:57RayCaster, we'll drag and drop them right onto the First Person Controller.
02:01Now before we hit play, let's go back into the Script Editor, and if we look,
02:07we can see that the Unity Script Editor has been tabbing scripts that we've already had open.
02:13I remember that in report distance we were having it print out to the console,
02:19and I think we need to suppress that.
02:21And we'll use the double forward slashes to comment it out.
02:26That way the message we're sending out from the RayCaster script will be easily
02:30seen in the status line.
02:32So save. Now we can go back to the Editor, click play, and drive our First
02:39Person Controller around, watching the status line. There is something in front of the object.
02:45Exit Play mode.
02:46As you might guess, there is pretty much always going to be something within ten
02:51meters of the First Person Controller. Even if there wasn't, there is no message
02:55to tell us that, so we really ought to add one.
02:58Let's go back to the Script Editor, and we're going to add an else clause.
03:03Let's go ahead and close out the other two scripts so we won't get confused.
03:08Now that we're in the RayCaster script, we're ready to add our else clause.
03:12I'm going to tab over, and we're going to add else print, "There's nothing
03:18directly ahead," and we end our line with a semicolon.
03:23So we can go ahead and save, toggle back to the Editor, click play, and this
03:29time our message in the status line should change as we move around the scene.
03:34Using my W key and we can see it changing.
03:39This is marginally more helpful, but it would be even better if it could report
03:42what the object was within ten meters.
03:45Let's exit Play mode. It turns out that many functions are capable of taking
03:50different arguments.
03:52For the Physics.Raycast we just used, we fed it an origin, a direction, and a
03:57distance--the length of the ray.
04:00If we want to know about the object the ray cast found or hit, we need to add a
04:05new variable. So let's get back to our Script Editor, and at the top we're going
04:11to add var of type RaycastHit.
04:15So colon, space, and that's a capital R, RaycastHit, and the closing semicolon.
04:24You might also want to add a comment, something like "holds some of the properties
04:28of the object that is detected."
04:31And now we need to add the hit variable inside the Physics.Raycast.
04:37And that goes right before the ten meters. Give them a space, type "hit," and
04:44another comma so it knows it's a different parameter,
04:47and we should be good to go.
04:49It's worthwhile looking at both Physics.Raycast and RaycastHit. They may not
04:55make a whole lot of sense yet, but it won't hurt to check them out.
04:58I'm going to go ahead and save my script, tab back into the editor, and from
05:03the Help window, this time in the Scripting Reference, in the search field,
05:09let's go ahead and type "RaycastHit" and hit Enter, and the first one at the top
05:14of the list is RaycastHit.
05:17We can see that it automatically can return a distance. And we can also get a
05:23transform of the object we hit, and if it's got a transform, we can get its name property.
05:29So now let's change the print line in our script so that we can see what we hit.
05:35I'm going to tab back over to the Script Editor, and in my print statement I'm
05:40going to change it to "there is a," and then I'll add the quotation marks, give
05:45myself a space before them, and then we're going to put hit.transform.name.
05:53And let's not forget the plus marks to concatenate our strings together.
05:59For the last part, we can just say space directly ahead.
06:02That looks pretty good.
06:04Let's save the script, head back to the editor, and now if we hit play, we'll
06:11see a lot more information down there.
06:14Nothing directly ahead, terrain, building outer. So there we go.
06:20It works. Let's exit Play mode.
06:23If you drove your First Person Controller as far as the bridge plank, you may
06:27have noticed that it's never detected.
06:29That's because we put the script on the First Person Controller.
06:34If we did go out there and we looked up and down, we'd notice that only the camera is
06:39looking at the bridge.
06:40If we wanted to see what the ray cast is looking at rather than what's directly
06:45ahead, we would have needed to put the script on the camera.
06:49So with Physics.Raycast, you can see that we can get a bunch of useful
06:53information back when something is detected.
Collapse this transcript
Building timers
00:00Another thing that is going to be useful in many games is the timer.
00:04For that we'll start by getting the time in seconds since the game started.
00:08We'll do that with Time.time.
00:12To check it out, we'll just borrow our RayCaster script and we'll test the code that way.
00:17So let's open our RayCaster script, and I'm going to start by commenting out our
00:23two print statements, forward slash, two of them.
00:27And below the else I'm going to add our new little bit of code, and this one is pretty simple.
00:34We're going to print Time.time, and that's a T on the first one. (Time.time);,
00:48and then we'll go ahead and save this guy, and we'll tab back to the editor.
00:53Now watching the status line, as soon as we click play, you'll be able to see
00:58the time ticking away.
01:00Let's go ahead and exit Play mode.
01:02We really need a way to show the time in the viewport so the player can see it too.
01:08When we cover Unity GUI elements we'll use only scripting for onscreen displays.
01:14For now though, because many of you are new to scripting, we're going to use a
01:18Unity object, the Unity GUI Text Object. Let's create one now.
01:24From GameObject > Create Other, we're going to select GUI text.
01:30It comes in in the middle of the viewport, and we can see it in the Hierarchy
01:34view. Let's name it Timer Text.
01:38Over in the Inspector we have access to its parameters.
01:41Let's set the Text field to zero and change the Anchor to lower-right.
01:47Here is our text field, we're going to set that to zero, and we'll change our
01:52anchor to lower-right.
01:54Arial is the default font in Unity, and font size, if set to zero, is its default size.
02:01System fonts such as Arial can be dynamically sized since the operating system
02:05already has, or can generate, them in the different sizes.
02:10Our text is a little small, so let's go ahead and set it to about 28.
02:14We'll turn on Maximize on Play in our Game window, and when we click play we can
02:23see the text right in the middle of the window.
02:26Let's exit Play mode and position it.
02:29To position a GUI text object we need to use the transform.
02:34I can move my text object by moving my cursor over the label in the transform
02:40and clicking and dragging, or I can type directly in the text field.
02:44So now that we've got our little heads-up display, it's time to make a new script for it.
02:51In the Practice Scripts folder, let's create a new script.
02:55So we right-click, Create > Javascript, and we'll name this one simply Timer, and click Enter.
03:03You'd think that scripting the time to show would be as easy as text =
03:09Time.time, but it's not.
03:12If we check the Inspector for the timer text, we can see that the Text parameter
03:18is in the GUI Text component.
03:21To access that, we'll need to get the component first.
03:25Let's open our Timer script, and then I'm going to head over to my snippets to grab the code.
03:32exercise files, 05-03/Code Snippets, we've already tried this one, so we want
03:41this line right here.
03:42GetComponent, right-click > Copy, and then we'll Tab back to the Script Editor.
03:50And since this is something that happens every frame, we're going to paste it
03:53into the Update function.
03:55And if we're going to be nice and tidy, we'll go ahead and give it a tab here.
04:00I've got GetComponent and it's going to get the GUI Text component, and it's
04:05going to get its text parameter, and then it's going to assign Time.time to that parameter.
04:12We'll save. But when I go back to the Editor, the console--let's click it open here--
04:19is giving me an error.
04:21It says, "Cannot convert float to string."
04:25The time parameter can only take a string-type variable.
04:28So now we need to wait to cast a float to a string. Let's get back to our Script Editor.
04:36The normal JavaScript use would be ToString and then in parentheses you'd have Time.time,
04:43but that gives us an error in Unity.
04:45So a search of the Unity community will turn up what we need. In this case
04:50we need to use some number here .ToString() with empty parentheses, so let's
04:57try that right now.
04:58Here is our number, Time.time. We need to add .ToString and then empty parentheses.
05:08Let's save the change and check back in the console. Give it a chance to
05:13update and it's happy now.
05:16And now we can go ahead and add our new script to our GUI text object.
05:20I'll just close the console first.
05:22Here is our Timer script, and we'll add it to our Timer Text, and when we click
05:28play, we see the results.
05:30There is nothing like fractions of a second ticking over to pressure our player.
05:35Let's exit play mode.
05:37To lower the pressure, why don't we try converting the float to an integer first?
05:43It turns out this is another of those oddballs that doesn't follow the usually
05:47Unity JavaScript rules.
05:49Let's go back over to our Script Editor and see what we need to do.
05:54This time it gets an argument, the float,
05:56but the function name is not capitalized.
06:00So first we need to convert the float to an integer.
06:03That's going to look like this.
06:05parseInt and then we put our Time.time in between the parentheses as the
06:13argument, and then we finish up with our ToString.
06:18Let's go ahead and save the script and see what we've got now.
06:22Tab to the editor and click play.
06:25And now it's much better.
06:28Let's exit Play mode.
06:30Our little timer is working nicely, but if we need to make a regular timer, we
06:35will be able to start the timer by storing the current Time.time and the
06:40subtracting the end time to find the elapsed time.
06:43Since we really don't a timer at all for our game, I'm going to go ahead and
06:47deactivate the Timer Text object back in the Hierarchy view.
06:51So we select it, and remember, we can deactivate an object up in the
06:55Inspector, like so.
06:57We'll be using GetComponent regularly throughout this course, but you might want
07:03to make a note of ToString and parseInt since they are oddballs.
Collapse this transcript
Creating a simple projectile
00:00With first-person shooters, a good portion of the animation is driven by physics,
00:05but when we talk about physics and game engines, you need to understand that the
00:08game engine physics are only a rough approximation of real physics.
00:13The calculations involved with the real thing takes way too long to use in a
00:16real-time environment.
00:18Bottom line, game physics is not a silver bullet;
00:21it won't magically solve everything.
00:24On the other hand, it's excellent for producing the randomness that's lacking
00:28in keyframe animation.
00:29We'll take a closer look at physics later on in the course, but since we'll need
00:34it for our simple projectile, we'll go ahead and get a sneak peak now.
00:39Let's start by switching to the 2 by 3 layout.
00:42Up at the top, 2 by 3. And let's load the scripting test scene.
00:48Here it is right here.
00:50Select the cube and rename it Cube1 or something to differentiate it.
00:54So I'm going to put it into Rename mode and I'll just add a 1 to it. And then
01:00we want to focus in on it, double- click, and we'll create another one,
01:04GameObject, > Create Other > Cube. We'll name this one Ground.
01:12And I'm going to scale this one, zoom out a little and squash it down, so that
01:19we have a Ground object. And you may want to scale it a little bit bigger.
01:23Then I'll go ahead and move it down so that it's just beneath our cube.
01:27Now let's create one more cube, and once again let's focus in our first one,
01:33GameObject > Create Other > Cube, and this one I'm going to use my middle-mouse
01:40roller to zoom out, and we want to move this one up slightly above the other one,
01:45by pulling on the Y axis handle.
01:48Let's adjust the view using our main camera.
01:51We might want to go ahead and use GameObject > Align With View, and so now we can
01:58see them both on our game view.
02:00Let's go ahead and click play and see what happens.
02:03Our bottom one that had the script on it is rotating, but our top one is just
02:07hanging there in space.
02:09Let's exit Play mode and see what we need to do.
02:12For physics to come into play objects need a rigid body component.
02:18So we'll select our cube--
02:19that's the top one--and from the Components menu, under Physics, we are going
02:25to add a Rigidbody.
02:27And we'll just leave all the default as is.
02:31Now when we click play, the cube drops.
02:35Let's exit Play mode again and make it a little different.
02:39I'm going to zoom out slightly in my scene view. And I want to move my cube over
02:45just a little bit, because we want them to still hit the edge of this cube, and
02:49we're going to move them up higher so he has a longer distance to fall.
02:53It looks like I could drag him over a little bit farther, and I want him to just
02:58hit the corner. Now click play and watch what happens.
03:02It hits, tips, falls again wobbles and settles. And that's a lot of animation for
03:07practically no effort.
03:09Gravity did most of the work.
03:11Best of all, we didn't need to do anything to any of the other objects. And we
03:16can go ahead and exit Play mode.
03:18Now that we've seen a little bit of physics in action let's go ahead and load
03:22our main level, double-click it.
03:25Yes we can save the scene.
03:28And now we're ready to make our projectile.
03:30So gravity maybe free with rigid bodies, but everything else needs to be scripted.
03:35So let's start by creating a new folder called Game Scripts.
03:40This time I'm going to go up to Assets.
03:43It brings up the same as the right- click menu. Then I'm going to say Create >
03:47Folder, and we're going to name this guy Game Scripts. And this is going to be
03:54our first real script for our game.
03:56We want to create a new script, so right- click > Create > Javascript, and we're
04:02going to name this guy Projectile.
04:03And we'll go ahead open him up in the Script Editor.
04:08The first thing we're going to need to add is a variable for our projectile.
04:13So I'm going to give myself a little bit of space here, and that's going to be
04:18var. And we'll call it projectile, lowercase because this is a variable name.
04:24And this guy needs to be of type GameObject, and semicolon.
04:31And now we'll need some code in the Update function.
04:34This is a quite bit of new code, so I'm going to tab out to my desktop and pick
04:39up my Code Snippets from 05/05-04. We'll open these guys up.
04:48There is our projectile variable that we added, and we want everything underneath that.
04:53And that's including the Update function.
04:56So we'll right-click and Copy, and then we'll tab back over to our Script Editor,
05:02and since we already have the Update function, we'll just paste it over the whole thing.
05:06So let's see what we've got here.
05:09Our variable is of type GameObject because we'll need access to more than
05:13just its transforms.
05:15Next, we see that our code is in the Update function, and this is because
05:20the engine needs to constantly check to see if the player has pressed the fire button.
05:25So far, nothing new, but now in the conditional of the if statement, we see
05:30something that says Input. Getbutton and ("Fire1").
05:38If that condition is true, do the then clause.
05:42We'll cover that in a minute, but let's go back to that Input.Getbutton.
05:45Obviously we are dealing with a user input button press.
05:50The mystery is, which button is Fire1?
05:54Fire1 is just a virtual button.
05:57We or the player can map anything we want to it. But let's take a quick peek to
06:02see what the default mapping is.
06:04We'll need to head back to the editor for that and from the Edit menu > Project
06:10Settings, we're going to look at the first one, Input.
06:14Over in the Inspector, we now see something called Axes. We'll open that guy up
06:20and there it is, Fire1.
06:22Well, let's see what it has in it.
06:25Fire1 it turns out is using the left control button and is also using mouse
06:32zero, which is also the left mouse button.
06:36So let's go back to the Script Editor and add a comment in the code to remind us what they are.
06:41I'll tab back over to the Script Editor, and then I'm going to make some space
06:46up above our conditional and add a comment.
06:49Fire1 button is left mouse or left Ctrl key.
06:55And now let's see what pressing the fire button is supposed to do.
06:58First, it creates a new variable called clone.
07:02Well, this is the tricky part and another key feature in Unity.
07:06It instantiates or creates a new copy of the object that we will be loading in
07:11to the projectile variable, and it does it at the location and orientation of
07:18the object that the script is sitting on.
07:20It won't go anywhere yet, but at least it will be making a projectile.
07:25So let's go ahead and save our script and head back to the editor.
07:30Now we could put the script directly on the First Person Shooter, but that would
07:35make it hard to position, so instead let's focus in on the First Person
07:40Shooter's main camera. To do that we'll need to open this hierarchy up, and we'll
07:46double-click to focus in on the main camera. Use Alt and left mouse button to
07:52rotate our view so we actually get to see him. Double-clicking again to make
07:57sure we're focused there, and now we're going to make an empty GameObject to
08:01organize any gear our player may end up with.
08:04So GameObject > Create Empty, and we're going to name this guy Weapon Handler, and
08:12hit Enter. And we need to add that to the main camera,
08:16so I'll click and drag it and drop it on the main camera.
08:20And now we'll make a proxy weapon from a cube to give the projectile a place to
08:25be instantiated from.
08:26GameObject > Create Other > Cube.
08:31Focus in on this guy to get a little closer. That's much better.
08:35And what we want here is we want to kind of shape it long and narrow, so I'm
08:40going to use my uniform skill first.
08:42That's by clicking on the center cube.
08:45Then I'll go ahead and scale it on the Z to make it a little bit longer, so
08:49it'll look more like a weapon.
08:52And maybe I need to scale it down a little more.
08:55Now this guy needs to be positioned so that its Z axis points forward, just like
09:01the First Person Controller.
09:03So I'm going to switch back over to position and make sure I know which way
09:07my First Person Controller is facing. It looks like he is facing that direction.
09:12So I want to make sure my Cube, which by the way we want to name Proxy Weapon, is
09:19going to be facing the same direction, which means we're going to have to rotate
09:22this one. And I'm going to do it scrubbing my Y label over in the Inspector.
09:28And if I remember correctly, that's which direction our First Person Controller is.
09:34And I got it to 86.28, so I'm just going to click inside the field and type 90.
09:39And we probably don't want it quite as high as the head, so I'm going to drop it
09:45down to about there.
09:46Now we can start seeing it in the game view, so you can do a little bit more
09:50adjusting there if you'd like. You might want to move it to the side and bring it down a little.
09:57So this is going to be our proxy weapon, and this is where the script we're writing is
10:01going to be placed, because this is where the projectile is going to come from.
10:05This one also needs to be put on the weapon handler,
10:10so I'll drag it on to the weapon handler object. And now our hierarchy for the
10:17First Person Controller should look like this.
10:20Here is the First Person Controller, its Main Camera, its Weapon Handler, and the Proxy Weapon.
10:27Now we're going to need our projectile. This one is easy.
10:31From GameObject > Create Other, we're going to create a sphere. And you can move
10:38it anywhere you want because we're going to delete it eventually,
10:41but I'm going to go ahead and scale it down to about 0.25.
10:46You could make it exact in there if you wanted, but that's all we need; we just
10:49need to get close to it.
10:51This guy we want to name Cannonball.
10:54And so we can get all that physics, we need to add a Rigidbody component to it.
10:59So Component > Physics > Rigidbody.
11:03The Rigidbody is needed for it to react with physics, including gravity.
11:09In order for an object to be instantiated, or created on the fly, we need to have
11:14what is called a prefab of it in the Project view.
11:18We'll get lots of practice with prefabs later, but for now let's just make
11:22one for the sphere.
11:24From the right-click menu > Create > Prefab.
11:29And it sort of ended up where I don't want it, so I'm going to just drag it out.
11:34It doesn't really matter where you drag it, as long as you get a bar.
11:37Unity is going to alphabetize this anyway. And there we go, a new prefab.
11:43And we're going to call this guy Cannonball.
11:47Notice right now the little icon cube is white.
11:51As soon as we drag our Hierarchy Cannonball into it, it's going to turn blue.
11:59This means it's ready to go.
12:01It also means we can select our original one and delete it.
12:06So now our game has the concept.
12:08It has the blueprint, so to speak, to make a cannonball anytime we ask for it.
12:14Let's go ahead and load it into our weapon.
12:16If we select our proxy weapon, we see that first we are going to need to add our
12:21projectile script to it.
12:22And in the Inspector, under its Projectile parameter, that is where we need
12:29to add our Cannonball.
12:31So we drag it from the Project view right into that field. We're all set.
12:36I'm going to double-check on our Script Editor to make sure that we've saved
12:41the latest changes.
12:43And yes, we have; it's grayed out, so we're good to go.
12:46So let's get back to the editor. And it's finally time to test,
12:50so let's click play, move the cursor to the Game window, and either click the
12:56left Ctrl button or left mouse button.
13:01Nothing is moving much yet, but if you watch the Hierarchy, you can see there are
13:05a lot of Cannonball Clones being created, every time we click.
13:10We'll get our wayward projectile and virtual fire button under control in
13:14the next video.
Collapse this transcript
Refining the projectile
00:00We made an excellent start on our projectile in the last video, but now we need
00:04to solve the problem of too many projectiles.
00:07Open the Projectile script and we're going to add a new variable.
00:12Underneath projectile, we're going to add var fireRate, of type float, and this one
00:21we are going to go ahead initialize it to 0.5, and we'll add our semicolon.
00:31This will be how long before the next projectile can be fired.
00:34Next we're going to need an internal variable, and we're going to name this guy
00:39nextFire to keep track of when the next projectile can be fired, and that's
00:44where Time.time comes in.
00:47So our next variable is var nextFire.
00:54It's also of type float, and this one we're not going to initialize. And I said
01:01it was going to be internal, so let me go back and add that.
01:04Remember, internal means that it's not going to show up in the Inspector.
01:08Next, we'll need to add the extra condition to our if clause.
01:13This is the part that prevents all those extra projectiles. And that goes into
01:17our if clause, and we're going to use our && for "and." And the second condition
01:25that needs to be met is Time.time > nextFire.
01:32Also, we need to update the nextFire variable each time we do fire it off,
01:38so we'll do that even before we instantiate the current projectile. And we can
01:44add that right above the instantiation line, nextFire = Time.time+fireRate.
01:56And of course we need to finish our line with a semicolon.
02:01So this is basically like we're looking at a clock and saying some event can't
02:06happen until it's five minutes from now, or in our case, 0.5 seconds.
02:12Let's save the script and then we will tab back into the editor.
02:16Let's click play and fire it off with either the left control button or the left mouse button.
02:22This time only one is generated per click or key press.
02:26Let's exit Play mode and get our cannonball going somewhere.
02:30We'll be doing that by giving it some velocity.
02:33Let's toggle over to the Script Editor again.
02:35First, we'll need a variable to control its speed, so I'm going to add another
02:41variable, var speed, of type float, and we are going to initialize that guy to 5.
02:52The last two lines are pretty complicated, so I'm going to copy them from the Snippets file.
02:57I'll just tab out there and find them.
02:59exercise file, Ch05/05-05.
03:05Here is our Code_Snippet. So we've done most of these, but these are the two we need.
03:11I'm going to grab them both and right-click and Copy.
03:15Then I'll tab back over to my Script Editor. And these guys go right below
03:21the clone line, because we have to have something to project before we can project it.
03:25So I'm going to Ctrl+V and paste.
03:29I've got a line here I don't need, so I'm going to get ride of that guy. And then
03:33I'll tab this line over so it matches up better.
03:37So let's see what we've got here.
03:39The velocity line is not as bad as it looks.
03:42It just sends the projectile off in the Z direction.
03:45That's where we've got our speed variable.
03:47But the second line is also important.
03:50Remember how our cube reacted with the other objects in our physics test?
03:55This line tells the projectile to ignore the root object the script is on,
04:00the First Person Controller's Collider.
04:02In our case, we also have the Proxy Weapon;
04:06we're just using it as a placeholder so we'll need to remove its Collider
04:10component when we get back into the editor.
04:13For now, let's go ahead and save and now we can tab back to the editor. And I'm
04:19going to open up my First Person Controller > Main Camera > Weapon Handler, and
04:26select the Proxy Weapon.
04:27We are going to remove the Box Collider so the projectile doesn't collide
04:32with the Proxy Weapon.
04:34We can do that by right-clicking and choosing Remove Component. That should be it.
04:39We've saved the script, we're back in the editor, and so now we can click play
04:45and test our new projectile.
04:47Be sure you move your cursor back into the Game window before you click Fire, and there I go.
04:54Well, it looks like 5 is a pretty paltry speed for our projectile,
04:59so I'm going to go back over to our Projectile script where it's on the Proxy
05:04Weapon, and I'm going to change my Speed until it's something I like.
05:08I'm going to try about 20.
05:11Now when I get back here in the Game window, we're getting some better action.
05:17Remember though, as soon as we exit play, we need to go back to the Inspector
05:23and reenter the value so it becomes permanent.
05:26We are well underway with our Projectile, but we'll still need to do some
05:30cleanup in the next video.
Collapse this transcript
Exploring the OnCollision variable and tags
00:00Now let's tidy up the projectile and incorporate it into our game.
00:05The first barricade is conveniently open, but the second won't be so easy to win through;
00:09it will need to be bombarded by our cannonballs.
00:12Let's move the First Person Controller to the nature side of the doors.
00:16I'm going to click the Y axis in the Scene view and then zoom out. And I can pan
00:27pressing my middle-mouse roller instead of rolling it.
00:30Then I'm going to select the First Person Controller, make sure I'm in Move
00:36mode, and I'll go ahead and grab this gizmo and drag him over.
00:41Now I need to pan a little bit more. And there is the barricade, and I want to
00:47move him over to the other side.
00:49And it'd be nice if we go ahead and rotate him
00:54so he is looking at it.
00:58So go ahead and position the First Person Controller so he is in a handy area.
01:04The first thing we ought to do is get rid of the cannonball sometime after it's been fired.
01:08We'll need a script for that of course. So in the Game Scripts folder--I'm going
01:13to highlight that--let's right-click, Create > JavaScript, and this one we're
01:21going to name ProjectileHandler.
01:25Before we jump into the Script Editor though, let's go ahead and turn our
01:28Solid Door back on.
01:29He is in Barrier 2 and his name is Solid Door, and you can see he's been grayed out.
01:37So we're going to go up to the Inspector and activate him.
01:41Now we're ready to go to the Script Editor.
01:43We'll double-click our ProjectileHandler, and there we go.
01:50At it's simplest, we can get away with adding inside the start function--after we
01:56give ourselves a couple of spaces-- Destroy(gameObject, 5). So I'll tab over.
02:04Destroy is the function, and the arguments are gameObject--that's the object
02:16that the script is on--and comma 5.
02:195 is the number of seconds before the gameObject is destroyed. And of course we
02:26need our semicolon to end the line.
02:29We'll save the script, head back over to the editor, and now we need to add the
02:33new script to the Cannonball prefab in the Project view.
02:38So let's locate it.
02:39There is our Cannonball. We'll select it and we're going to drag the
02:43ProjectHandler script and drop it directly onto the Cannonball prefab, like so.
02:50Now we can click play and test the script.
02:57In the Game view, as soon as I fire an object, the projectile, it goes out and
03:03after five seconds it disappears.
03:06And if you're not sure it disappeared, let's do one in the dark.
03:09It might show up better. Okay, no it's not, we'll hit the door.
03:12There it goes and it should pop out right there, so we know it works. Let's exit play.
03:22A time destroy is okay for some things, like rockets that shoot quickly out of range.
03:27But for a projectile it will make more sense for it to disappear after it's hit something.
03:32So back in our Script Editor, let's comment out the Destroy line, two forward
03:39slashes, and we're going to add a new function.
03:44I'm going to go out for my Code_Snippets to find it, Ch05/05-06 and my Code_Snippets.
03:53So we're going to take the second one right here, because we already entered the
03:57first one, right-click, Copy, tab back over to our Script Editor. And this one is
04:07a function all on its own, so I'm going to put it beneath the Update function by
04:12Ctrl+V, pasting it in.
04:14And let's see what we've got here.
04:16This one is pretty easy to read.
04:19When it first collides with something, it will get destroyed after one second.
04:23Time, by the way, is optional on destroy.
04:27Let's save the script now, head back into our editor, and click so we can test it
04:32by shooting at the door.
04:33Play, find the door, and shoot. Ooh and there it goes; it disappears right away almost.
04:44So we know that one works.
04:47Now we can exit play.
04:50At some point you may want different reactions depending on what was hit.
04:54Lucky for us, OnCollisionEnter passes in the object that it hits, or at least its
04:59collider, and it does that in a variable named Collision, of type collider.
05:04Let's go back and look at our Script Editor.
05:05There is the variable Collision and it's of type Collision.
05:11Just like the RayCast, if we wanted, we could get the name of the hit object
05:15with something like print collision.transform.name. And since we will know
05:21it's being hit, we might not want to destroy the cannonball immediately when
05:25it, say, hits the ground.
05:27So we can add something like if collision.transform.name and then it will go
05:33ahead and carry out the instructions.
05:36That's a little bit of code, so I'm going to tab over to my snippets and
05:41grab the next part.
05:42We'll go ahead and substitute our Destroy line with this whole conditional.
05:49Select it, right-click, and Copy, go back over to our Script Editor, and we'll just replace this.
05:57Ctrl+V and now we have our new condition.
06:02So as long it's not the terrain, we're going to get the name of it this time and
06:06then we're going to destroy it after one second.
06:10Let's save our script and head back to the editor and click play and try it out.
06:17This time, if we shoot at the terrain, it doesn't destroy it, but if we shoot
06:25at the door, it does.
06:27If we shoot at the wall, it doesn't.
06:33So let's exit Play mode and look at our next issue.
06:36Now that it doesn't get destroyed when it hits the terrain, we're going to
06:39have another problem.
06:40Letting rigid bodies wander around the scene will needlessly suck up resources
06:45with physics calculations,
06:46so we should really turn off the rigid body after a few seconds.
06:50Let's head back to the Script Editor and figure out how to do that.
06:54We're going to adding an else clause to do it. And once again, I'll pop out to my
07:00Snippets file to grab the code. And here is our else clause waiting for us. Copy
07:06it, right-click, and then we'll tab back over to the Script Editor. And since
07:13it's in else clause, it goes underneath the if and I'll paste it in with
07:18Ctrl+V. So this time what's going to happen is, if it was the terrain, we're
07:24going to destroy the rigid body on the projectile after five seconds, and we'll
07:29even have a message there to tell us when it stopped it.
07:32So let's go ahead and save the script.
07:35This time though, before we hit play, we should shoot it up on the sides of
07:38the terrain. When it stops rolling we'll know that the rigid body has been destroyed.
07:45We'll click play, find a convenient piece of terrain to shoot at, and we'll fire
07:54a bunch off and see what happens.
07:58Watch this guy right here. Oh and he just stopped. And the next guy, and he stops.
08:04So we can see that's working as well.
08:07Now we can exit Play mode.
08:08So you can see that that's working okay, but what if we had lots of things we
08:14didn't want destroying the cannonball?
08:15We certainly wouldn't want to stuff all the exceptions into the conditional.
08:18Well, we're in luck; another useful Unity feature is the tag.
08:22Tags are identifiers that allow us to test for certain conditions before
08:27carrying out instructions.
08:29Up at the top of the Inspector, you'll see the Tag dropdown, with a bunch of pre-made tags.
08:36If I click on it, there they are.
08:40We want to make a new one so we're going to click Add Tag.
08:45This opens up the TagManager.
08:47Tags and layers are all handled in the same place, so we need to be sure to open
08:52up the Tags array at the top.
08:55And we'll make a new tag called Don't Destroy.
08:59Click on Element 0 that's waiting for us, and Don't Destroy.
09:06Now we can head back to the Script Editor and change our code.
09:09Instead of collision.transform.name != "Terrain", we're going to say
09:16collision.transform.tag != and we keep the quotation marks, Don't Destroy.
09:27So we'll save our script.
09:30Now if we select our terrain, we can put a tag on it by clicking our dropdown,
09:37and there is the tag we added, so we're going to check that.
09:43And we can even go as far as going to the Cannonball and adding one to that so
09:50that they won't destroy each other, like so.
09:55We can click play and test now.
09:57As soon as we fire, they persist unless we hit the gate.
10:11So our little projectile has gotten a lot more sophisticated.
10:16In the next video, we'll be giving it something to destroy.
Collapse this transcript
Sending messages
00:00The last thing we'll do with the projectile for a while is to send a message to the hit object.
00:05For that, we'll be using the SendMessage function.
00:09It calls a function on another object's script.
00:13This will enable us to go about getting rid of that door in the second barrier,
00:17door solid, and we'll be doing that using SendMessage.
00:22Let's go ahead and open our ProjectHandler script again.
00:26We'll need to add one line inside the if collision section--two if we count the comment.
00:31I'm going to go out and get them from Code_Snippets. From the exercise files
00:36folder/Ch05/05-07, I'll open my Code _Snippets. We want this whole first
00:44section here. Right-click and copy and tab back to the Script Editor.
00:50So this one needs to be inside and right about here, and we no longer need our
00:55print line, so I'm just going to take it out as well.
00:59And I'll Ctrl+V to paste my new code into it.
01:03We haven't used this for a while, but it's an ideal time to click the
01:06right-click menu and choose Indent Selection. It keeps it tidier.
01:12I'm also going to comment out my other print statement with the forward slashes as well.
01:18So let's see what we've got.
01:20BeenHit is the name of the function we're sending the message to.
01:25When we are talking about function names, we always need to use quotation marks.
01:30And it will be sent to any script on the Hit object that has a BeenHit function.
01:35SendMessageOptions.DontRequireReceiver prevents an error message in case there
01:42is no BeenHit function on the script.
01:45And just a note here: the BeenHit function,
01:47it can have different contents on each script; only the name is the same.
01:53So now we can save the script and get back into the editor.
01:57Now we'll need a new script to take care of the damage.
02:01In our Game Scripts folder, right-click, create a new JavaScript, and this one we
02:07are going to call DoorDamageController.
02:08And we'll open him up in the script editor. And this one is pretty simple.
02:16This is where we put our BeenHit function.
02:19So it's a function all on its own, which actually means we could rid of the Start
02:23and the Update. And we are going to have function.
02:27Its name is BeenHit, our open and closing parentheses, our open curly bracket.
02:35When it's BeenHit, we just want it destroyed after one second,
02:40Destroy(gameObject, 1) for one second, semicolon, and let's not forget to
02:51close the curly bracket.
02:53And we can save this one.
02:55Now everything we put this script on, as long as it doesn't have a don't destroy
03:00tag, will get destroyed.
03:02So let's get back to the editor and try it.
03:05And we'll begin by putting it on the door.
03:08The door is in Barrier 2 and its name is Solid Door, so we are going to drag the
03:14DoorDamageController script from the Project folder over to the Hierarchy and
03:19drop it on Solid Door.
03:21Let's click play and see what happens when our cannonball hits the door.
03:26Aim at the door, left-mouse click, and voila!
03:31That was too easy, wasn't it? Or rather, it wasn't very entertaining. We'll be
03:35fixing that in the next video.
Collapse this transcript
Reacting to messages
00:00So we need to be a bit more creative with the door.
00:03I've decided our player will need to shoot the door a few times with the
00:07cannonballs to knock it over so he can get through it.
00:10First, we'll need to add a rigid body to the Solid Door.
00:14And we can find that in Structures > Barrier 2.
00:16Here is our Solid Door. And we go up to Component > Physics, and add our Rigidbody.
00:24Let's go ahead and just click play and see what it did.
00:28And as soon as we click play, it drops down through the terrain.
00:32We'll exit our Play mode for a minute.
00:35There's something important you need to know about real-time physics.
00:38When checking for intersections or collisions, only one object can have a
00:44mesh type collider.
00:45We'll look deeper into colliders in the next chapter, but what it boils down to
00:50is that the terrain must use a MeshCollider or the First Person Controller
00:55wouldn't be able to go up and down it.
00:58And imported meshes like the door are also assigned mesh colliders, or at least
01:04the option is there.
01:06In the case of the door, it's an easy fix.
01:09From Component > Physics, we'll just choose Box Collider.
01:15And since we already had a MeshCollider, we'll get a dialog that asks us what we
01:19want to do about it.
01:21We'll choose Replace.
01:22Now if we click play, the door settles right into place.
01:26I'm going to exit Play mode and turn off Maximize on Play.
01:32So let's see about knocking it over.
01:35Let's open the DamageController script in the script editor and see what we need to do.
01:40To start, let's comment out the Destroy line with our forward slashes, and then
01:46let's see what happens.
01:47I'm going to save the script, so now we should be able to hit it with a
01:51projectile and it won't be destroyed.
01:53Back in the editor, if I click play and shoot the door, we can see it wiggle,
02:03but it's not going anywhere.
02:04While still in Play mode, let's select the Solid Door and in the Inspector,
02:11let's decrease the Mass in the Rigidbody component to .1.
02:14Now we'll go back and try and shoot it again.
02:17Well, it's wiggling more, and it's trying to open, but something is holding it in.
02:24Let's exit Play mode.
02:28Apparently, it has being held up by the doorjamb in the wall.
02:31Remember that ignore physics line we added to the projectile so it wouldn't get
02:36stuck in the Proxy Weapon?
02:37It looks like we need its help to knock over the door.
02:41So let's head back to the Script Editor and add a couple of variables in the
02:46DoorDamageController script. And our two offending objects are--and we'll name
02:52our variables for them--var doorJamb is of type. Collider is all we really need
02:59for this one and a semicolon and var wall.
03:06It's also of type Collider.
03:09For the rest of the code, I'm going to go out to my Snippets file again.
03:13From the exercise files folder > Ch05/05-08/05-08Code_Snippets,
03:21there's our variables we've already added.
03:23And now we are going to take all of this, highlight it, right-click, and Copy, and
03:30then we'll tab over to our Script Editor again.
03:32So that's what we need in our BeenHit function.
03:37And I'm going to delete the original line and use Ctrl+V to paste this in.
03:44And we'll go ahead and save our script.
03:46So now when the door gets hit, its physics are going to ignore collisions with
03:51both the doorjamb and the wall.
03:54Let's head back over to the editor.
03:56Click play and see what happens.
04:00I'm firing on the door, but it's not going down.
04:03Let's exit Play mode, and this time I'll drag BarrierJamb002 into Door Jamb and
04:12the Barricade Mid into the field for the wall.
04:16Now when we click play, we should see some results.
04:21And there we go: our door is down.
04:24Let's exit Play mode.
04:26If you wanted to get really fancy, you could make a damage variable for when the door is hit.
04:31At reaching the specified amount, you could reduce the mass or any number of
04:35things to finish it off.
04:37With the door, you could even destroy it and instantiate a dead replacement for it.
04:42A mangled lump of metal would be nice.
04:45We've got lots more goodies to look into though, so let's move on to the
04:49next video.
Collapse this transcript
Juggling Play and Edit modes
00:00For the rest of this chapter we'll add a few niceties that will make authoring
00:04easier when use in shooter controls.
00:06We'll start by turning the operating system cursor off during play mode and
00:11bringing it back when we need to edit stuff.
00:14With the mouse move being used to look around, the first thing we need to do is
00:18turn off the cursor on startup.
00:21Since the cursor is not directly related to any particular object, we'll make an
00:25empty game object to manage it and other generic functionality.
00:29Let's name it Game Manager.
00:30I am going up to GameObject, and I want to Create Empty, and I'll name him Game Manager.
00:37It will be a master-control command-center sort of object.
00:42And then we'll need to make a script to do all the work.
00:46So in the Game Scripts folder, let's right-click, Create > Javascript.
00:53This one we are going to name GameManager, only without the space,
00:57and Enter and then we'll go ahead and open it.
01:01In the Start function we are going to add first,
01:05I'll make the comment and this is to remind us that it's going to Hide Cursor.
01:12And then we'll actually write the code that does it.
01:14This one comes from Screen.showCursor, and we want to make it equal false.
01:23And of course we close it with a semicolon.
01:27So save the script, get back to the editor, and now we need to drag our new
01:32script onto the new Game Manager object.
01:37Now we can click play and see what's happened to our cursor.
01:41If you are in 2x3 mode, you may find that it's kind of there and it's kind of flickering.
01:48I am going to exit play mode, but if you are in wide or you are using Maximum on
01:54Play, then when we click play, we'll see that indeed the cursor is gone.
02:00So I am going to go back up and get out of play mode.
02:05Now we are going to see about toggling it off and on with a key press.
02:09That way we can easily switch back and forth whenever we want.
02:14A key press means we'll need to check the input every frame.
02:18So let's head back to the Script Editor. And this is a few more lines, so I am
02:23going to go out and grab the code from the snippets file.
02:27exercise files/Ch05/05-09, and we'll open up the snippets.
02:34This is the one we want right here.
02:37We'll right-click to copy, tab back over to the Script Editor, and we need to add
02:43that one inside the Update function.
02:45So I'll give myself a little bit of space and Ctrl+V to paste it in.
02:51In this conditional, we are checking to see if the Escape key was pressed.
02:55Let's save the code and go back to the Editor.
02:59When we click play, now I am hitting Escape, but nothing is happening.
03:06Let's get out of Play mode and see if we can track it down.
03:10We expected it to print "Escape was pressed in the Console," but all we are
03:14getting is a bunch of numbers.
03:16I think I need to open the Console and see where they are coming from.
03:20So I am clicking it. And remember, if you double-click on a line, it will take you
03:26to the script in the line in the code.
03:28And sure enough in the RayCaster script we see print (Time.time), and we
03:34definitely don't want to see that anymore.
03:37So I am going to comment it out with my forward slashes. And remember to click Save.
03:44Now we should be able to go back to our editor, clear the Console, and see if we
03:50can click Escape and get our message printed out.
03:54Play mode, click Escape, and there it is down in the status line: Escape was pressed.
04:00So now we can exit Play mode and go ahead and put our real code into the proper script.
04:07Back in the Script Editor, we are going to switch back over to GameManager.
04:13And this is quite a bit of script here, so I am going to head out to the
04:16snippets file again.
04:18This time we are going to replace our print line with the condition.
04:24This will toggle the operating system cursor off and on when we press Escape.
04:30Copy, back over to the Script Editor, and in the GameManager, I am going to
04:35replace my print statement with the contents of the snippets file, using
04:41Ctrl+V. If you remember, when we click next to a curly bracket, we should find its matching one.
04:50So it looks like I have got one to many.
04:53So I'll delete that curly bracket and I'll double-check the rest.
04:58That one matches to there, this one matches to here. It should be good to go.
05:05Save, tab back over to the editor, and click play.
05:09As you can see, with a great relief, the status line is empty.
05:15So now in my scene if I click my Escape key, I can toggle my cursor off and on.
05:22Let's go ahead and exit Play mode.
05:23Now that the cursor is under control, let's add a radical, or crosshairs, to the game.
05:29We'll be controlling it in the same place as the cursor, so we may as well add it now.
05:35Let's start by importing the crosshairs.target texture from this video's Assets
05:40folder and we can do that using Import New Asset.
05:45It's in the same menu as the Import Package tool we've already used.
05:49Since we've only got one object, we can use Import New Asset instead.
05:55Now I need to navigate to my Exercise Folders/ Ch05/05-09/Assets, and here's my image.
06:06And all we need to do is click Import.
06:09It came in the Game Scripts folder because I had it highlighted.
06:13I'll just go ahead and drag it out and drop it into the Textures folder instead.
06:18So it's not very exciting now, but as soon as we bring it into the scene,
06:23you'll see the difference. It does have an alpha channel.
06:27Since this guy has an alpha channel and it is image, we're going to need an
06:31object to put him on in the game.
06:33This time we can use the texture version of the GUI text object: the GUI Texture object.
06:40But instead of making it first and then assigning the texture, we are going to
06:44select the texture first over in the Project view. Then we are going to go up to
06:50GameObject > Create Other > GUI Texture.
06:55That way it automatically creates the GUI Texture object, names it, and puts it
07:02at 00 in our screen space.
07:05You may need to adjust the height of the crosshair or you could adjust the speed
07:09of the projectile or even the angle of the Proxy Weapon.
07:14As with all GUI objects, in the Scene view, you can toggle it off and on
07:18with the Overlay button.
07:21To position it in the Inspector, you can ingest its X or Y screen position.
07:27So now we're ready to finish the escape functionality. We'll do that in the
07:31next video.
Collapse this transcript
Suppressing input
00:00The final touch for the escape functionality is to stop the player from moving
00:04around the scene with the keyboard and mouse controls, because it's really
00:08annoying to have the view spin when we are trying to move the cursor out of the
00:12Game view when we're still in play mode.
00:14We are handling the cursor functionality from the GameManager script, but the
00:18input needs to be suppressed in the FPSInput Controller.
00:23It's the one using the virtual input keys.
00:27So let's select the First Person Controller and in the Inspector, we need to
00:32locate the FPSInput Controller script and open it up.
00:40We'll start by testing a very powerful little function at the top of the Update function.
00:46So I am going to go up to the curly bracket, the opening curly bracket, press
00:51Enter a couple of times, and then tab over. And here is what we are going to
00:57add: Input.ResetInputAxes, and an open and closing parentheses and a semicolon to close the line.
01:14And because this is code that I added, I'm going to use my forward slashes
01:19to make the comment and I'm going to use a bunch of asterisks so I can find it quickly.
01:27Let's save our script and get back to the game editor and test.
01:33I'm going to turn off Maximize on Play, then I'll click play, and now, in the Game
01:41window, I'm going to use my arrow keys-- W, A, S, D--and mouse move, and you can see we've
01:51suppressed all of the player input, which is exactly what we want to do.
01:56So, let's exit Play mode.
01:57The First Person Controller controls no longer work.
02:02This is sort of like overriding a laser beam with a mirror;
02:06it never allows the input to be evaluated.
02:09So now we are going to need a flag in that script to tell it when to suppress
02:14the navigation, and then we'll need to send a message to set the flag true or
02:18false from the GameManager script, because that's what we'll be using the Escape
02:23key to toggle it off and on with.
02:25So let's open the Script Editor again and in the FPSInput Control script, we
02:32need to add a variable up at the top. And we can add it beneath the private
02:36variable. And this one is going to be internal var, and we'll name it noInput, and
02:43it is of type boolean.
02:48And now, we're also going to need a function to receive the message to toggle
02:53that variable, noInput, to true or false.
02:57This one is really simple.
02:58So down at the very bottom of the script--not the very bottom; we're going to
03:03keep it up above the last three lines--and we're going to add function
03:11ToggleInput, and we're going to pass it an argument.
03:24That variable's name will be state and it is of type boolean. Open
03:32curly bracket, close curly bracket, and then I'll move up inside, tab over,
03:43an add noInput = state;.
03:56So we'll be passing at the state we want it to be directly.
04:00Let's go ahead and save and toggle back into the editor. And finally, we need to
04:07open the GameManager script, and we'll need to add the variable that will give us
04:13access to the First Person Controller.
04:16So up at the top, we're going to make a var and we'll call this one fpc for
04:22First Person Controller. You'll see that used quite a bit, and this guy is
04:27of type GameObject.
04:32And now we can add the SendMessage code inside the ifs.
04:37So let's think about it for a minute.
04:39I'm going to clean these up by backspacing.
04:43So if we've hit Escape and if the screen cursor is false--in other words it's not showing--
04:51that means we want the cursor to show again, and it also means we want to send
04:56the message to the First Person Controller to block user input.
05:03So this is going to look like fpc.SendMessage, and we are sending the message to
05:16the function we just made called ToggleInput. And that needs quotation marks.
05:28And because we're sending it an argument, we need a comma, and we want to say
05:34true. In other words true, we want no input. And we can close the parentheses
05:44and add the semicolon.
05:46In the else, we need just the opposite.
05:48So I am going to go ahead and copy this line--right-click > Copy--and I'll add
05:58it under this one. Paste and of course I need to change my true to false.
06:07We've seen message before, but this time we are also sending an argument to the
06:10function we are calling, in this case a true or false.
06:13We are limited to only one argument though, and the function must always
06:18have matching arguments.
06:20You can't just send one when it's expecting two.
06:23I didn't add the DontRequireReceiver, because it should always find one since
06:27it's on the First Person Controller, but it wouldn't hurt to have it.
06:31Anyway, let's save the script and get back to our editor.
06:36Before we test it, we need to remember to select the Game Manager and drag the
06:41First Person Controller into the Fpc field.
06:46Now we can click and play, but I still can't move around in my Game view.
06:52It turns out there is one more thing I need to do.
06:56So, let's exit play, select the First Person Controller, and open that First
07:04Person Input Controller script again. And this time I need to put the
07:11condition in front of my Input. ResetInputAxes, and that is if (noInput).
07:27And that's all it needs.
07:29I save the script, toggle back to the game editor, and now when we click play, we
07:37once again have our First Person Controller controls, but if I click my Escape
07:43button, the viewport is frozen, my operating system cursor returns, and now I can
07:51go out and edit in any of the other views.
07:55Let's stop Play mode, and there we go.
07:58I don't know about you, but that was well worth the scripting.
Collapse this transcript
6. Working with GameObjects and Components
Creating GameObjects
00:00In this chapter we will be working with GameObjects and their components.
00:04GameObject is Unity's name for, well, an object.
00:08If you have a background in 3D content creation, you may already have a feel
00:12for what an object is.
00:14An object has a set of properties that define or describe it.
00:17Spheres, cubes, terrains, lights, and cameras are a few kinds of objects, each
00:23with its own unique properties.
00:24So what do all of these objects have in common?
00:27The most important answer is, a location and orientation in space,
00:32in other words, a transform or pivot point.
00:35This concept forms the basis of the Unity game object.
00:39There are a few other properties, but this one is the most important.
00:43From a programmer's standpoint it's more than a concept.
00:46The GameObject is the base class for all entities in Unity scenes,
00:51so all other objects in the scene inherit and are members of that class.
00:56If you do a search for "GameObject" in the scripting reference, you can see the
01:00variables and functions associated with it.
01:03Let's go to Help > Scripting Reference and type in the search area, GameObject.
01:12The first one, GameObject, is the one we want.
01:16We can see the variables and functions associated with it.
01:21You can have camera, light, animation, audio, collider, and there's all sorts of
01:28things we can do with it.
01:30Let's close this and get back to the editor.
01:33The term GameObject should be pretty familiar by now anyway.
01:36We've been creating simple primitive objects from the GameObject menu, and we've
01:40been using GameObjects in some of our scripts. Let's take a look.
01:44From the GameObject menu, there are two choices:
01:48Create Empty and Create Other.
01:51Under Create Other, the choices are pretty self-explanatory.
01:56Most of you have probably already deleted and added several types of GameObjects
02:00besides the ones we used in the previous videos.
02:03Let's take a closer look at the other option, Create Empty.
02:06While it seems kind of silly at first glance, as soon as you start to think of
02:11it as a container, the possibilities become apparent.
02:14It gives you a means to organize scene assets into tidy groups, control
02:19complicated hierarchies, construct custom objects, and manage object states at the top level.
02:26Take a door. Making it slide from side to side is a simple transform,
02:31but to make it a conventional swinging door, we would need to get it rotating
02:35from the end instead of the middle.
02:37Not only will an empty GameObject make that possible, it will also give us a
02:42few side benefits as well.
02:44Let's give that a try.
02:47In the MainLevel, let's focus in on the First Person Controller to give us a
02:52good place to start.
02:54Using my Alt key, I'm going to adjust my view a little bit. Then let's select
03:01GameObject > Create Other > Cube.
03:06We can move it aside and use Scale to squash it and expand it until it looks
03:16sort of like a door.
03:17Now we'll focus the Scene window on it.
03:21And from the top view we are now going to add an empty GameObject, Create Empty.
03:29And this one we can move over to where the door should pivot.
03:36When we drag our original cube into the empty GameObject and switch the pivot
03:42from center to Pivot, we now have a way to rotate our door properly.
03:50As an added benefit, we could go ahead and create another object, a sphere, scale
03:57it down to about the size of a doorknob, put it into position. We don't need two.
04:08But when we drag this into that same GameObject's group and select it again and
04:15click the Rotate tool, everything rotates together.
04:20This is a really important concept.
04:22Children inherit the Rotation, Transform, and Scale of their parent.
04:29To see this better, let's select the Cube. To get a better idea what's happening
04:34here if we select the Cube and in the Inspector make note of one of its position
04:41values, then move the parent,
04:50if we now go back and look at the Cube, you can see that that value hasn't
04:55changed, so its position is relative to its parent. And this is going to be
05:00an important concept when we get into animated objects, and especially
05:05imported animated objects.
05:07Let's test another of the GameObject's properties.
05:10With our parent GameObject here, in the Inspector, if we deactivate it, we get a
05:17dialog asking if we wish to deactivate all the child objects as well.
05:22We can choose to or not, and when we activate, we get the same dialog. And we'll
05:28choose Activate Children.
05:30When you're scripting though, all you have to do is deactivate the parent and
05:37all of the children automatically will be deactivated.
05:41Another cool thing about GameObjects is that they can be dynamically parented to
05:45different GameObjects at runtime through scripting.
05:48A ride on an elevator for instance with the First Person Controller will appear
05:53kind of jittery, but if we parented the First Person Controller to the elevator
05:58during the ride, it will be a smooth trip and the First Person Controller will
06:03still be able to move around.
06:05In the next video, we'll see how components can be added to turn GameObjects into
06:10specialized objects.
Collapse this transcript
Understanding components
00:00In the previous video, we saw that an empty GameObject could be used as a
00:04container to hold other GameObjects in a parent-child relationship.
00:09In this video, you will see what happens when we add components to the GameObject.
00:14In programming terms, a component is the base class for everything that can be
00:18attached to GameObjects.
00:21Let's take a look at few of our GameObjects to see what kind of components
00:24they already contain.
00:26Let's select the door object we created in the last video.
00:30It's under GameObject and it's called Cube.
00:33We didn't bother naming it door.
00:35In the Inspector, besides the features already present in the GameObject, such
00:40as transforms, we can see that it has three components:
00:44a Cube (Mesh Filter), a Box Collider, and a Mesh Renderer.
00:51The Cube component contains only mesh information.
00:55The Box Collider component, however, is one of the most important in the scene, as
01:00it prevents the player from going through an object or allows a player to go
01:04through but flags the intersection.
01:06And that's in case some event needs to be triggered.
01:09It's also necessary for triggering an OnMouseDown event.
01:13Try adjusting the size of the Box Collider.
01:16You can now see that the green bounding box represents the collider.
01:21So I'll just try changing his X and in the scene view, we can see it getting
01:26larger and smaller, and its Z, like so.
01:33The third component is the Mesh Renderer.
01:35It is responsible for rendering the mesh in the scene.
01:38It also tells Unity which material or materials are used on the mesh.
01:44Try disabling the Mesh Renderer.
01:48The cube disappears in the Scene view, but the Box Collider is still active.
01:53As you might guess, the player would still be blocked even though he
01:57couldn't see the cube.
01:58Now let's deactivate the Box Collider by clicking the box right next to its name.
02:05The bounding box still shows, but it's a dimmer version of the active green color.
02:10At this point, the object would no longer be detectable by the player, but
02:14since it is still active at the GameObject level, the game engine still has full access to it.
02:21And here is something else to remember:
02:23GameObjects are active when we check or uncheck, but components are enabled or disabled.
02:33These aren't just terms;
02:35these are parameters to be used in scripting.
02:38Let's look at a few more objects.
02:40From GameObjects > Create Other, let's create a point light.
02:44As you can see, it has a single light component, but that component has several
02:50parameters such as Type, Color, Range, and Intensity.
02:54Now let's create a spotlight in the scene.
02:57GameObject > Create Other > Spotlight.
03:02As you can see, it has the same light component, but its Type parameter is
03:08Spot rather than Point.
03:11Besides the components that make up the predefined objects in the GameObject
03:15menu, there are many more components that can be added to enhance an
03:19object's functionality.
03:20Open the Components menu and take a look at what's available.
03:25If the submenus are grayed out, you'll need to select an object first.
03:29Note that scripts are also components.
03:32Anything that contributes to the creation and functionality of a GameObject can
03:37be found under Components.
03:39Just for fun, choose any component to add to your object.
03:45I added a skinned cloth and that was probably a mistake.
03:49If I scroll down in the Inspector, I discover not only did it add a Skinned
03:54Cloth component, but it added a Skinned Mesh Renderer as well.
03:58I need to remove both of them.
04:00You can remove a component by right- clicking over its name and saying Remove
04:05Component. And then I'll go ahead and remove this one as well.
04:11Now let's select the Spotlight and remove its Light component.
04:16Right-click over the label and Remove Component.
04:19It leaves you with--wait for it--an empty GameObject.
04:25So all of those Create Other objects are just GameObjects with
04:30components already added.
04:33In the rest of this chapter, we will be examining several of the important
04:36components in depth so we can add to the functionality and interactivity of our little game.
04:42Go ahead and delete the door group and extra lights from the scene.
04:45I'll do that by selecting the Spotlight, right-clicking, and clicking Delete.
04:51I can also click on the parent object and press Delete on my keyboard.
04:57And one more to get rid of: Point Light. Right-click, Delete as well.
Collapse this transcript
Using colliders for barriers
00:00By now you've had a few run-ins with colliders--literally.
00:03Colliders are the components of mesh objects that prevent you from
00:07going through things, but they have other functions as well.
00:10Let's start by looking at the different kinds of colliders available.
00:14From the Component menu > Physics, we've got Box, Sphere, Capsule, Mesh,
00:21Wheel, and Terrain.
00:23Wheel and Terrain are specialty colliders that we won't be covering.
00:28The Mesh collider uses the object's own mesh to check for collision, and is the
00:33highest resource user of the regular colliders.
00:36When we import objects and check generate colliders, that's what gets created.
00:42Let's select and focus on the Entry Stair object.
00:47It's in the Structures for Scene group, under Building Group > Entry Stair.
00:55Double-click it and then you can use your Alt and left mouse to get a better view of it.
01:01I'll just zoom in a little bit with my middle-mouse roller and adjust it.
01:08The Entry Stair object has a Mesh Collider.
01:11Mesh Collider calculates collision off of every face.
01:15The Mesh Collider does have an option to recalculate the Mesh Collider to be
01:19convex, which is much more economical.
01:22That is, when it can come up with a good solution, and sometimes it can't.
01:26Let's try that out with the stair.
01:28Here's our Convex option, and let's click it.
01:32In this case, it worked quite well.
01:35Let's set it back to normal.
01:37The Mesh Collider also has a polygon limit, so don't be surprised if an imported
01:42mesh's collider fails.
01:44Remember also that only one object in an intersection or collision test can be a mesh collider.
01:50The exception is if at least one is marked as Convex.
01:55So what do you do with the mesh that's too complicated?
01:58The answer is multiple colliders.
02:00You can have one of each kind of collider on an object, but they can be
02:04tricky to position.
02:06A better solution is to add empty GameObjects to the main object and
02:10put colliders on those.
02:12They can be transformed into position using the GameObject, but you will need to
02:16use their own scale transforms to adjust them.
02:20Let's import the Fountains package from the Assets menu > Import Package >
02:27Custom Package, and we'll find that in the exercise files for this video: Ch06/06-03/Assets.
02:40And there it is, the Fountain package, and Open.
02:46Import. And if we check our Project view, under Imported Assets, we'll see our new prefab.
02:58In the Scene view, let's toggle to the top view, clicking on the Y component
03:05of the scene gizmo. and zoom out, and then we'll move our view to the center of the nature area.
03:17Now we can drag our Fountain prefab into the very center spot.
03:25Let's get a closer look at our fountain by double-clicking to focus on it.
03:29And then holding the Alt key, we can rotate the view and zoom in with the middle-
03:36mouse button until we see what we've got.
03:41If we look at the various components of the fountain, besides the Bobbles,
03:47Brace, none of these objects have colliders yet.
03:52For the Fountain Base, because we want our first person controller to be able to
03:56navigate it, we need to add from Component > Physics > a Mesh Collider.
04:04For the Frufra piece, we're going to add a Box Collider, and we'll need to adjust
04:12its Size in the Inspector by adjusting its X, Y, and Z parameters.
04:18This effectively is going to block the first person controller from going
04:21through it without the high overhead of a Mesh Collider.
04:25We've already seen the Capsule Collider in action.
04:28The first person controller's Capsule Collider is built into its character
04:32controller script, but it allows for very economical collision testing.
04:37Capsule Colliders are also the only controller types allowed on trees for the
04:41Terrain Editor library.
04:43Remember that big tree that we used in the central area?
04:47Right now we can drive right through it.
04:49Let's select the BigTree in the Project view and check it out.
04:53He is up at the top here. And if we close his Tree component, we can see that
05:00he has no collider.
05:02Let's focus in on him, use Alt to swing the view around, and then zoom in. There we go!
05:15Now we can see him. And we'll go ahead and add a Capsule Collider to the tree
05:21from Component > Physics > Capsule Collider.
05:27Now the problem is that it's scaled pretty much to the size of the tree.
05:32So the first thing we need to do is change its Radius, and I'm going to use that
05:38by clicking and dragging next to the field. And you can see it's a little bit off center here,
05:44so we're also going to need to adjust the center to bring it into position on
05:51the X and the Z. I'm going to leave it as is.
05:59It would be easier to do from a top view.
06:02Once we've got it how we like it, then we'll need to update the prefab in the Project view.
06:10We could do that by dragging the original BigTree onto the prefab, or in the
06:17Inspector, we can click Apply, and that will update the prefab for us.
06:24When we've used it in the Terrain Editor, we also need to remember to go to the
06:28Terrain menu > Refresh Tree and Detail Prototypes.
06:35If we were to click lay and test, not only would we find out we couldn't go
06:40through the trees, but we'd also find out that our cannonballs bounced off them as well.
06:45And finally, one of the more interesting and sometimes useful things is that the
06:50Mesh Collider on a plain object is single-sided.
06:54If you were to rotate it vertically, you would be able to find that you could go
06:59through it on the back side but not the front side.
07:02And that could make for some interesting traps.
07:05Anyway, bottom line on colliders is, use the simplest colliders for the best
07:10efficiency, and use all colliders sparingly.
07:15
Collapse this transcript
Using colliders for triggers
00:01The next bit of collider goodness we'll look into is the Is Trigger parameter.
00:05It turns out you need a collider to be able to detect a collision of any kind,
00:10and that includes ray casting, by the way. Plus, one of the colliding objects
00:15must have a rigid body.
00:16Character controllers have a special kind of rigid body, so we are good to go.
00:20So how do you allow the player to go through something while still triggering an intersection?
00:25The answer is the Is Trigger parameter.
00:28When checked, it allows objects to go through it, but it can still be detected.
00:34To see how this works, let's select the Barricade Mid. In the Structures for
00:38Scenes > Barrier 2, we'll select the Barricade Mid.
00:44In the Inspector, in the Mesh Collider, we are going to check Is Trigger.
00:52Now we can click play and see about driving through the barricade.
00:56With my W key, I head over and sure enough, I can get through it.
01:03I'm going to hit my Escape key to disable navigation, so I can get out of Play mode.
01:08Now we'll need to create a new script to trigger something.
01:12So in the Practice Scripts folder--and I'm going to close my Standard Assets
01:17folder while I'm there--right-click on the Practice Scripts folder, Create >
01:23Javascript, and we'll name our new script TriggerTest.
01:28And we'll go ahead and open it in the Script Editor.
01:33Because we are going through the object now, we need to use OnTriggerEnter
01:39instead of OnCollisionEnter, but it works pretty much the same way.
01:43I am going to grab the code from the snippets file for this one.
01:46And we want this for a section, the OnTriggerEnter function. Ctrl+C to copy.
01:55I'll tab back to my Script Editor, and it looks like I need to make sure I'm in
02:01the TriggerTest. And then I'll add my new script after the Update function, and
02:08use Ctrl+V to paste.
02:11Okay, let's save this guy, get back into the editor, and now we need to drag our
02:19TriggerTest script onto Barricade Mid.
02:24Before we click play, there's something else we should think about. Our Solid
02:29Door already has a rigid body on it, and it's probably intersecting with the wall,
02:36so don't be surprised to see our first message detect the Solid Door.
02:42Now we'll go ahead and click play.
02:45And sure enough, our script has detected the Solid Door. And I'm going to go ahead
02:50and hit W and go through the wall.
02:53And now you see it senses the presence of First Person Controller.
02:57So everything works. Let's click Escape and get out of Play mode.
03:01Let's go back into the Script Editor again and this time we'll add
03:05OnTriggerEnter's counter part, OnTriggerExit.
03:08We can do that easily by copying the OnTriggerEnter function with Ctrl+C and
03:16pasting it right below.
03:18And we need to change Enter to Exit, and we can add something else for our
03:25message, like "I sense an emptiness," and don't forget quotation marks, and then we'll save.
03:35Now back in the editor, when we click play, as soon as we exit the wall, we'll
03:43get the last message.
03:45So W, First Person Controller, and as I leave, I sense an emptiness.
03:52Escape and we'll quit Play mode and there we have it.
03:56So this gives us a non-directional means of triggering events such as doors,
04:02power-ups, disembodied voices, just about anything you can think of.
04:07At its simplest, a collider can be the only thing on a GameObject, but if we
04:12wanted to do something more interesting, at its simplest, a collider can be the
04:17only thing on a GameObject.
04:19If we wanted to open and shut doors in the first barricade like a Star Trek
04:23door, we could use an empty game object with just a large box collider.
Collapse this transcript
Exploring physics
00:00We've seen the class of Box Test with physics and used physics to fire our
00:05cannonball and drop the solid door, but there is a lot more we can do with it.
00:09Unity's physics engine is based on NVIDIA's PhysX Engine, and has all kinds of
00:13cool stuff like joints, springs, and motors, not to mention constant forces.
00:19Let's switch over to our Scripting Test scene. We'll double-click it and then we
00:24want to go ahead and activate the Sphere. It was turned off.
00:28So I'm going to click on it and up at the top of the Inspector we'll click to
00:33activate it. And we can go ahead and double-click on it to focus it in the Scene
00:38View. And then, since we're going to drop it, we'll need to add from Component >
00:46Physics > Rigidbody.
00:48I'm going to zoom back a bit to see where it is, and it looks like it's nowhere
00:53near the rest of our stuff, so I'm going to click the Y marker on the scene
00:59gizmo. And I'm zooming out and I'm still not finding it,
01:03so I'm going to double-click on the Cube, select the Sphere, and use, from
01:13GameObject, Move To View.
01:18Switch back to Perspective, and now zooming out, we've found our Sphere again.
01:26So let's go ahead and click play and watch it drop to the ground.
01:32Something is missing here.
01:34We expect the cube to hit with a plop, but we kind of expect the Sphere to
01:39bounce, at least a little. For that we need to assign a physics material, and
01:45that's done in the Collider component.
01:48Let's go ahead and exit Play and then look into doing that.
01:53In the Sphere Collider we see Material, and it says None. If we click on the
01:58shortcut to the browser, we find that there are no physic materials listed.
02:02Let's close it and it turns out, we need to go to Assets > Import Package and
02:10import the Physics Materials package. Import.
02:14Now when we click on the Browser button, we have a whole bunch.
02:20Let's start with Bouncy and click play.
02:27Now we can see our sphere bouncing up and down.
02:31If we watch it, it seems to be gaining energy with each bounce. We'll need some air friction.
02:36In the Inspector, in the Rigidbody, that's Drag. And we can click and drag next
02:45to the field to increase it.
02:47Now you can see our Sphere slowing down and even to a stop.
02:52That's a good time to exit Play mode.
02:54The physics materials have parameters that you can adjust, but if you want
02:58to adjust something, you should duplicate an existing one with Ctrl+D and
03:03then tweak that one.
03:04The next thing we want to look at in physics is the Is Kinematic option on the Rigidbody.
03:10The name doesn't exactly give us a hint, but this one is extremely important, for
03:14a couple of reasons.
03:15When this is checked, physics are not used on the object.
03:19Okay, I know that sounds kind of funky. Why put a Rigidbody on something if you
03:24aren't going to use it?
03:25It turns out that if an object has a collider, physics are working on it anyway,
03:30just like the original cube and the plane.
03:33As long as the object with the collider is static, or not moving, there is no
03:37problem. But as soon as we transform it, through scripting or physics, the
03:43physics engine is forced to recalculate, and that sucks up resources.
03:49If we wanted to have something like a windmill turning slowly throughout the
03:52game, we would add a Rigidbody and set it to Is Kinematic.
03:58Another important use for Is Kinematic is so we can anchor objects using joints.
04:03We'll test this next.
04:05Select the cube and we'll bring it down within range in the Game view, and then
04:10we're going to clone it. So Ctrl+D clones the cube, and we're going to rename the
04:16new one Board. And since it's a board, we need to move it aside and use our Scale
04:29to flatten it a bit.
04:31Now we may as well move it over to the side we can see in the Game view. And it
04:38looks like right there would be good.
04:43Before we go adding the Hinge Joint component, think about where the
04:47object's pivot point is.
04:48It's in the center, right?
04:50We want this board to hinge from the edge of the cube, so we're going to need to
04:55add an empty GameObject to that spot.
04:57To do that, I'm going to focus on the board from GameObject > Create Empty, and
05:06we'll name this one board parent.
05:09We'll adjust its position so it's at the edge of the other cube, and drag our
05:19board down that far, and now reselecting the board parent, we can see that it's
05:26going to look about right.
05:27So now I'm going to drag my board into the board parent to create a hierarchy.
05:35Now we're going to add a Rigidbody to the GameObject, named board parent, and
05:42then we'll remove the Rigidbody from the board, the child.
05:46According to the docs, you should never have a parent and child
05:50Rigidbody together.
05:52So first, for our board parent, we're going to add Physics > Rigidbody, and then
05:58for board, the child, we're going to right-click and remove the component.
06:04Now we'll add the Hinge Joint component to the board parent.
06:08First we need to select the board parent. Then from Component > Physics, we're
06:15going to select Hinge Joint.
06:19It's got a bunch of parameters, but the only one to worry about here is the axes.
06:24We need to set them to 0 over in the Inspector, and then we need to make sure
06:32that we're choosing the right one.
06:34In this case I'm okay.
06:35It looks like X is the axis we want to rotate from.
06:38So we'll click play and test.
06:45Like the Sphere, it looks like it's going to swing forever,
06:48so we could add a bit of drag if we wanted.
06:50Let's exit Play mode first.
06:53If the object is not going to be moving aside, from the hinge, it can be parented
06:57to the world by leaving the connected body set to None, as we have it now.
07:03If you wanted to connect the board parent to the cube, you could drag the cube
07:08into the Hinge Joint's Connected Body field.
07:11We won't be doing that now, but feel free to try it on your own.
Collapse this transcript
Working with physics components
00:00So what if you wanted a sign outside an old inn to swing in the wind during the whole game?
00:05First off, you'd probably only have it swing when the player was around to see it.
00:11You already know a few ways to do that.
00:13Assuming we'd eventually make it dependent on the player's presence, we would
00:17still need to know how to keep it swinging, and that's where physics--the
00:21Constant Force component--comes into play.
00:24Let's add one to our board parent.
00:26That's where all the action is.
00:27Remember, the board is just going along for the ride.
00:30So we will select our board parent, go to Component > Physics, and way down at
00:37the bottom, we will find Constant Force.
00:43In the Inspector, we can see that we've got Force and Relative Force.
00:48The first is global coordinates.
00:51So if you had a bunch of physics objects that were going to be affected by
00:54wind, you'd use this one.
00:56Relative would be useful for pushing an object the direction it was facing.
01:00We're going to use Force. Let's open it up.
01:04If I check my scene gizmo, it looks like I need to use the Z direction.
01:08Positive values go one direction and negative ones go the opposite.
01:13In our Scene view, our Z is on the right-hand side, but we need our wind to blow to the left,
01:20so we're going to need to use a negative value in our Z parameter.
01:25So back in the Inspector, in the Constant Force component, I'm going to type in a -1.
01:33Before we hit play, let's go ahead and fix one thing. Our cube falls,
01:38so in the Inspector, in the Rigidbody, let's tell that guy to be Is Kinematic.
01:44Now we are ready to click play and check on our wind.
01:47So let's select our board parent again and expose the Constant Force parameters
01:53in the Inspector and hit Play.
01:59Now you can see our board swinging.
02:02You might want to try increasing the force to see what reaction we get.
02:07Okay, let's go ahead and exit play mode.
02:11The next parameter in the Constant Force is Torque.
02:14Torque is rotation.
02:16We're going to go ahead and add a Constant Force to the original cube, Cube1, and
02:21we'll try Torque on it. So Component > Physics > Constant Force.
02:30This time we didn't add a Rigidbody first, but because we added Constant Force,
02:38one was added for us.
02:40And let's set the Torque, the Y parameter-- since that's up in the world--to about 50.
02:49Now there's one more thing we need to know. According to the docs, never have
02:54transforms and physics controlling an object at the same time.
02:59That means we need to disable the rotation script on this cube before we test.
03:04And we can just turn it off or we could right-click and say Remove Component.
03:11Now we'll click play, and the original cube is happily rotating.
03:20If we left it going for a while, it might wander off the board,
03:24so we're going to try something else.
03:27Exit play and to keep him from leaving town, we need to go up to his Rigidbody,
03:35open Constraints, and now we can freeze his position to keep him from going
03:42anywhere but spinning around.
03:45In case you're wondering, when a character is turned into a rag doll, all the
03:50objects were animated by keyframe animation and they already had Rigidbodies set
03:55to Is Kinematic. They're unchecked dynamically and the keyframe animation turned
04:00off to allow the character to tumble into a heap of bones.
04:04Okay, since they're pretty important, let's do a little recap on physics rules.
04:09Number one: objects that have colliders and are transformed by other than
04:13physics need to have a Rigidbody with Is Kinematic checked.
04:18Two: don't mix active physics and transforms at the same time.
04:24Three: don't have parent and child Rigidbodies together and use joints to
04:29create hierarchies.
04:31And four: never scale the parent of a Rigidbody. Remember, children inherit the
04:36transforms of their parents.
Collapse this transcript
Making cloth
00:00Cloth is incredibly easy to make in Unity, but it also uses a lot of resources,
00:05so use it sparingly.
00:07From the GameObject menu, let's select Create Other > Cloth.
00:14It starts out rather large, so let's zoom out using my middle-mouse roller here,
00:19move it up a little bit, and use Scale to bring it down.
00:27Let's start out by moving it up above the sphere.
00:33And I'm going to rotate my window to make sure I am up above the sphere, and it
00:38is. And now we can click play.
00:47The Sphere and Cloth drop and the Cloth eventually slides off, so we can
00:52exit Play mode now.
00:53Okay, everyone has seen the Cloth-Sphere test a million times.
00:59It's quick to calculate, and it looks impressive.
01:02Let's try moving the Cloth over the top of Cube1 and click play again.
01:07Cube1 is our original cube sitting on the ground. And that should do it. We'll
01:13click play again, and you can see it's also reacting to a moving object.
01:25Okay, let's exit Play mode again.
01:28I always figured the test is to see how easy it is to attach a Cloth object to
01:32something. Anyone can drop it.
01:35Turns out, it's pretty easy. Let's save the scene and get back into the main level.
01:40File > Save Scene. And then we'll locate our MainLevel scene and double-click it.
01:49Let's select and focus in on the fountain object, specifically the Fountain
01:57Cloth. And you'll want to rotate the viewport a little using your Alt button.
02:03And now let's create a Cloth object and then we'll set and position it to match the
02:08original one hanging there.
02:10GameObject > Create Other > Cloth. And we'll need to rotate it and then shrink
02:24it. And maybe I'll do a little bit of Scale on my X axis, and then I'm going to drop it down.
02:39So I want to leave it pretty much in the place that the original imported Cloth
02:43mesh was. Note that that's just a mesh. It's not cloth.
02:47So let's go ahead and, in the Fountain, select the Fountain Cloth and deactivate it.
02:56I'm going to spin my view a little bit more again.
02:59I'm getting tired of seeing the crosshairs, so I'm also going to toggle off the
03:03Overlays button. And now we have to see how we go about hanging the cloth.
03:09At the bottom of the Interactive Cloth component, over in the Inspector, when we
03:14select the Interactive Cloth, you'll find something called Attached Colliders.
03:20If we open it up, we're going to see something a bit odd.
03:23The variable on this guy is an array. We'll get to work with arrays later on,
03:28but for now all you need to know is that they can have as many elements as we
03:32need. We just need to tell it how many we want.
03:35For this example we're going to need three, so set the Size to 3, and now we can
03:45see we have three elements.
03:47Let's open Element 0. Arrays, by the way, start counting at 0, not 1.
03:52And it looks like we're going to need a Collider,
03:55so next we'll need to add some box colliders to three of the bobbles that are
04:00sitting on our fountain:
04:02this one, this one, and that one. And those are Bobbles014, 015, and 016.
04:10So select Bobble014 and from Component, we're going to add Physics > Box
04:18Collider. And you might want to zoom in a little bit closer here. And the trick
04:23here is that we need that Collider to intersect with the Cloth.
04:29So in the Inspector, under the Box Collider, I'm going to change its center by
04:35adjusting its Y position. And I'll just drop it down so I'm sure that it
04:40intersects, as we can see over here. And we need to do that for 15.
04:46Component > Physics > Box Collider, and adjust its Y. In this case we
04:54probably need to adjust its X, make sure it intersects the cloth. And the same for Bobble016:
05:02Component > Physics > Box Collider.
05:07And there again we're going to need to adjust its X until we're sure that it's intersecting.
05:13Now, switch back to our Interactive Cloth and we'll scroll down to where we can
05:19see our elements for our attached colliders. And I'm going to go ahead and open
05:23up Element 1 and 2 as well.
05:27And now we just need to drag Bobble014 into the Collider field in Element 0, 15
05:37into the Collider field in Element 1, and 16 into the field in Element 2.
05:45And that's all there is to it. If we click play, we see our Cloth settled.
05:50Let's exit Play mode and think about what we can do to make it more interesting.
05:56So you're probably wondering about wind.
05:59It turns out the Cloth Component has it built in.
06:02If we select the Cloth and look up farther in the parameters, we will find
06:10External Acceleration.
06:14In this case, I'm looking at my Scene gizmo and I'm looking at my Cloth gizmo,
06:19External Acceleration doesn't tell us whether it's global or local.
06:24So let's try turning on the wind on our Y parameter and see what's happening.
06:31I'm going to try a value of about 50.
06:33It's probably overkill, but at least we'll see if something happens. And we can
06:39click play and there we go. It looks like that proves that Y is using world.
06:48So I'm going to exit Play and instead of 50 in the Y, maybe I'll try 10 in the
06:58Z. Here is our Z and let's see what happens. Click play and there it goes; we've got wind.
07:09Let's go ahead and exit Play mode.
07:12Unlike the Rigidbody animations, wind also has a parameter for Random
07:18Acceleration. You might want to try this one on your own.
07:21So there is one other little issue. If we use the default Cloth mesh, it's only
07:27one-sided. If I hold my Alt key down and spin it around, you can see, well, that
07:32we look right through it.
07:35For a material, we could use one of the particle shaders since they are all
07:39two-sided. And there are a few other shaders that do two-sided, but most aren't.
07:43I'll show you how to convert a few simple shaders later on in the course.
07:48One last thing we can try with this guy: let's add a material to the Cloth and
07:52see if we can find a shader that uses two-sided.
07:55I'm going to open my Materials folder and see if I can find anything that looks promising.
08:00I have a feeling that this one might, so let's click on it. And it has a Shader.
08:06It's using one of the particle shaders, so this one should work.
08:10We can drag and drop it straight onto the object in the viewport, and now, if
08:17we spin this around, we can see that we've got a material on both sides.
08:23The last thing we can try with our Interactive Cloth is instead of using the
08:28rectangular default Cloth mesh, we can actually use our own mesh.
08:33So I'm going to select my Interactive Cloth again and in its mesh parameter over
08:40here on the Inspector, instead of Plane, I'm going to hit the browser and I'm
08:46going to go looking for our Fountain Cloth. And we'll select it, and since we
08:55can't see it, let's use our Alt key to look around the viewport.
09:02Oh, we are seeing it.
09:04It's just small. So we can go ahead and scale it up and then move it up.
09:12It may need a little more scaling, because it too is going to have to intersect the
09:19colliders. And we should probably double-check those.
09:24I'll click on this bobble.
09:25I think that was Bobble016. It might make it.
09:31It will take a little adjusting to make sure the Cloth mesh intersects with the colliders,
09:34but in the end it will work just like the regular Cloth object.
09:39And finally, if you want to use Cloth on characters or other skinned mesh
09:44objects, you should use physics skin Cloth instead. It's much more economical
09:49since it doesn't offer so many choices.
09:52As you can see, Unity offers several good options for Cloth.
Collapse this transcript
Working with wind zones
00:00As you've probably figured out by now, adding wind in Unity is pretty much a
00:04painful per-object affair.
00:06The only exception is adding wind to trees. Okay, not quite.
00:12And the reason is that non-physics- related wind is done with shaders, the things
00:17that make up Unity materials.
00:19Odd as it may seem, shaders can displace vertices, so the nature shaders can
00:24make your trees bend and sway, the water shaders can add waves to your water,
00:29and other shaders can cause other useful effects if you know how to write them.
00:34To activate the bend parameters on trees, we need to use a Wind Zone.
00:39The Wind Zone object allows you to affect terrain trees as well as custom trees
00:44all at once, or within localized areas when you use a different mode.
00:49We're already at the center of the nature area, so let's focus in on the Fountain.
00:55From GameObject > Create Other, we're going to select Wind Zone.
01:03It's come in at 0, 0, 0, as we can see in the Inspector.
01:07So let's go ahead and use GameObject > Move To View.
01:13Now we can see it near the fountain.
01:15I'm going to move it up a little bit. And you can see that the default mode on
01:21the Inspector is Directional.
01:24Let's go ahead and click play and try it out.
01:29In the Inspector, if I click Escape to get my cursor, we can try changing the
01:36Wind Turbulence and any of the other parameters.
01:42Let's exit play mode.
01:45Under mode, we can also use Spherical.
01:51If we click play and Escape to keep our cursor, we can drag this guy back and
01:58forth over our trees and cause a helicopter-type effect.
02:03Okay, let's exit Play mode again.
02:06Let's go ahead and set our mode back to Directional and we'll look at the next topic.
02:14So, how do we control the actual bend on the trees?
02:17Well, that depends on the shader used on the tree.
02:21For the BigTree we added to the Terrain library, changing the bend parameter has
02:26absolutely no effect.
02:27Feel free to try that out on your own.
02:30Meanwhile, let's go ahead and select the Terrain and head over to the Inspector.
02:36I've noticed we're missing the palm tree.
02:38That means we need to reload the Terrain assets.
02:42So I'm going to go back up to Assets > Import Package, and we'll reimport the
02:49Terrain Assets package.
02:53Click on Import and now we can go to Place Trees > Edit Trees > Add Tree, and
03:06we'll add our palm tree.
03:10I'm going to leave the Bend Factor to 0 and see what we get.
03:15So let's click Add.
03:17Now we can select our Palm tree, paint a few and click play.
03:26Without Bend, they're not moving in the wind.
03:29So let's exit play, go back to the Inspector, select the Palm and Edit Trees--we
03:37want to edit them--and this time we'll set their Bend Factor to about 3.
03:44We'll click Apply, and now when we click play, they're shaking right along with
03:51the rest of the trees. Okay, that's good.
03:56Let's exit Play mode, and since we probably don't need palms here, I'm going to
04:01zoom out a bit, select my Palm tree, and, holding Ctrl, we'll remove only the palm trees.
04:15You may need to zoom in a little closer to make sure you get them all. And I'm
04:21going to zoom out and rotate my view just to make sure. And I think they're all gone now.
04:30So let's deselect the Terrain and now let's go up and look at BigTree.
04:34I'm going to focus in on it by double- clicking and then I'm going to rotate
04:40the view and see if I can get a little closer. And that's probably about as
04:45good as we can get.
04:46So what's the deal with the BigTree?
04:49Why doesn't the Bend parameter affect it?
04:52Well, it was created with the tree generator, and it uses a material that uses
04:57a different shader.
04:58Let's select the BigTree and in the Inspector, we'll need to open the Tree
05:04component. And if we click on one of the nodes and scroll down, we can see that
05:13it has its own Wind parameters.
05:16In this case, we have Main Wind and Main Turbulence.
05:21On each node of the Tree hierarchy, you will see a Wind setting.
05:25On the Leaf nodes, you will also get a Main Turbulence and an Edge Turbulence.
05:31If we select one of those, we will be able to see that.
05:36Scrolling down, this one has Main Wind, Main Turbulence, and Edge Turbulence.
05:45Whatever these settings are, the Wind Zone controls them overall.
05:49Main Wind will control how far the tree bends in the wind direction and its
05:54other two, in this case the randomness and the amount of frequency.
05:58Now as long as we're here, let's fix another niggling problem: the dynamic
06:03shadow's lack of respect for texture opacity.
06:06This is a shader issue.
06:08So we're going to fix this by selecting the left leaf node and under its
06:16Material parameter, we're just going to click once to locate the original
06:22material. Then we want to drag BigTree_leaves into this one, and notice that
06:30BigTree_leaves has an underscore. And we'll do the same for the other leaf node.
06:39This node uses BigTree_branches, so we're going to take the BigTree_branches
06:45and load it in there.
06:47Now, if we look closely in our Scene view, we can see that we're now seeing
06:52actual leaves from BigTree,
06:56but we aren't seeing them yet in the Game window because the rest of the trees
07:01were painted with the Terrain Editor.
07:04To update them, we need to go to Terrain > Refresh Tree and Detail Prototypes.
07:12And now, at least in the Scene View, we can see that they've been updated.
07:16We have a message from the Console, but I suspect that one is left over from pre-
07:22tree-generator days, so I'm just going to clear it.
07:26We won't see it again.
07:28And I'll close the Console.
07:29Now notice that even our trees in the Game view have been updated as well.
07:35So our takeaways on Wind Zones are tree creator trees need the wind settings
07:41adjusted in the individual tree node; regular trees used in the Terrain library
07:47are adjusted using the Bend settings.
Collapse this transcript
Using an audio source
00:00About now you're probably thinking a few sound effects would go a long way
00:04towards making our game more engaging.
00:07Before we can have any sound in a scene, we must have an audio listener
00:10component, and only one.
00:13This should sound familiar. Cameras have one by default, and we've already had to remove a few.
00:18To hear sound we need to add audio source components, but first we'll need to
00:23import some sound files.
00:25Let's go out to the exercise folders and drag the Game Sounds folder into the
00:31Unity Sampler Assets folder.
00:34In Ch06/06-09, from the Assets folder--and these are the exercise assets--
00:42we're going to right-click and Copy the entire Game Sounds folder. And then in
00:51the UnitySampler folder, our project, we're going to click on that Assets
00:58folder, right-click, and Paste.
01:03Now we can return to Unity and if we check our project view, we should find them.
01:12I'm going to close everything else first. And there it is, Game Sounds.
01:17Let's open it, and now we've got lots of things to play with.
01:21Unity can handle several audio file types:
01:24AIF, WAV, MP3, and OGG.
01:29You will need to decide on how it stores and plays them, and that will
01:34probably depend on length.
01:36When you let Unity compress the files it uses the Ogg Vorbis compression for Mac
01:42and PC and MP3 for mobile.
01:45Let's see how this works.
01:47Select the Birds1 sound in the Game Sounds folder.
01:52In the Inspector, we can either click Play down in the Preview,
01:56(birds chirping)
02:00or we can turn on Auto Play, so that whenever we click the file, sounds will play.
02:06(sound effects)
02:10sounds will play. I'll be turning Auto Play off. (sound effects)
02:14Most of the sounds in the new folder are already Ogg Vorbis, but the last one,
02:24Warning, is a WAV file.
02:28So under Format it shows as Native. Very short sound effects can be left as
02:33native and should be set to Load into memory.
02:36This one shows a 6.2K disk size, so it's pretty small.
02:41If we change the Compression to Ogg Vorbis, under Audio Format, and click
02:50Apply, the new file size is now 4.2K. And now you have the option to keep it
03:00compressed in memory.
03:01Larger files such as background sound and music should usually be treated this way.
03:06Unity also offers a streaming option, and it's well covered in the docks.
03:10Anyway, our file here is just a little bitty thing, so let's change it back to
03:14Native. Don't forget to hit Apply.
03:17In Unity, sound is set to 3D by default.
03:21That means that when we add a sound to the scene, it is directional and distance-based.
03:26Let's select the WindZone object in the Hierarchy and add an audio
03:30source component to it.
03:33WindZone, Component, and under Audio, we're going to add an Audio Source.
03:41Now zoom back a little bit, so we can see our WindZone.
03:46I'm going to rotate the view just to remind you that the WindZone is already
03:50centrally located in the nature area.
03:52And now let's drag the LightWind sound clip into the Audio Source.
04:01The first thing we notice is that it's set to Play On Awake. Directly beneath
04:07that is Loop. We'll need that one too.
04:10Now let's click play and drive towards the center of the nature area.
04:20As we drive closer to the center, we expect to hear some sound, but I'm
04:26hearing very little.
04:28Let's exit Play and see was what's going on here.
04:32So there are a few things that are happening here.
04:34Let's open up our Sound settings first.
04:38So the Max Distance is set to 500. Our little nature area is only about 200
04:43meters, so that should be okay.
04:46But here's the clincher: if we look at the Listener curve in the little graph,
04:50we can see that the falloff is pretty severe.
04:54Up in the Volume Rolloff, we can see that it's set to Logarithmic Rolloff.
04:59Let's set it to Linear.
05:01Now the curve has an even Rolloff and we should be hearing our sound a lot
05:06louder, a lot sooner.
05:08Let's click play and try it. (sound effects)
05:17And sure enough, we get a much better effect. (sound effects)
05:25So we can hit Escape and get out of Play mode again.
05:28Now here's a tip: if your sound file was already stereo, you'll want to turn the
05:34Spread--and we can find that right here--all the way up.
05:39Spread combines both channels so that they can react properly in the 3D environment.
05:44Feel free also to adjust the Min Distance and Max Distance to improve the Rolloff.
05:50If you were to click play now, at the gate we should hear nothing, but it should
05:55be loud at the center.
05:57If you want, you can even try your hand at a custom rolloff.
06:00In the Listener curve, you can right- click to add a key, and you can adjust to
06:07make a Custom curve.
06:09In the next video, we'll be creating a stand-alone sound zone.
Collapse this transcript
Creating a sound zone
00:00In this video, we'll start seeing how to control our audio through scripting.
00:05Since our nature section is a foresty sort of area, we might like to add
00:09some bird sounds too.
00:11But you can only have one Audio Source component on an object.
00:15We could get around that by adding an empty GameObject to the WindZone and then
00:19giving it an audio source of its own.
00:22For now though, let's just reuse the audio source we've already got.
00:26Let's start by selecting our WindZone and from the Game Sounds folder, let's
00:31drag Birds1 into the audio clip.
00:35Make sure it's set to Loop. And then I want to set the Custom Rolloff so I get a steep exit.
00:44I'll click on the existing node, and I can move its handle up.
00:49I want to get rid of this node, so I can click on him and then right-click
00:54and say Delete Key.
00:56Then I might need to adjust this one a little bit more. We're good to go.
01:02If we clicked play and test it at this point, we would be able to hear birds
01:06all the way out into the other sections, but it isn't the right mood for the
01:10other areas, so we're going to write a script to turn the whole audio component off and on.
01:16To make easy, we can use a collider to trigger on enter and exit.
01:22Let's start by adding a Box Collider to the WindZone.
01:25With the WindZone selected, we're going to go to Component > Physics > Box Collider.
01:33Now in the Inspector, the first thing we need to do is set it to Is Trigger.
01:39That will allow us to drive through it.
01:41Then I'm going to adjust my Scene view for a better top view, and now I'm going
01:48to adjust the size by dragging on the X and dragging on the Z until my Collider
01:58fits the area better.
01:59We may need to adjust the center as well.
02:04And the last important part is to rotate the view and make sure that the
02:11Collider is going to be low enough for our First Person Controller to interact
02:16with, and for that we need to change the Y size.
02:22Now in the Game Scripts folder right-click and create a new JavaScript.
02:30We'll name it SoundZoneController, and we'll open it in the Script Editor by
02:36double-clicking on it.
02:38To start, this one is going to be very simple.
02:40We just need to turn the Audio Component off and on on enter and exit.
02:45So we'll need to make an OnTriggerEnter and an OnTriggerExit function.
02:50I'm going to tab out to the Exercise folders and copy the code.
02:54Ch06/06-10/06-10Code_Snippets. And we're going to take the whole top section.
03:06Copy, tab over and since these are functions, we're going to add them underneath
03:13the existing functions.
03:15Paste and we've got our new OnTriggerEnter and OnTriggerExit.
03:19Now we are going to be enabling and disabling the Audio Source component.
03:26You may think we need to use audio source.enabled, but this is one of the ones
03:31that we have a shortcut for,
03:33so we only use audio.enabled.
03:36Let's go ahead and save our script and get back to the Editor.
03:41Now we need to drag our SoundZoneController onto the WindZone, but before we
03:47click play, let's try one more thing.
03:50Let's select the WindZone and adjust the Inspector so we'll be able to watch the
03:58audio source turn off and on as we go in and out of the Collider. We'll click play.
04:05(sound effects)
04:09It was set to Play On Awake, so it's already playing, but now I'll drive forward
04:14with W and backward with S and the audio source turns off.
04:22If I go Forward again, it turns on, but we're not hearing the audio anymore.
04:29So there's one more thing we need to do to our script to fix it.
04:33I'm going to hit Escape and then I'll get out and Play mode and return to the Script Editor.
04:41It turns out we need one more little line here, and that one is audio.Play() and the
04:57semicolon to end the line.
04:59Now we can save our script and get back to the editor.
05:04This time when we click play, drive into the zone, drive out with the S key, and
05:14drive back in, our birds play again.
05:22Let's hit Escape and exit Play mode.
05:28So there you have it. We'll deal with one-off sound effects in the next video.
Collapse this transcript
Adding audio effects
00:00Now that we've had an introduction to audio, let's add some sound effects
00:04to specific objects.
00:06Our cannonball is a prime candidate.
00:08Let's start by adding sound when it's fired off.
00:11For this we need to add an audio source to the Proxy Weapon. So let's elect
00:16our First Person Controller, Main Camera > Weapon Handler and here is our Proxy Weapon.
00:24From Component > Audio, select Audio Source. And we need to turn off Play On Awake.
00:35Like before, we'll play the audio clip directly from the script, but this time we
00:40won't tell it which clip to play in the Components audio clip parameter. Let's
00:45go ahead and open the Projectile Script.
00:48Double-click. It brings up the Script Editor. First we need to create a variable to
00:53hold the audio clip.
00:55So under my speed variable, I'll add var weaponFireFX of type Audioclip;.
01:17And inside the if clause where we fire the projectile we're going to add these lines.
01:23So inside the if clause--and we can start down here. I'll tab over, and we'll a
01:29note to ourself with our forward slashes to make a comment. Play a sound when it
01:35fires. Hit Enter and here's our line.
01:42audio.PlayOneShot, and now it takes the argument weaponFireFX, our audio clip.
01:56So I'm going to double-click, right-click and Copy and right-click and Paste,
02:04and then I'll close my parentheses and semicolon.
02:08So we can go ahead and save our script now and get back into the editor. And now
02:14we need to select our Proxy Weapon, find a script--here it is, our Projectile
02:20Script--and we need to add a sound. And I'm going to choose PopCanon and I'll
02:26drag it right over here.
02:29Before we click play though, there's one thing I'm going to do.
02:32I'm going to disable the WindZone so we don't have to listen to those birds over and over.
02:38So I'm going to click the WindZone and deactivate it up in the Inspector.
02:44Okay, click play and fire the weapon. Remember, we do that with either the left
02:49mouse button or the left Ctrl Key.
02:53Play and here we go. (cannon firing)
03:00And so now we have a sound when we fire off our weapon.
03:04Let's Escape, get out of Play mode, and look to see what we need to do next.
03:11Well, of course now we need a sound for when the cannonball hits something, but
03:16we really don't want to have to put an audio source on everything that can be
03:20hit, and we probably don't want to have to assign a special sound to each object
03:24that can be hit either.
03:25An advanced solution would be to have the hit object use send message to tell
03:31the projectile what sound to use, but we're just going to keep it simple.
03:36Let's start by adding an audio source to the Cannonball prefab in the Project folder.
03:41So in the Project folder, we'll select our Cannonball prefab. From Component >
03:48Audio, we'll add our audio source.
03:51Once again, as soon as we find it, we're going to turn off Play On Awake.
04:00And this time since it maybe quite a distance away, let's make sure we change our
04:05Volume Rolloff to linear rolloff; otherwise, we might not even hear it.
04:12So as long as we have the Cannonball selected, let's go ahead and tidy things up.
04:17I'm going to close the Game Sounds folder for a minute, and I want to take my
04:21Cannonball prefab and drag it into the Prefabs folder.
04:25That was made when we imported the fountain, but it will serve us well for
04:29all of our prefabs.
04:31Now let's open the ProjectileHandler script.
04:35Double-click it to open it in the Script Editor and now we need to add a
04:39variable named var hitSound, of type AudioClip, and of course semicolon.
04:58Now here's the tricky part: we need to decide where we want it to play.
05:03If it's gotten as far as OnCollisionEnter, either way, it can play a sound
05:08effect, so we are going to add our play line down below the else. And this one
05:17will be audio.PlayOneShot. And inside the argument will be our hitSound
05:32variable, right-click and Copy, right-click and Paste, close the parentheses and semicolon.
05:42So let's go ahead and save our script and head back to the editor. Before we
05:47can test it, we need to select the Cannonball prefab. And remember, we just put
05:53it into the Prefabs folder. And we need to load a sound into its new Hit Sound parameter.
06:01I'm going to open up Game Sounds and choose plopsm. And be sure you put it in
06:09the Hit Sound parameter, not the audio source.
06:12Okay, we're ready to play. Let's click play and fire it off.
06:20(sound effects playing)
06:26With the addition of audio, our little projectile is shaping up nicely.
Collapse this transcript
7. Exploring Prefabs
Creating and reusing prefabs
00:00Prefabs are Unity's mechanism for creating fully-formed sophisticated
00:04game objects on the fly.
00:06We've made instances of objects in the scene using duplicate, Ctrl+D, but they
00:12only exist in their own particular scene, to instantiate an object at runtime
00:17in any scene or level we need to store the original and the Project view as a Prefab.
00:22We've already created a simple Prefab, our Cannonball.
00:26It's instantiated at the transfer of the object the script is on. Let's open the
00:31Projectile script in Script editor and take a closer look at what the
00:35Instantiate function is doing.
00:37We'll just double-click it to open it up, and here's our Instantiate line.
00:42It creates an instance of the projectile at a particular location and orientation,
00:48transform.position and transform.rotate.
00:52Transform is referring to the object the script is on, in this case the Proxy Weapon.
00:56Let's take a minute to look up instantiate in the scripting reference.
01:01I'm going to go back to the editor, and open the scripting Reference, and we're
01:08going to type in instantiate in the search and click Enter.
01:12I'm going to choose the first one, object.instantiate. Let's take a minute to
01:16look up instantiate in the scripting reference,
01:19we've used the second variation with the Cannonball,
01:22transform.position and transform.rotation.
01:26But if we wanted to do something like instantiate a genie and a puff of smoke in
01:30a fixed position, we'd leave off the position and rotation arguments and the
01:35instance would be creating using the Prefab's original transforms.
01:39The last form of instantiate would be the one we want.
01:44Let's try that with something more down to earth, a rock, and since the code is
01:48already written for us in the scripting Reference we may as well trigger the
01:52Instantiation with an OnTriggerEnter.
01:55Let's go back to the editor, and we'll start by moving the first-person
01:59controller to the staging area.
02:04So on my top view, I'm going to select my first-person controller, use my middle
02:10mouse to pan and roll it to zoom, and I'm going to switch to Global and drag
02:21them back behind the first barrier, about, like so.
02:31Next we'll create an empty game object near the first-person controller, I'm
02:35going to double-click to zoom a little closer.
02:38So I'll make it GameObject, Create Empty, and we'll name this Rock Zone.
02:44And we'll give it a box collider, Component > Physics > Box Collider.
02:53Check Is Trigger, and we'll want to scale it up to about 5x5x5.
03:03And I'll zoom out, and we'll move it back a little from the first-person controller.
03:08Now let's create a new script in the Game folder and name it Rocks.
03:14Right-click > Create > Javascript, and we'll name this one Rocks, and we'll go
03:21ahead and open it in the Script editor.
03:24I'm going to go out and get the code from the Snippets file.
03:29Exercise Files07/07-01/07-01 Code Snippets.
03:40So we'll select it, right-click, Copy, and then back in our scripts editor I'll
03:46just paste it into the Rocks script.
03:49This one is pretty simple. Let's go ahead and Save and head back to the editor,
03:53and we'll drag the new script onto the Rock Zone Game object.
03:58Now we'll need a rock, so let's import the simple rock package from this
04:03video's assets folder.
04:06Right-click > Import Package > Custom Package, and in the Assets folder select
04:18SingleRock and Open, and we'll Import, and our rock can be found in the
04:26imported assets folder.
04:28The usual procedure for creating a Prefab is to: one,
04:32create an object in the scene. Two, create a new Prefab in the Project view.
04:38Three, drag the object from the Hierarchy view onto the Prefab, and four, delete
04:43the original from the scene. Let's give it a try.
04:46We'll start from dragging the rock into the scene from the Project folder.
04:54I'm going to switch to Perspective. Next we'll create a new Prefab in the
04:58Project view in the Prefabs folder.
05:01So, select folder, right-click > Create > Prefab, and we're going to name that
05:10one Rock Prefab, since we already have a rock in the scene.
05:15And you'll notice that its icon is white.
05:18As soon as we take our rock into it, we'll see the Prefab icon turn blue.
05:26In case you notice the object's name in the Hierarchy view was already blue
05:30since it's an instance of an asset that's already in the Project view.
05:34We've already got an object named Rock in the project view, so we avoided
05:38confusion by naming this one Rock Prefab.
05:41Our Prefab is ready to use, so in the Hierarchy view we can delete the rock from the scene.
05:48I'll select it and then hit Delete.
05:50And now we need to assign the Rock Prefab to the Prefab parameter of the Rock Zone.
05:55So we'll select this, and we'll drag our Rock Prefab over onto that parameter.
06:04Now if we click Play, and move our first-person controller into the collider,
06:11and I'm going to use my S key for that to run in backwards, we can see that the
06:16Rock gets instantiated right where we placed it. Let's exit Play mode.
06:23The Rock Prefab we instantiated during runtime is destroyed, leaving the
06:27Hierarchy just as it was before we clicked Play.
06:30So what it wanted our Prefab to be instantiated in a different position?
06:35Simple, drag the Rock Prefab into the Hierarchy view.
06:41It appears right where we originally put it.
06:44Now in the Scene view, let's move it off to the side a bit.
06:50Now we need to update the Prefab.
06:53At the top of the Inspector, under the Prefab section, we're going to click Apply.
07:00Now let's delete this guy,
07:03right-click > Delete, click Play, and as we move our first-person controller
07:11into the collider again our rock is instantiated in the new position, and we can
07:16go ahead and exit Play mode.
07:18If we wanted to include several rocks in our Prefab we could put them all in an
07:22empty game object and drag that back onto our Prefab, using that method will
07:28give us a warning about overwriting, but it allows us to make more serious
07:32changes to an existing Prefab.
07:34As an added benefit, once an object or group of objects exists in the Project
07:40view, we can export it as a Unity package. Let's go ahead and make one now.
07:46Let's select our Rock Prefab in the Prefabs folders and from the right-click
07:52menu choose Export Package, we'll click Export, and I'm just going to save mine
08:01here, 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:00Let's have a bit more fun with Prefabs.
00:02So far we've instantiated them in predictable places at predictable times.
00:08In our little game the player will start out in the staging area.
00:11It's small, and there's nothing of interest in it, but we might need to motivate
00:15him into leaving it.
00:16A bunch of rocks falling on him just might do the job.
00:20Now it would look pretty odd if all the rocks were the same size, but the
00:24Instantiate function doesn't have a Scale parameter.
00:27So the first thing we need to do is import the LotsOfRocks package from
00:32the right-click menu.
00:36Import Package > Custom Package, and from our Assets folder we are going to
00:44bring in LotsOfRocks.
00:49In the Prefabs folder, you can see Rock1, Rock2, Rock3, and Rock4.
00:55I've added to each a Mesh collider set to Convex, a Physics material, a Rigidbody, and an Audio Source.
01:04Let's drag the four new rocks into the scene near the original rock pile, and
01:08then lift them up above the Rock Zone's collider.
01:14Rock1, Rock2, Rock3, and Rock4, and I'll use Shift to select them all and drag
01:30them up a little ways.
01:32I'm going to deselect them, and click Play, and watch them fall. We'll exit Play mode.
01:41And now we need to update each Rock's Prefab by clicking Apply in the selector
01:47to make sure it knows where the new location is.
01:52Apply, Apply, Apply, and Apply, and now we can delete the rocks in our scene,
02:07Delete, and there we go, so far so good.
02:10Let's make a new Rock script in the Game Scripts folder by duplicating the original.
02:15So I'll select it and use Ctrl+D, and I want to name this one RockDropper.
02:23Let's open it in the Script editor and make a few changes, double-click, make
02:30sure we're on RockDropper.
02:31And the first change we are going to make is the variable.
02:35Instead of 1 of type transform we're going to make it an array.
02:39Unity uses two types of arrays, the usual Javascript type array, and its own version.
02:46The Unity array must be declared as a particular type, and it can show up in the
02:50Inspector where we can change its size and load up its elements.
02:55A Javascript array doesn't store types causing the #pragma strict to report an error.
03:01With Unity's emphasis on mobile we're better off to stick to the Unity arrays.
03:06If you're already familiar with Javascript arrays you may want to read through
03:10the scripting reference on arrays to see the differences.
03:13So in the RockDropper script, let's change the variable line to their Prefabs,
03:20I'm adding an S, and then transform and then open and shut bracket.
03:27This is what tells us it's going to be an array. Next we need to change the instantiate line.
03:33To access an element of an array we need to put the element number in brackets.
03:38So Prefabs and open bracket, I'm going to start with element 0 and close bracket.
03:46Arrays always start with element 0.
03:49Let's save the script now and get back to the editor.
03:56We can replace the original script with this one on the Rock Zone object.
04:00And we can do that to the browser, and we'll choose RockDropper.
04:10If you click Play, and use the S key to back into the collider, you'll get an
04:15IndexOutOfRangeException Error on the console. Let's look at that.
04:23That's because we haven't filled out the array with anything yet, and then we're
04:27trying to instantiate element 0. So let's exit Play mode and fix that.
04:33I'll close the console, exit Play mode.
04:36And in the Rock Zone, we need to open up Prefabs, set its size to four.
04:44And drag the Rock into each parameter.
04:54Now we can click Play, press S to back into the zone, and we get lots and lots of rocks.
05:03Let's stop before we get too many.
05:07So this time the Rock Prefab from element 0 drops into the scene.
05:11And it keeps dropping because each rock triggers the zone on entry.
05:16In this case that's a serendipitous side effect.
05:19It will eventually shut itself off when it fills up.
05:22The problem now is that the same rock is being used over and over.
05:26We'll fix that in the next video.
Collapse this transcript
Introducing randomness
00:00In the last video we left our rock element zero dropping over and over into the zone.
00:06We need a way to use all four of our rocks better yet in random order.
00:11Since randomness is a mainstay of games of all types, let's use the random
00:15function to get different rocks.
00:17We'll start by opening the scripting Reference and do a search for random.
00:23And we'll enter, and we're going to select Random.Range.
00:27If we look up Random.Range, we see that it has two configurations:
00:32one for using floats, where both of the values are inclusive, and the one that
00:37uses integers, where the max number is not inclusive.
00:42This may sound odd until you think about arrays, they start at element zero.
00:47So if we have four elements we can ask for an integer between zero and four.
00:53And it will give us 0, 1, 2, or 3.
00:57Perfect. Let's go back to the editor. And we'll start by opening the RockDropper
01:02in the Script editor.
01:05Let's start by rewriting the instantiate line and replacing the zero with the random function.
01:11And that will be Random.Range and our range will be 0 to 4.
01:24Let's Save the script and head back to the editor.
01:28Now we can click Play again, and back the first-person controller into the
01:33collider with our S key, and there we go. Let's click Stop, and you can see it works.
01:43A randomly selected rock from our array is dropped each time the Rock Zone is triggered.
01:49There's one more thing we ought to change though.
01:51We hard coded the 4 in the Range, and that's not good practice, we'd have to
01:56manually change it each time we change the array in the Inspector.
02:00Instead, let's create a variable to hold the length of the array because arrays
02:06have a length parameter. We can get that number in the Start function.
02:11So back in the Script editor, we're going to add the variable var Prefabs
02:17length of type int.
02:20And in the Start function, we'll go ahead and assign the value PrefabsLength
02:28equals Prefabs.Length.
02:31As long as we're in the RockDropper there's one more thing we need to consider.
02:35Since the amount of rock seems to be dramatically increasing, it might be a good
02:40idea to disable the physics after a few seconds using isKinematic.
02:46If we do that after the line is instantiated in the new Prefab, we'll need a
02:50temporary variable name so we can refer to it.
02:54The Instantiate function returns the object it just created, so we can assign it directly.
03:00We'll change the line as follows,
03:02var clone of type transform equals the instantiated object.
03:14And now we'll add directly underneath this--so I'm going to give myself a
03:18little bit more room.
03:21And now I'm going to go out to my snippets file and grab the next two lines,
03:26Exercise Files07/07-03/Code_Snippets, and we're going to grab the last two
03:35here, right-click, Copy, and I'm going to paste these right here.
03:42New here is the yield statement.
03:45It's another odd ball syntax wise, but it's extremely useful.
03:49For a single frame you can just use yield. This one, as you can probably tell, takes seconds.
03:58Rigidbody is another one of those components that you can get directly,
04:01we don't need get component rigidbody to refer to it.
04:05The isKinematic we've seen before, it turns off the physics on an object so we
04:10don't suck up all the machine's resources.
04:14So let's go ahead and save our script now and head back to the editor.
04:20And we'll click Play, and drive our first-person controller into the collider
04:24again using the S key, and we'll go ahead and stop Play mode.
04:37We've already discovered that the rocks will eventually pile up so high that
04:41they completely cover up the Rock Zone's collider, effectively shutting it off.
04:46Feel free to reduce the height of the Rock Zone's collider to one and move it
04:50down so will shut off sooner.
04:53Even without our player taking damage from the rocks, he'll quickly get buried
04:57and should be highly motivated to get through the door.
Collapse this transcript
Creating particle systems
00:00A big part of interactive games regardless of genre is Particle systems.
00:05Particle systems make up most of the eye candy in a game.
00:09One of the unique things about Particle systems is that they usually can't be
00:13imported from regular 3D applications like Max or Maya, so need to be developed
00:18almost exclusively in the game engine.
00:21Unity has a complex and powerful system for creating and combining particles to
00:25give you all sorts of special effects.
00:27We'll only cover enough to get you familiar with the main features, but you
00:32should come away with enough understanding to let you spend hours on your own
00:35experimenting with them.
00:37Let's go ahead and import the Particles package, right-click Import Package, and
00:44this time we're looking for Particles, and Import.
00:52Let's create a new scene for our Particle system experiments, File > New Scene,
01:01and we can go ahead and Save.
01:03And then we are going to name this one as Particle Tests.
01:06File > Save Seen As, Particle Tests, and that should automatically open up in
01:16our Unity 704 Assets folder, and we'll click Save.
01:20This will save it automatically into our projects Assets folder.
01:25Now that we've got several scenes cluttering up the project view, let's go ahead
01:29and make a folder called Scenes and put all of our scenes into it.
01:33Right-click > Create > Folder, and we'll name it Scenes, and then we'll drag all
01:44of our scenes into it.
01:53To make a new Particle system, you can either make an empty game object and add a
01:57Particle system component to it, or create it directly from the game object
02:02Create Other submenu.
02:04Let's use that method to create this one, Game Object > Create Other, and it's
02:10right here at the top, Particle system.
02:15And it happily spews particles at a casual speed.
02:19Let's deselect the Particle system in the hierarchy view,
02:24the particles are no longer active.
02:26Since we won't need the game window for a while, let's switch to wide layout and
02:31focus back on the Particle system.
02:33Under 2x3 we'll switch to wide, and we'll double-click on the Particle system to
02:41bring it back into the view, and once again they start flowing.
02:46You can also scrub through the timeline by clicking to the left of the playback
02:50time and dragging the mouse left and right.
02:59You can also change the Playback Speed, that would make it slower 0.5, and if I
03:07put it at 5 you can see it's a lot faster. I am going to set it back to 1.
03:15This time let's select Stop before deselecting them, and now we no longer have
03:20particles cluttering the Scene view.
03:23We usually have two types of particles in a scene, those that are happening
03:27throughout, like a fountain and those that are instantiated during runtime and
03:32have short life spans, like an explosion.
03:35In the Scene view we can you use Stop and Simulate to see how the finite life spans look.
03:41Let's select the Particle system again and in the Inspector uncheck Looping.
03:53Click Stop then Simulate, click Stop.
04:01As you can see, the particles were emitted for the first five seconds, then stopped.
04:08Let's look at the basic parameters.
04:10Duration is the amount of time the particles emit or the length of the cycle
04:14that repeats when it's set to loop.
04:16Prewarm starts the particles fully into the cycle so that things like waterfalls
04:21and chimney smoke are already going when your game starts.
04:25Let's check Looping again, and Prewarm, and then Simulate.
04:33This time the particles are already underway. Let's click Stop.
04:40Start Delay is a built in pause before they start up.
04:43This is handy when you're combining several Particle systems to make complex
04:47particle effects, Unity's term for several that are used together.
04:52In an explosion for an example, you wouldn't want the smoke to start until the
04:56pyrotechnics were nearly finished.
04:58Start Lifetime along with the next four parameters let us add variation through
05:03presets in the modules below this section, and also through the little right-hand dropdowns.
05:09At Start Color, we can affect the color of the particles on a wholesale basis.
05:14Using gradient here would cycle the colors over the duration, not the particle lifetime.
05:20Next we can adjust the gravity with the Gravity Modifier,
05:23this adjusts the values already set in the Physics Manager.
05:27The Physics Manager can be found in Edit > Project Settings > Physics.
05:31Let's add more gravity, about 0.5, and click Simulate.
05:42Then we'll try running it up and down to see the difference.
05:50Let's go ahead and stop and set it back to zero.
05:58Inherent Velocity will determine what happens when the emitter is transformed.
06:02At zero the particles ignore the transform.
06:05We can't see this one in Edit mode, we'd need to add a script to transform it
06:10and observe it during real Play mode.
06:12If you opt to try this one out on your own, be sure to switch to the local
06:16coordinate system, the results will probably make a lot more sense.
06:20Simulation Space determines whether the particles are emitted in local space or world space.
06:26For something that moves around, like water from a fire hose, you'd want to
06:31use local space, Play On Awake is just like the audio, the particles start up
06:36as soon as the scene starts, or if they're on a Prefab as soon as the object is instantiated.
06:43Max Particles limits the number of live particles we will have on screen at any time.
06:48When reached, the Particle system will quit emitting until the old ones start dying off.
06:53In the next video we'll look at the modules beneath these settings to see what they offer.
Collapse this transcript
Refining particle systems
00:00In the Particles Test scene, let's select the Particle system object and then click Stop.
00:08Before we move on to the rollout section we really ought to take a peek at some
00:13of the options available to some of the regular Particle system parameters.
00:16Let's click on a few of the down arrows.
00:22With numbers we get the choice of Constant, Curve, Random Between Two Constants,
00:28and Random Between Two Curves.
00:31With Colors we get Color, Gradient, Random Between Two Colors, and Random
00:38Between Two Gradients. We'll be testing Gradient a little later on.
00:42The rollout section of the Particle system contains modules that give you more
00:46control, especially over the individual particles.
00:52Of the three that are already turned on, Emission and Renderer are mandatory.
00:57We can turn the modules off and on with the checkboxes, but need to open and
01:01close the rollouts by clicking on the bars.
01:04Under Emission we have rate, how many particles per second or per distance are emitted.
01:11First, let's just emit extra at the specified time or times in the duration.
01:16We can add a remove Bursts with the plus button. Let's look at Shape next.
01:24There are several different emitter types to choose from, including the option
01:28to limit from meshes.
01:31The next several modules alter the particles on an individual basis.
01:35Velocity over time lets you affect the direction of the particles in world or local space.
01:41Limit Velocity over time allows you to dampen or slow the particles.
01:45Before we look at Color Over Lifetime, and we are going to need to turn it
01:53on, we want make sure that the start color is just white, so we're good to go on this one.
02:00Color over Lifetime lets us affect the color on a per particle basis rather than
02:05Particle system duration, let's go ahead and try it.
02:09Let's click the down arrow, it defaults to Gradient, so let's click on the
02:14Gradient and give it a try.
02:18In the Gradient editor the ramp color picker works like this, the top markers
02:23are for opacity and the bottom are for color.
02:26Click above or below the color bar to create a new marker.
02:31The marker will inherit the color or opacity of the initial position.
02:35You can delete a marker by selecting it and then pressing Delete, and I'll hit
02:39my Delete key, and that one is gone.
02:42To change the color of marker we can double-click on it, and it opens up the
02:47regular color picker.
02:49And if I change the color we can see the gradient.
02:55For the opacity we can click on a marker here and these are set by number.
03:06Let's click simulate and see what it looks like.
03:11And I'll zoom in a little bit more, I'll adjust my window size so we can get a
03:16better look at it, and we can stop.
03:21For Size over Lifetime we need to open the Particle system editor to see the curve.
03:28The button for that is up near the top.
03:30If you click the button we'll see the curve in the editor, and we can go ahead
03:36and close the editor.
03:37We'll get lots more practice with the basic curve editor functionality when we
03:42do some Unity keyframe animation, and let's go ahead and stop the particles.
03:46Back to our rollouts, Collision lets us use planes as deflectors, coupled
03:54with bounce and other parameters, this one can come in handy for things like rain effects.
03:58Submitters lets you spawn more particles on death or collision using
04:03other Particle systems.
04:05An example would be fireworks were the sparks flyout and explode into individual fireworks themselves.
04:11Texture sheet lets you cycle the particles through different images on a texture
04:15sheet to have animated images on your particles.
04:18The Angrybots demo scene has an excellent example of this with the ripples on
04:22the outside raining terrace areas.
04:25And finally, we get down to the Render module. Let's open this one up.
04:31From here you can select the type of particles you want, the default is
04:34Billboard or facing planes.
04:37Before you test out the last choice, Mesh, you will want to turn the
04:41Max particles down.
04:42You can also set the material for your particles,
04:45Unity has several particle specific shaders that are great for many typical use cases.
04:52The Sorting options will help with opacity draw order issues and the Sorting
04:57Fudge will help withdraw order issues between different Particle systems.
05:01The doc say Cast and Receive shadows is only for opaque materials, so it's
05:06usually safe to leave on, if in doubt uncheck them to save resources.
05:11And finally, we have Max Particle Size as the player gets closer to the
05:15particles this is the largest they can scale to. This is a screen percent 0 to 1.
05:21Plan on lots of tests to get the look and functionality you're looking for.
05:25In the next several videos we'll make use of some of the Particle system Prefabs.
Collapse this transcript
Combining particle systems
00:00While the power and versatility of Unity's particle system is impressive
00:04thing thought of making your own Particle systems from scratch can still be intimidating.
00:08Fortunately there are several great Prefabs waiting for us in the Particles
00:12Package we imported in the last video.
00:14Unfortunately, at the time of this video, most of the legacy types and are harder to tweak.
00:20A lot of the parameters were the same, but they don't have the playback controls
00:24in the viewport and they show the wires in the Scene view when selected.
00:28Unless you select the Parent Game Object, and then you can't edit them.
00:32So until all of the Legacy Particle system Prefabs have been replaced with the
00:36newer Shuriken type it would be useful to know what some of the legacy
00:40parameters equate to.
00:42Let's open the Standard Assets folder, and the Particles folder, and then the Dust
00:51folder, let's select Dust Storm. This is one of the Legacy Particles.
01:00The Legacy Particles energy equals particle life, One Shot means no looping and
01:07Size Grow means size over time.
01:13For Auto Destruct there is no equivalent, and it needs to be scripted.
01:17Let's check out some other Prefabs.
01:20From the Fire folder, let's select Flame and drag it into the Scene viewport.
01:30And I'm going to zoom in on it. Let's double-click to focus in on it and open
01:38the Game Object and select each of the objects individually.
01:43Now we can see we need to zoom out a bit to see it.
01:49So this one has an InnerCore particle system, a light source, which is an actual
01:55light if we look in the Inspector,
01:59an outer core, and a smoke. If I zoom out you'll see that it starts getting
02:06darker as it goes up higher.
02:08Let's see if we can make an updated version of the Flame Prefab.
02:12You probably don't want to watch me set each new particle system up to match the
02:16Legacy particles, so I've made replacements available as Unity packages.
02:21Let's deselect our current object, let's use import package to get InnerCore,
02:27OuterCore, and smoke from this chapter's exercise files.
02:31Import Package > Custom Package in the Assets folder, select InnerCore and Open,
02:42right-click again, Import > Custom Package, Assets > Outer Core, and one more time
02:59Import Package > Custom Package > Assets and Smoke.
03:12Let's tidy up our Project view, so we can find our new objects.
03:16To start I'm going to drag my three objects into the Prefabs folder,
03:23InnerCore_S, OuterCore_S, and Smoke_S.
03:31And now I want to go ahead and drag them into the hierarchy panel.
03:39This one, this one, and the Smoke.
03:43Now that we have our three base particle systems and they are in the
03:47Hierarchy view, let's put them together into a particle effect so we can work on them together.
03:52The doc say that all must be parented to the same object, but what they don't
03:56say is that the parent must also have a particle component on it.
04:00So in the Hierarchy view, let's drag OuterCore_S and Smoke_S onto
04:06the InnerCore_S object.
04:09So OuterCore on to InnerCore and Smoke on to InnerCore.
04:15And now, let's double-click InnerCore_S to find in the scene view.
04:23And I'll zoom in a little bit, and it looks like we need to rotate it -90 degrees on the X.
04:36There we go, that's much better.
04:38Now we can open them in the Particle system editor.
04:40We'll select InnerCore_S, if it isn't already, and we'll open the editor.
04:47It looks like we'll need to drag the side panel over to see our three Particle systems.
04:52This enables us to tweak them individually while watching the full effect.
04:56Let's go ahead and close the editor and deselect the particles.
04:59Now that the fire effect looks pretty good we can sneak the light source from
05:04the Legacy Prefab, drag it out of its parent, continue, and I'm going to use
05:14Move to view to get it close to our particle system.
05:21I should probably double-click to focus on the InnerCore and be a little more
05:28exact when I move it to view. Drop it down, and there we go.
05:34I'll drag it into the other particle system parent, and we are ready to
05:39create our new Prefab.
05:42Let's right-click on Prefab and create new Prefab, and we'll call this one
05:50Flame_S and drag our new Particle system Effect into it.
06:01Let's go ahead and save the scene.
06:07Now we are going to go ahead and open up the main level again, and let's focus
06:12in on the bridge plank. That's in the structures for scene section.
06:20Give myself a little bit more real estate here, use Alt and left mouse
06:26button, and now we can bring our Flame_S into the scene to make it much more interesting.
06:38You can see the nice addition the light source makes, feel free to click Play
06:42and check out the new stuff in the Scene view.
06:45Let's create an empty game object and name it Flames Group.
06:48That way we can keep all of our flame objects together in the Hierarchy view.
06:52GameObject > Create Empty, and we'll name our New GameObject, Flames Group.
07:01And 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:00Now that the compound area is starting to look pretty good, we may need to get more
00:04serious about our weaponry.
00:06Lobbing pseudo-cannonballs at stuff can only take us so far.
00:09With all the particle system Prefabs at hand, it's time to think about improving our cannonball's
00:15functionality, and for that we can start with explosions.
00:18We know that on collision returns a bunch of information besides just the hit object.
00:24So let's make use of it to give us a place to instantiate an explosion.
00:28Let's start by opening the ProjectileHandler script, that's the one that already has the
00:33OnCollisionEnter function in it.
00:35We'll be using an Explosion Prefab, so the first thing to do is make a variable to hold
00:40it at the top of the script. Var Explosion of type GameObject.
00:47At the top of OnCollisionEnter we'll need to add a couple of variables to store the
00:51exact location of the hit.
00:54We also need to know the orientation of the face or triangles' face normal, so we can point
00:58the special effects that local direction at the hit location.
01:02I'm going to copy the next couple of lines from the snippets file, then paste it in.
01:07Exercise Files07/07-07Code_Snippets, and I'm going to take these lines, right-click, and
01:22copy, back to the Script editor, and I'm going to paste them right in here.
01:30And highlight them, right-click, we'll have an Indent Selection.
01:34I've also included comments on these since they are a little bit confusing.
01:40For our contact line, remember those brackets? That means an array.
01:45If you think about it, the projectile hits several times before being destroyed as we heard when we added sound.
01:51So the Collision class is storing all of those hits in an array.
01:55We just want the first one, which is Element 0, and we've added a comment to let us know what that's doing.
02:02The rotation line is a little bit more complicated.
02:06We are used to thinking of rotation in terms of X, Y, and Z axis, but the Euler Math involved
02:12has a few problems. It's prone to gimbal lock.
02:15If you haven't heard that term before, the easiest way to explain it is to picture yourself
02:19standing and watching an airplane flying towards you, as it passes directly overhead, you will
02:25need to turn 180 degrees to watch it as it flies away from you.
02:29Euler Math can also give different results depending on the order that the axes are evaluated.
02:35Quaternion math is much better mathematically but less intuitive for us to work with.
02:40It only needs to know which direction it needs end up facing.
02:44Unity uses both and devotes a lot of functions to converting from one type to the other.
02:49Now if that sounds confusing, don't worry.
02:52The bottom line on this one is that it gets the direction of the hit face's normal, and
02:56the normal is an imaginary line perpendicular to that face, and we've added a comment for that as well.
03:03And now inside the if clause, we can tell it where to instantiate the explosion, and
03:09I'm going to copy that one from the Snippets file as well.
03:13Copy it, and we'll paste this line underneath the SendMessage line.
03:22The only mildly tricky thing about this line is the contact.point, since the location is
03:28a three-part affair, X, Y, and Z, the point property of contact delivers it in one shot, a vector three type.
03:35And finally, we need to copy the audio line into the if and the else statements, so it
03:41will play before the object is destroyed.
03:44I 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:56In the if statement, I need to make sure that the audio plays before the object is destroyed.
04:02So I am going to add a yield statement here.
04:05Yield is one frame before it goes ahead and destroys.
04:08In the else statement, this one is going for five seconds before it gets destroyed, so
04:14we don't have to worry about it.
04:15Okay, let's save the script and get back to the editor.
04:20Since this script lives on Projectiles, we'll need to locate our original cannonball Prefab
04:25in the project view, so we can assign the explosion to it.
04:29And Prefabs, here is our Cannonball, and in our ProjectileHandler script, here is our
04:39field for the explosion.
04:41We're going to get a Prefab from the Standard Assets folder, under Particles, under Legacy
04:51Particles, we're going to drag the Small Explosion into the Explosion field on our ProjectileHandler.
04:59We should be ready to click Play and try it out.
05:02I'm going to drag my window open a little further and click Play.
05:10If we fire using our left mouse button, we get an explosion, Exit Play mode.
05:20Well, that worked, but let's try a different explosion.
05:24I am going to scroll down and then try just the regular explosion.
05:33Click play, and fire again, much better.
05:41Let's Exit Play mode.
05:43Before we move on, let's do a little bit of housekeeping.
05:46In an earlier video we put a script on one of the barricades that senses the presence
05:51of, well, any object that intersects it.
05:55Let's select the Barricade Mid and remove the Trigger Test script.
06:02From 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:00We've made the area beyond the nature zone more interesting with fire, so now
00:04let's go back the other direction and add water to the nature area.
00:08We're going to bring in the Water Packages for pro and basic, so we can check
00:12out the differences.
00:14The pro version makes use of reflection and refraction for some spectacular results.
00:19The basic version is pretty sad, so in a later video we'll also look into a
00:23better version of it in case you want to lower resource using version of water.
00:28Let's import both the Water Packages, right-click, Import Package, and we'll
00:36start with Water Basic, Import.
00:43And we'll repeat Import Package, Water (Pro Only), Import.
00:53We'll find them both in the Standard Assets folder near the bottom.
01:01Let's start by focusing in on the Fountain and move the first-person controller
01:05to it using Move To View.
01:10So we select the first-person controller, GameObject > Move To View, and we'll
01:17double-click on him to zoom in closer.
01:19I am going to use my Alt key, spin around a little bit, and then we'll move him
01:29down out of the way.
01:34This way we will be able to see the view when we click Play.
01:37It will be a lot easier to see what we've got if we go ahead and select the
01:41Terrain and turn off the Trees. So let's do that now.
01:47In Settings I'm going to uncheck Draw, and there much easier.
01:54I want to rotate it a little bit.
01:59From Standard Assets, Water folder, let's drag in Daylight Simple Water, and
02:08maybe move it up slightly.
02:14It's not terribly inspiring. Let's delete it and see how much better we can
02:19do with the Pro Water.
02:21So I'll right-click and delete it and from the Water (Pro Only) folder, I'm
02:31going to drag in Daylight Water. And once again I'll position it a little better.
02:39That's more like it.
02:41The downside to this one is it tends to be a resource hog.
02:46In the Inspector we can see that there are tons of things you can adjust, but
02:50we'll just stick with the defaults.
02:51The waves in both water Prefabs use world scale so shrinking the meshes won't affect them.
02:57Let's scale our Water down to fit the fountain.
03:06And I'll tip my view a little so I can get my water a little more centered.
03:15Right now, our Terrain fills up the fountain where our water should be.
03:19Let's deactivate our water for a minute at the top of the Inspector.
03:23In the Terrain editor we're going to need to go ahead and make a hole in the
03:26Terrain at the fountain until we can see the bottom.
03:30So I'll select our Terrain, go to our Raise/Lower the Terrain height, choose a
03:37small size, I am going to try about 8.
03:44And since we're lowering the Terrain we need to remember to hold the Shift button.
03:51And I should probably rotate my view to make sure I've got it all.
03:57While we've got the Terrain editor open, we are also going to need a hole for a waterfall.
04:02And that will be off to the left here, so I'm going to increase my Brush Size
04:07to about 20, hold my Shift again and just make a bit of a hole, it doesn't
04:17matter how deep it is.
04:19Now we can activate our Water again, and we're going to add a water fountain.
04:27So from the Standard Assets folder > Particle systems > Water, let's choose
04:35Water Fountain, and we can drag it in and drop it right about there.
04:42May need a little adjustment, so I am going to move it over a little bit, wait
04:49for the particles to catch up. Use my Alt to look at the view, and there we go.
04:56The Pro Water doesn't come with Colliders, so if you've already jumped into the
05:00Fountain and gotten stuck, feel free to add a Collider to it.
05:04Let's click Play and watch the results, and Exit.
05:14Next we are going to drag in the Waterfall Prefab.
05:17It's the same place as the Water Fountain.
05:19So I am going to zoom back a little bit, and we want to position it up on the cliffs.
05:34So from Water > Waterfall, and we'll drop it right about here.
05:43We need to rotate it and maybe position it a little bit and then the biggest
05:51thing we need to change on it is the life of the particles.
05:55Coming from that high up we need a longer life. In the legacy particle life equates to energy.
06:02We'll set our Min and Max Energy to about 3 for now.
06:10We'll add a lower resource using water later on when we get to textures, but for
06:14now, let's pretend there is a surface there, so we can use one last water
06:18Prefab, and that is Water Surface Splash.
06:22Located in the Standard Assets > Particle systems folder > Water, and we'll drag
06:28it into the scene beneath the waterfall.
06:36Zoom in, looks like I need to align it to the waterfall first.
06:44So I'll double-click my Waterfall, and then I'll select my Water Surface and use
06:53Move To View, and now I should be able to move it down and inward, and now if I
07:04zoom in on it, we'll get to see what it does. And there we have it, Water Surface.
07:14You'll probably want to do some scaling on this one.
07:17Let's set the Min Size to 3 and the Max Size to 4, and we start to see
07:29the effect much better.
07:31Okay, let's click Play and see what it looks like.
07:39There is our Water Fountain, and if we drive over to here we can see the start
07:44of our Waterfall, and let's exit Play mode.
07:49The four water type Prefabs make a nice addition to our scene.
Collapse this transcript
8. Using Imported Assets
Importing static objects
00:00We've had a peak at dealing with imported assets in Unity in earlier chapters.
00:04Now let's dig a little deeper and see what goes on with the entire process.
00:08First off, Unity supports files from several popular 3D applications, 3ds Max,
00:14Maya, Blender, Cinema 4D, Cheetah3D, and Modo.
00:20It also reads, .FBX, .DAE, .3DS, .DXF and .OBJ files.
00:28If your application or application's file type is not directly supported,
00:32chances are there's an FBX Exporter out there for it.
00:36The caveat to the supported file types is that many of the original
00:40applications must be installed and licensed on the computer in order for Unity
00:45to read their files.
00:46Once the file has been saved in the Unity folder, the nice thing is that anytime
00:51you make changes to that file then return to Unity, the changes are automatically updated.
00:57The not so nice thing is that unless you're using a versioning software such as
01:02SVN or Unity's own Asset Server, you won't have any earlier versions to revert
01:07to unless you manually save them somewhere else.
01:10Unity recommends saving the applications file directly to your Assets folder.
01:15Internally though, it converts all supported file types to FBX format.
01:20For that reason I prefer the extra step of exporting an FBX file to my Unity
01:24project and keeping my application files separate.
01:28This way I know anyone will be able to open the project without having the 3D
01:32app installed, and I also have all of my incremented versions in case I need
01:37to revisit something. So what exactly does Unity support?
01:41Well, if FBX supports it Unity probably supports it.
01:46All nodes with position, rotation and scale. So objects, groups, hierarchies, or linkages.
01:51Meshes with vertex colors, normals, and one or two sets of UVs, no more.
01:57Materials with a diffuse color and texture, and it also supports multiple materials per mesh.
02:05For animation, simple transform animations--and we'll cover imported animations
02:10in a later chapter--and bone based animations.
02:14Currently there is no native support for vertex animations such as Morph targets.
02:19If you check the manual for how do I import objects from my 3D app, you can find
02:24more information for your specific application. So let's bring in some more assets.
02:29Theoretically you should be able to bring your meshes and your textures in at the same time.
02:34Unity needs to generate its own version of the materials so it must have
02:38the textures at hand, to ensure that I usually bring my textures in before the meshes.
02:44It doesn't matter where in the Assets folder you drop them, you can always move
02:48them later, but only from inside Unity.
02:51So let's start by selecting all of the compound extras textures from the
02:55exercise files folder, and then we'll be pasting them into the Assets folder via
03:00the operating system.
03:03Exercise Files08/08-01/Assets, and I'm going to open my CompoundExtrasTextures.
03:15I am going to switchover to Details, so I can easily use shift to select them
03:22all, right-click and copy them.
03:28And now I'm going to go back and open my UnitySampler project, the Assets
03:36folder, and I'm going to paste them into my Textures folder that I already have.
03:43And we'll open it up just to make sure they've arrived.
03:50And we've got lots of new textures now.
03:52Now we can bring in the FBX file, CompoundExtras.FBX, and we can do that in several ways.
03:59We could bring it in through the operating system like we just did for the
04:02textures or we can just use Assets > Import New Assets.
04:07We could also drag it directly into the Project view from the operating system.
04:11I'm going to select the Imported Assets folder and then use the second method.
04:16Here is our Imported Assets, right-click and Import New Asset.
04:28We want to make sure we get to the right folder Exercise Files08/08-01/Assets,
04:41and here is our CompoundExtras FBX file, and Import.
04:48And now in our Imported Assets folder, we have our CompoundExtras.
04:52We'll need to get a good look at what we've got, so let's start by moving our
04:56first-person controller into the compound area.
05:04Select him and move him, and we want him right about there, and I'll switch over
05:13to a Perspective view and double-click. We need to put him down on the ground.
05:23And now he should have a pretty good view of the assets when we bring them in.
05:29So now, let's bring the CompoundExtras from the Project view into our compound area.
05:43And maybe I'll bring my first- person controller a little closer.
05:49Let's click Play and drive around and see them.
05:54Using my W A S D I go here, and I can check and see what else I've got here, and
06:04we can exit Play mode.
06:06The first thing we want to check after importing assets is the scale.
06:10So let's start by selecting the CompoundExtras in the Project view and
06:16looking at the Inspector.
06:19Right now we see a Scale Factor of 0.01, and it seems about right for our new assets.
06:25I made these objects in 3ds Max. Max objects tend to come in huge.
06:30I exported my objects as FBX, so they would be application independent.
06:33But if you're using Max files directly you'll see an option to use file units.
06:39This lets you use one Max unit equal to one Unity unit.
06:43Let's try changing the Scale Factor to 0.005.
06:49Whenever we change a parameter in the import settings we need to press Apply,
06:53and that is down near the bottom. Click Apply, we can that our objects shrunk.
07:01Let's set it back to 1, 0.01 and click Apply again, and now they look right again.
07:11Unity scaling system is very good.
07:14If you're using assets from different sources it's no problem to set the scale
07:18for each import individually. The next on our list,
07:24Mesh Compression may need to be used if the meshes you import were not
07:28modeled for real time.
07:29But check the results to make sure that the model still looks okay.
07:33Models that have had serious poly reduction done on them might benefit
07:37from optimized mesh.
07:39It renumbers the polygons internally for quicker rendering.
07:42If your mesh looks neat, clean, and orderly, it's probably okay as is.
07:46The next check box, Generate Colliders, is important.
07:50It will generate mesh colliders on all objects in the selected asset collection.
07:55For the Structures Assets it was extremely useful.
07:58For the CompoundExtras we may want to exchange several of the mesh colliders
08:02for Primitive Colliders later, but let's go ahead and check it now and of
08:07course, click Apply.
08:14The next to deal with UVs are texture mapping coordinates.
08:18Unity only supports two UV channels.
08:21The first is used for the diffused texture and the second for light maps.
08:25Diffused UVs often have chaotic looking UVs to allow tiling and matching up the
08:30textures with the building's stone texture.
08:33It allows you to tile a high-resolution map across a lot of surfaces and retain detail.
08:38Light maps however must be normalized.
08:41The UVs all must be contained within the boundary of the texture and must not
08:45overlap or share the same spot on the map.
08:48If your diffused UVs are not normalized, the same UVs can be used for the light mapping.
08:53Otherwise, a second set will either need to be provided or you can have Unity
08:58generate them for you with Generate Light Map UVs.
09:02If for some reason the two UVs come and assign to the wrong numbers, you can use
09:06Swap UVs to set them right.
09:08Most of the objects I've provided come in with the second set of UVs already made.
09:13If you don't plan on baking light in Unity, you don't need to worry about the
09:17second UV channel at all.
09:19If your object does not import looking quite right, you may need to fuss with
09:22normals and tangents.
09:24Some formats such as .OBJ do not store smoothing angle data and may need to be
09:30manually set up, see the docs if that's the case.
09:33The next section is for Materials.
09:35Unity does not import materials from your modeling app.
09:40It finds the diffused texture for each material on the mesh, but that's as far as it goes.
09:45With that texture it generates a generic material with the diffused shader.
09:50As a default for naming that material, it uses the material's diffused texture
09:54name, good news for those of us who forget to name our materials.
09:58So what happens if your objects material doesn't have a diffused texture?
10:02Well, then it gets assigned the name of the original material.
10:05If you prefer that it always named after the material, you can change it in the
10:09Material naming field.
10:11For material search there's a nice description of what's happening.
10:15But as I mentioned earlier the safest thing to do is make sure that all your
10:18textures are imported before you import the meshes.
10:22The reason I stress this is that if you update the asset by re-importing, and
10:26you don't use the generic material assigned on the import, you'll have to
10:30reassign the ones you replaced them with.
10:33Under Animations > Generation, select Don't Import, and I'll just do that right now.
10:40We're going to select Don't Import since none of these objects have
10:44animations on them.
10:45And, having changed something, we need to go down and click Apply.
10:52So a few more things to know about imported assets in general,
10:55you can change the name of the asset group in the Project view, but the rest of
10:59the objects in the file can't be changed in Unity.
11:02Changes to the original file will be updated as soon as you return to Unity.
11:07If you are already using the assets in a scene, as long as you haven't broken
11:11the Prefab, the references to the original asset file updating should be pretty seamless.
11:16As soon as you break the Prefab, by say, removing something from the group, all
11:22bets are off, but you can revert back to the original if you need to.
11:26Let's try removing the rocket.
11:28So in the Hierarchy, CompoundExtras, we'll just drag the Rocket out and put it somewhere else.
11:39We get our Losing Prefab warning, and we are going to say Continue, and since
11:44it's no longer referenced properly, the text turns white.
11:48If we rename, say the Crate, and I'll select it just add a 2 to the end, and then
11:55Revert the entire CompoundExtras, watch what happens.
11:59And Revert is up here in the same place that we usually have our Prefab area.
12:04So we'll say Revert and look what happens. Our rocket is put back and our Crate is renamed.
12:11What about the first rocket we removed? Well, let's check and see, and there it is,
12:17it's right where we left it.
12:19So this gives us a way to only use selected objects in a larger group
12:22of imported assets.
12:24Let's go ahead and delete the extra rocket, right-click, Delete.
12:28We'll take a closer look at how Unity handles textures and materials for our imported objects next.
Collapse this transcript
Manipulating textures
00:00Before we can start tweaking the imported materials we need to investigate
00:04textures and how they are handled in Unity.
00:07Let's start by looking at the Cardboard Box object.
00:10I'm going to move the CompoundExtras back a little bit so it will be in the sun,
00:15and I'm going to zoom in as well.
00:20So opening my CompoundExtras, I'm going to double-click the Cardboard Box and
00:28get a nice view of it.
00:29When we select it we see its material at the bottom of the Inspector.
00:36Let's click on the thumbnail, and that locates the texture in the Project view,
00:42and we'll go ahead and select it from there.
00:45In the Inspector we can see a preview of the texture as well as its various properties.
00:50Unity, let's us tweak several of them.
00:54Selecting the texture type will bring up the appropriate parameters, it also
00:58sets many properties according to the type selected.
01:01If you're feeling like a game texture guru you can select Advanced and set everything manually.
01:07The others are nothing more than presets, we'll stick with texture.
01:11The next option is Alpha from Grayscale, before we try this let's check out
01:15the Preview window.
01:17This texture was a simple JPEG and had no Alpha channel.
01:21Now let's check Alpha from Grayscale and Apply.
01:29We can now toggle between the RGB version and the Alpha version.
01:34Obviously it doesn't make much sense for this texture, so let's uncheck it
01:38and click Apply again.
01:42The next parameter is Wrap mode. Let's select the Sheet-Metal Rusty Object in
01:47the Scene view and track down its texture, Rusty panel.
01:58If we change Wrap from Repeat to Clamp and click Apply, we can see the pixels
02:09are stretched across the rest of the object.
02:11Let's set it back to Repeat and click Apply again.
02:16Filter mode is how it goes between mipmaps.
02:19With mipmapping decreasingly smaller and blurrier versions are made and stored
02:24of the image, then used in the scene depending on how far away you are from the object.
02:29Scrub the slider in the Preview window to see the various versions.
02:34You won't see the actual size, but they will be base 2.
02:38So the first was to 256x256, the next was 128x128 then 64x64, 32x32, 16x16 et cetera.
02:49Look at the Sheet Metal from an angle, the farther away it is the blurry it gets.
02:56The default Filter is Bilinear, so besides getting blurrier as it gets farther
03:00away, it also blurs the texture when the player gets very close.
03:06Aniso Level--Aniso is short for Anisotropic--allows you to increase texture
03:11quality when viewing the texture at a steep angle.
03:14If your floor and ground textures have a lot of artifacting going on, try
03:18increasing this, but use it sparingly it's a resource hog.
03:22What's an artifact?
03:23Basically something that doesn't look like it belongs in the render.
03:27It may be some odd black pixels, or in this case, the ground might look sparkly as
03:32move through the scene.
03:33That's because the renderer can't decide what color to make each pixel
03:36from frame to frame.
03:38Aniso Level samples the area and comes up with a consistent color.
03:42And now the last section, let's select our Rustypanel again and go back to the Inspector.
03:48As a default, Unity compresses and changes the format internally on your
03:52textures unless told otherwise.
03:55This means you can use Photoshop layers and files with abandon.
03:59Just as with meshes, as soon as you make changes in your image and save it from
04:04your Texture Editing Application, Unity updates its compressed version.
04:08If you're using the Advanced Texture Type, and let's switch to it for a minute,
04:12you can even specify which flavor of .dds compression you want, otherwise you
04:17only get a few choices. We'll switch back to Texture, and Apply.
04:29One of the nicest features is the Max texture Size and the option to override on
04:33a per platform basis.
04:35Let's select the Sentry Gun and track down its texture.
04:43I'll click on its thumbnail, bring up the SentryGun texture, I rendered out my
04:48SentryGun texture at 1024x1024, which is overkill for the size and importance of the object.
04:55I can reduce it and see just how far it can go down with it.
04:59Since it's kind of splotchy by nature, I can take it down pretty far.
05:07And I should zoom into my SentryGun and Apply first.
05:17At 64 it starts to look different, so I'll just set it to 256 and Apply, back to
05:25my SentryGun texture, 256 and Apply.
05:33And finally, if you want to edit your texture, double-clicking on it in the
05:37Project view or clicking the Open button will open it in your Default Texture editor.
Collapse this transcript
Working with materials and shaders
00:00Let's look at materials next.
00:02In Unity materials are made of shaders, so they are handled by the graphics card.
00:08Instead of starting with a generic material and adding components such as bump,
00:12shininess, and reflection as needed. With Unity you need to select the shader
00:18that has all of the components you need to start with.
00:21Most of these parameters will require textures.
00:24Let's start by looking at the Cardboard Box material this time.
00:28Select the box in the Hierarchy or Scene views.
00:32To locate the material in the Project view we need to click on the Mesh Renderer component.
00:39So under Mesh Renderer > Materials, we're going to look for the material here, 16 - Default.
00:48And we'll click on it in the Project view.
00:51Now we've got plenty of room to experiment with it, and we also get a Preview Window at the bottom.
00:58You can change the display shape and lighting there also.
01:05The main color is usually going to be a light silver, this gives you wiggle room
01:09in case your texture looks a bit dark in the scene.
01:12Mine looks a bit dark, I'm going to lighten it.
01:18And we should also be looking at the Cardboard Box in the Scene.
01:22It also allows you to add a different color to the texture map.
01:26Along with the texture map we can set the tiling and offset of the texture.
01:31I'm going to select my 16 - Default material again, and let's see what happens
01:36if we change our Tiling, 2 and 2. And the Offset we can change as well.
01:43I'll just leave it as is and set my Tiling back to 1.
01:47But we have no means of tweaking the UVs that the object came in with.
01:51So what about Shader choices? Let's hit the dropdown and check them out.
01:57Since Cardboard is smooth but not shiny, I guess we can leave this one as it is
02:02with the default Diffuse Shader. Let's look at the Crate instead.
02:07It's a simple box with a single bitmap.
02:11I'll double-click to select it, and we'll get a better view of it.
02:18It's awfully flat looking, even for wood. Let's check out our options.
02:23First we'll find its material, in the Mesh Renderer, here's its material 01 - Default.
02:29We'll hit the Down Arrow again then if we look up at the top, Bumped Diffuse
02:37might be a good choice.
02:39It needs a normal map for the bump map but Unity can create one for us.
02:44But it will change the original in the process. So we need to make a duplicate of it first.
02:49Let's find the CrateSide texture, select it then use Ctrl+D to make a Duplicate,
03:00and we'll name this CrateSide bump or bmp.
03:05In the Inspector, now we can change the Texture Type to Normal map.
03:12It will create it from a Grayscale version of the texture.
03:15Go ahead and click Apply. Little goes a long way.
03:20So let's bring it down about halfway, on the Bumpiness, and click Apply again.
03:28Now let's get back to our Crate material and finish setting up our
03:31Bumped Diffuse shader.
03:35I'll select my Crate again, get myself to the material, and now I'm
03:45going to locate my CrateSide bump image and drag it into the Normal map.
03:52If I lighten the Main Color, we'll be able to see the results a lot better.
04:00Let's take it one step further. What if we add it some Specular?
04:04Let's go up and choose a Bumped Specular instead of Bumped Diffuse.
04:10We can tweak the Shininess and also the Specular Color for some interesting results.
04:19But here's the interesting thing, notice that our base texture is now RGB, and
04:24the gloss is in its Alpha channel.
04:27Since the CrateSide texture doesn't even have an Alpha texture, it gets a
04:31full dose of glossiness.
04:33But wait you say, wasn't there an option for that? Yep, there was.
04:37So let's go back to our CrateSide texture and check Alpha from Grayscale and Apply.
04:48That definitely tones this one down, even though it was not a specially made Specular map.
04:53So with shaders it's not unusual to repurpose an Alpha Channel to use for
04:57something other than transparency, and that's a good thing to keep in mind when
05:02you're making your textures.
05:03As a sort of wrap up, let's remember that Unity won't automatically assign
05:08non-diffuse textures on import.
05:10We will need to have them in the project, so we can finish setting up our
05:14materials once the import is finished.
Collapse this transcript
Handling multiple materials
00:00Let's look at a few more materials with different shader needs.
00:03The Lamp is a good place to start.
00:06So in our CompoundExtras, let's select the Lamp and double-click it, so we get a good view of it.
00:15We'll be dealing with the bulb inside it first, so you may want to tip it upwards.
00:21You can see that the lamp has four different materials over in the Inspector.
00:28Normally we try to combine multiple textures into a single texture map to reduce
00:33draw calls, but sometimes there is no shader available to do the job.
00:38Let's see what we need to do for a couple of these specialty shaders.
00:41Starting with the BulbLit material we'll want to find one of the
00:45Self-illuminated shaders. So let's go up and select.
00:53Since my materials don't have proper names, I'm going to need to figure them out by number.
00:57The BulbLit looks like it's going to be the fourth, so I'm going to double-click
01:04on it, and there it is.
01:06With this one we're looking for a self-illuminated shader.
01:10So I'm going to click the dropdown and under Self-Illuminated, I'm just going to
01:16choose the simplest, Specular.
01:21Most of the Self-Illuminated shaders use the Alpha channel for glossiness, even
01:26the simple diffuse uses an Alpha channel for the glossiness and needs an extra
01:318-bit map for the self-illumination. Which actually makes the shaders in this
01:35category quite useful for those nice walls with light panels in them.
01:39Emission determines whether the material will emit light when using the Lightmapper.
01:44Zero is no light will be added.
01:47The dock suggests using emissive light calculated from material should only be
01:51used for large dim areas.
01:53So our light bulb object should be accompanied by an actual light object at some
01:59point just like our flame Prefab.
02:01Okay, let's select the Lamp again, and look at the Chrome material.
02:07Fortunately this one has a name.
02:10I'll double-click on it, it is mapped to the underside of the fixture and needs
02:15a shader with reflection.
02:17So let's change its shader to Reflective > Specular.
02:22So under Reflective we're going to choose Specular.
02:27Before we even add a map, we can see there's some self-illumination going on.
02:32Toggle off the scene lights in the Scene view, and adjust the Specular Color and
02:36Shininess to affect the highlight.
02:39So we'll toggle off the Scene lights, and now adjust the Shininess, so it makes
02:50a nice pseudo-reflective look.
02:52For the reflection, Unity expects a Cubemap, as we can see right here.
02:58Even if you have some of your own, they may not be the same format Unity uses, so
03:02we're going to see how to make a quick one next.
03:05Cubemaps require six individual maps, so let's start with something small.
03:10For now we're just going to use a single texture to make the Cubemap.
03:13I want my new Cubemap in the Textures folder, so I'll select the Textures
03:17folder, right-click on it and Create > Cubemap. Let's name it ChromeRef.
03:33And there it is waiting for six maps. We're going to cheat.
03:37Let's drag MetalRef_small texture into each of the slots.
03:42Yeah, I know it's a cheat, we're not using six different maps, but you got the idea now.
03:51So now I have something marginally better than the Unity defaults to load into
03:55Chrome materials reflection Cubemap slot.
03:58Let's select the Lamp and load in the new Cubemap.
04:06And we can do it right in the material, and there we go.
04:17For the top of the lamp, we can use the RibbedRadial as a bump map and change
04:21the shader to Bumped Specular.
04:24Let's see if we can figure out which is the top, it looks like the lighter gray,
04:33so I'm going to guess it's 07. We'll change its Shader to Bumped Specular.
04:45Rather than making the Normal map first, let's see what happens if we try to
04:48use a regular texture. Let's duplicate the RibbedRadial texture first.
04:55In the Textures folder, RibbedRadial, use Ctrl+D, I'll name this one
05:03RibbedRadial bmp, for bump, and select our Lamp again.
05:17Now I'm going to drag my RibbedRadial bmp into my Normal map.
05:27And we get a warning.
05:29This texture is not marked as a normal map. Fix Now? Sure why not.
05:34If we click it, and it fixed it nicely.
05:37So now that we've seen if you specialty shaders, you should have a better idea
05:40on how to set up your own materials.
Collapse this transcript
Animating UVs
00:00Now that we've learned more about textures and materials we are going to fill
00:04in the hole over at the waterfall. This time with a non-proshader and a useful little script.
00:09Let's focus in on the water splash area, I'll double-click on water surface
00:13splash in the Hierarchy to locate it, and then I am going to use my Alt-left mouse
00:18button to rotate the scene and then zoom in.
00:23And now we want to create a plane, so GameObject > Create Other > Plane, and
00:31it's going to come in at about the same spot as our water splash, and so we
00:37want to drop that down just a little bit, and then we will scale it up so it fills the hole.
00:46And we are going to name this one Water Basin.
00:51Now we need to import the simple Water Package from the exercise files for this
00:54video, it should turn up in the Main Materials folder.
00:59Right-click, Import Package > Custom Package, and in our Assets folder, Simple
01:10Water, and click Import.
01:14So let's locate our new material, and since I don't see it right-off, I'm
01:20going to go ahead and use the search function, and there it is right here, Simple Water.
01:25We will drop our new material onto the Water Basin, like so.
01:33You don't need to click Play to see that it's going to need some motion, looks
01:38pretty static as is.
01:40Let's select the Simple Water material and change the Offset X to 0.5.
01:48Our Offset X, and when we change it to 0.5 watch it shift in the Scene view.
01:57The Offset loops at one. So let's go ahead and set it back to 0.
02:03Since writing shaders to animate vertices is an advanced topic, we'll just write
02:07a little script to animate the offset of the texture.
02:10It can be used on just about anything to animate a materials-based texture.
02:15Let's think about what we'll need.
02:17We'll need to be able to give it a speed and to tell it which direction, U or V,
02:22to scroll, and we will need to tell it which material it should be affecting.
02:26Let's create a new script in the Game scripts folder and name it UV_Scroller,
02:32and then we'll open it in the editor.
02:34I'm going to click out of my search function and locate my Game Scripts.
02:42Right-click, create Javascript, UV_ Scroller, double-click it, and we are going
02:57to need several variables.
02:59So I am just going to copy them from the Snippets file, Code_Snippets, and
03:04we're going to take these first three, Ctrl+C to copy and add our variables up at the top.
03:14In the Update function we'll need to affect the Offset by using time.time then
03:19multiply it by speed.
03:20I'm going to grab the next couple of lines and paste them in as well.
03:24Highlight our next two lines, Ctrl+C to copy, and we add those to our Update function.
03:31I am going to give myself a little bit of space first and Ctrl+V to paste.
03:35Now here comes the new bit, to access a shader's property we need to use the
03:40property names a bit differently.
03:42We usually start with an underscore and some of the names are different than
03:46what we see in the Inspector, base being one of them.
03:49You can find the common texture names scattered through the material class functions.
03:54Let's open the shader reference for a minute and search for material, and open
03:58the scripting reference, and do a search for material.
04:06We're going to be looking for SetTextureOffset, so I am going to hit Enter, and
04:12we'll see if we can find that, SetTextureOffset, and it shows us the names that
04:20we need to be using to refer to the shaders.
04:23It looks like MainTex is the one that we're going to need. And grab the next
04:28line, right-click, copy, and we want to put that one right beneath the others,
04:35using Ctrl+V to paste.
04:37And now we can save the script, and we'll apply the script to the Water Basin
04:43object, UV_Scroller over to Water Basin.
04:50Let's select it and in the Inspector we are going to change one of the scroll
04:57speeds to about 0.05.
05:02Let's switch back to the 2 by 3 layout and focus in on the Water Basin again.
05:08Up at the top, 2 by 3, we'll double-click Water Basin, and use the Alt key to
05:18get back to our view.
05:23I'm going to deselect the Water Basin, and then click Play.
05:30And our water has a nice little animation on it. Let's exit Play mode. Just a note here,
05:37if you try the UV_Scroller on the pro-water nothing happens.
05:41Remember, Unity controls that animation through the shader, so the shader must
05:45support the offset property as well.
05:48There's a nice water shader in one of the sample projects, Sewer Room, that does
05:52support it, and it also has a very good non-pro-water shader.
05:56That can be found on the Unity web site.
05:58Now let's use another trick for Economical Water, a double layer.
06:02Let's duplicate the Water Basin with Ctrl+D, so we'll select it, Ctrl+ D, and
06:10we'll drop it down just a little bit.
06:17Just about that much, then we're going to change its UV_Scroller numbers a little.
06:22Let's say 0.03 and 0.03 to get it moving at an angle that's different from the original.
06:30We'll click Play and check it out, and I'll deselect the water so we can see the difference.
06:41The addition of the second layer really makes our water look dynamic.
06:45Let's exit Play mode.
06:47Once we edit the partially transparent Water Basins we started to see a
06:51flickering issue with the Water Surface Splash Prefab.
06:54The problem is because both basins and particles use a transparency shader, so
06:59the engine can't decide which to draw first.
07:02Unity uses a queue tag system with the shaders to tell the engine which order to
07:07draw objects into the scene.
07:09Search queue tag, if you're curious, that's Q-U-E-U-E on queue.
07:15Meanwhile, let's use import asset to bring in the
07:18Alpha-BumpSpecDrawFirst.shader.
07:23Right-click, Import New Asset, and this is the one we want so we'll say Import.
07:32Now we can replace the Simple Water Material Shader with that, it's under
07:36the Custom Section.
07:38To find our simple water material again, this time we can click on the Water
07:42Basin, and there it is at the bottom of the Inspector.
07:47So we are going to change our Transparent/Bumped Specular to Custom, Bumped Specular Draw First.
07:57I've changed the Queue tags in this one so it should work better for us.
08:01Let's click Play and test.
08:08Now the Water Surface Splash Prefab always draws after the two Water Basin
08:14objects, and we can exit Play mode.
08:19And in case you already tried walking on water just leave the colliders on the
08:22water surfaces for now. We'll see a final alternative in a later video.
Collapse this transcript
Tracking objects with LookAt
00:00With the addition of the Sentry Gun in the CompoundExtras, we'll be able to
00:04check out a few more popular features with our scripting.
00:07Crucial for any interaction between player and other entities is the ability for
00:11them to see the player when he comes within range.
00:14We're going to set up the Sentry Gun so we script it to turn to face the player.
00:19It will need some changes in the colliders, plus a Rigidbody.
00:23So let's import the Better Extras Package and use the Prefab from it.
00:28It's already set up for us.
00:30So right-click, Import Package > Custom Package > Assets > Better Extras, and we'll
00:42click Open and Import.
00:45We've also got a few other new Prefabs, we'll look at those later.
00:50Now let's focus in on the Sentry Tripod in the CompoundExtras folder, and I'm
00:58going to rotate my view a little bit, and then from the Prefabs folder we are
01:10going to bring SentryGunGroup into the scene.
01:16And we can use Move To View to match it up to the original.
01:20We'll need to drop it down a little bit, and now we can delete our original
01:24Sentry Tripod group.
01:26Right-click, and delete, and yes, we'll lose our Prefab.
01:31So this guy now, the SentryGunGroup, has an added Rigidbody, and I have changed
01:40him to a Box Collider, and you can see it's kind of narrow and tall that way
01:44when we hit him it will be kind of wobbly and fall over easier.
01:47Now for the fun part, we'll be using the simplest code, Transform.LookAt.
01:53So let's make a new script in the Game Scripts folder and name it SentryGun.
02:01Right-click, Create > Javascript, SentryGun, and we'll double-click to open it.
02:13And I am going to go ahead and close some of the other tabs so we don't get
02:17confused, by clicking the X.
02:22So to start, for our SentryGun script we're going to need a variable to hold the
02:26target and then the rest is going to go into the Update function, so let's
02:30start with our target. Give myself some space, var target : Transform;.
02:41And in the Update function we are going to add, and I'll give myself some room
02:47here, transform.LookAt(target);.
02:52So now we can save the script and get back to the editor.
02:56And we need to drop it on the SentryGun.
02:58So I am going to make sure my SentryGunGroup is open, and I'm going to drag
03:02SentryGun onto SentryGun, and select it.
03:06So now we need to drag our first- person controller onto its target parameter.
03:11Let's go to the Inspector find where that is.
03:16Here is our first-person controller, and we'll drag and drop him on to
03:21the Target parameter.
03:23This is one of those times we need to make sure and use the 2 by 3 layout so we
03:27can get a better view of the gun.
03:28So if you haven't already, go ahead and switch to the 2 by 3 layout, and
03:32let's get a little bit of an Overhead view going so we can see what the gun is pointing at.
03:37I am going to use Alt-left mouse key, and maybe zoom out a little bit.
03:44And now we can click Play and drive around the area, we should be able to see
03:48the gun watching the first-person controller, and don't forget to go up and down
03:51the steps and maybe even jump a few times.
03:56Click Play, and I'm using my Left Arrow key, Right Arrow key, I'm going to go up
04:07now with my Up key, and maybe I'll try jumping, and we can see the gun is
04:12definitely tracking us, and we can exit Play mode.
04:16So now that we are sure the LookAt is working nicely, let's see about keeping
04:20the SentryGun from tracking the first- person controller when it's beyond range.
04:24That means we'll need a range variable, so let's head back to the Script editor and add it.
04:29We'll edit underneath our Target variable var range : float,
04:34and we'll go ahead and initialize it at say 30 meters.
04:40I am going to grab the next bit of code from the Snippets file, and we'll
04:45open 08_06Code_Snippets, we've already added the first three, so let's just
04:51copy this guy, right-click, Copy, and we want to add that one up above the LookAt line.
05:01The Return Xs us out of the function so that nothing below it is carried out.
05:07In this case that means if the first- person controller is out of range the
05:11SentryGun wont rotate towards it.
05:13Let's save the script and head back to the editor.
05:16And there we go, now we can click Play and test.
05:19If we leave the compound area this SentryGun will no longer track the
05:23first-person controller.
05:28And I am using W to head on out, and he is still watching, and at some point he
05:35no longer rotates to follow us. And let's exit Play mode.
05:40Now 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:00The next goody we'll make is a laser beam.
00:03Our sentry may not have any ammo, but its laser will show us what our first-
00:07person controller has been detected.
00:08Let's start by selecting the laser point object on the Sentry Gun.
00:12I'll need to open him up, and here is our Laser Point.
00:16From the Components menu, Effects, let's add a Line Renderer component.
00:23Components > Effects > Line Renderer.
00:28The Line Renderer creates a plane that always faces the camera.
00:32First we want to uncheck Use World Space.
00:38That keeps it at the laser point instead of 000 in the World.
00:42Now we can see it in a scene. Let's uncheck Cast and Receive Shadows and Open Up Positions.
00:51Elements 0 and 1 are locations of the start and end points of the line.
00:57The line is actually a plane.
01:00Element 1 Y is the length of the line, we'll be feeding it the hit distance from
01:05the guns Line Caster later. But for now we'll set it to 5 so we can see it.
01:10Under parameters we'll set the start and end with to .15.
01:17And now we are going to need a material.
01:20Our last package import included a laser material, let's go ahead and assign the
01:24new material in the Line Renderer's Material Array.
01:29Open up Materials we'll add it to 0.
01:35And I've opened up the browser, and I am looking for Laser, and here it is.
01:43The Laser material came in with our last package import, let's take a quick look at it.
01:49It's in the Materials folder and here it is. It's using a Tiling of 20, and
01:59that's going to show up as soon as we start animating it.
02:02For now let's get back to our Laser Point.
02:04Now we are going to need a script to calculate the length and direction of our laser.
02:09So let's create our new script in the Game Scripts folder, right-click,
02:18Create > Javascript, and we are going to name this one Laser.
02:23Double-click it to open it in the script editor, and, of course, it's going to need
02:29a target there, so we'll start with var target : Transform;.
02:33Var target of type Transform--and auto complete has got me again.
02:46I'm going to copy the next bit of code from the snippets file.
02:50Exercise Files08/08-07/Code_Snippets.
02:55So we are going to highlight, right- click, and Copy, back to our Script editor,
03:03now we're going to paste this in the update function. So let's see what's going on here.
03:09In an earlier video we used physics.Raycast with a starting position and direction.
03:16With physics.Linecast we have a starting position also, but instead of the
03:20direction we have a target position that is used to calculate the direction internally.
03:26Next using hit, of type Raycast hit, we get both the location of the hit and
03:33the distance to it.
03:35Those values are fed back into the LineRenderer component to draw Element 1 in
03:39the correct location.
03:41Our Element 0 is always at the laser point's location.
03:45Let's save the script and head back to the editor.
03:48And we'll need to add the laser script to the laser point object and then assign
03:53the target our first-person controller.
03:56So our Laser script goes on the Laser Point, select the Laser Point and here's
04:04our target, and we want our first- person controller as the target.
04:10With the last package import we also got a nice stack of barrels.
04:14This will give our first-person controller something to hide behind.
04:18So from the Prefabs folder, let's drag the Stack O' Barrels into the Hierarchy view.
04:26And we may need to adjust them slightly.
04:32I'm going to move them so they are sort of in and sort of out of the sun.
04:36Now let's click Play and test it by strafing the first-person controller
04:39with the A and D keys.
04:41I'm going to tip our view a little bit, click Play, and as soon as our first-
04:49person controller gets out from behind the barrels, the laser beam spots him,
04:56let's exit Play mode.
04:58So we have now seen how physics.Linecast can be used to create some special effects.
Collapse this transcript
9. Understanding Lighting
Investigating ambient light
00:00Back when we first setup our environment, we needed to add a light so we could
00:04see things in the game view.
00:06Scene view offers the option of default light, but game view must have lights or
00:11everything appears in an odd sort of twilight.
00:13In this video we'll be investigating ambient light.
00:17So let's deactivate the Directional light to start.
00:20I select my Directional Light, and I'm going to deactivate it.
00:25If you've been baking your light into textures you won't see much difference,
00:29let's clear them just in case.
00:31From the Window menu, open Lightmapping and click Clear--mine wasn't baked in so
00:39you won't see any difference for me.
00:41In the game window everything still looks kind of light. So what's happening?
00:46Unity, like most 3D engines, has a setting for ambient light, it sort of fakes the
00:52bounce light that gets scattered around from the atmosphere.
00:54Desert areas have sharp shadows and high contrast between sunny areas and
00:59shadows, this is because the air is so dry.
01:02Places with high humidity and/or cloud cover have softer diffused light and only
01:07darkish areas of shadow from the light bouncing off the moisture in the air.
01:12In Unity we can find the ambient light property in Edit, Render Settings. Edit > Render Settings.
01:22We've been here before when we were looking into fog, so let's turn
01:26Ambient Light to black.
01:33Now there's nothing much showing in the game window, we can reactivate the
01:36Directional light now, depending on where we are it's still pretty dark, there's
01:41no bounced light, we may as well be on the moon with no atmosphere at all,
01:46select the light, and let's increase its Intensity to 0.8.
01:49The lit area looks much better now, but the things that receive no light are
01:53pretty much in the dark.
01:55Remember Directional lights only cast rays in one direction, so let's set
01:59it back down to 0.5.
02:02And now, let's turn the Ambient up just enough so the scene looks believable.
02:06We'll go back to Edit > Render Settings.
02:11I like it somewhere around 49 or 50 for the RGB values, now we're ready to go
02:18ahead and look at light objects.
Collapse this transcript
Looking at light types
00:00Now that we've seen how ambient light affects the scene we can look into regular lights.
00:05Let's start by selecting the Directional light. The first parameter is Type.
00:11The Directional light cast rays throughout the scene regardless of position,
00:16all rays are parallel to each other.
00:18In other words, the direction you point the light is the direction they all point
00:21Let's deactivate the Directional light again.
00:25Let's focus in on the Lamp, in the CompoundExtras, and we're going to create a test light.
00:30We could create one from the GameObject menu, but since it's just a component,
00:35let's create an empty GameObject, and name it Generic Light, and add a Light
00:43component to it. And we'll find that in Component > Rendering > Light.
00:49The default Type is Point, I'm going to move mine aside a little bit, and zoom out.
00:59So we'll have a good view of what it's doing.
01:01Point lights cast rays in all directions from a central point, and point
01:06lights have a range. Let's reduce the Range until we can see the range gizmo in the scene view.
01:11I'm going to click and drag next to the Range field, and as I bring it down, we
01:20can now start seeing its gizmo.
01:23If we move the light down we can see that it gets stronger the closer to the
01:27surface we get, so point lights have a built-in fall off within the range, and
01:32of course we can set the Color and Intensity.
01:36Cookies mask the light using a textures Alpha channel, point lights need cube
01:40maps with Alpha channels so let's change our light to a spotlight,
01:44under Type we'll choose Spot.
01:47It will need to be rotated 90 degrees on the X to get it to point down.
01:52And let's increase the Range, and the Intensity, and maybe I'll bring it up
02:00a bit, and bring my Spot Angle down. Let's see about loading a texture for the Cookie.
02:07I'm going to click on the browser, and see what we've got. Let's choose Cookie.
02:12We've already moved the light up so let's move it down now.
02:19As we move it down we can see that the cookie shows beyond the cone and since
02:23this texture is set to wrap it tiles. Let's change the light Type to Directional.
02:30Now we get a Cookie Size parameter.
02:33I'm going to reduce it, by clicking on it in Inspector, I can find it in the
02:38Project file, and look at it in the inspector, and we're going to change its Wrap
02:43mode to Clamp, and Apply. And now we can see that we have a single Cookie
02:51emitting from our directional light. So using a Directional light it gives us an
02:56economical way to use Cookies.
02:59Let's remove the Cookie texture by clicking on the browser and selecting None.
03:07And we'll go ahead and reduce its Intensity. In the next video we'll be looking at shadows.
Collapse this transcript
Exploring shadows
00:00If you're using Pro, you'll be able to test out Shadow Types, hard or soft shadows.
00:06Click play and select the BigTree and use Move To View to get it over to the compound.
00:12Click play. We'll select the BigTree. We're going to use Move To View to get into the compound.
00:19It doesn't really matter where it ends up, we're just looking for the shadow.
00:23So now activate the WindZone in the Hierarchy panel, and let's deactivate the
00:32Audio Source for a minute.
00:34Let's select Generic Light and test the difference between hard and soft shadows.
00:38Under Shadow Type I'm going to select Hard Shadows, and now we can see our
00:44dynamic shadows in the viewports. And then I'll switch to Soft Shadows.
00:51Okay, let's exit Play mode and continue with shadows.
00:57Let's turn our Generic Light back into a Point light, and increase its range
01:01and intensity a bit.
01:02So we'll turn it to and a Point light, and let's increase its intensity a
01:08little, and check its Range. That's probably pretty good.
01:13Let's set our Shadow Type back to Soft Shadows, and we'll see a warning
01:18here--Only directional lights have shadows in forward rendering.
01:24With Pro we can switch to Deferred Lighting, we find that through Edit > Project Settings > Player.
01:35In the Other Settings we can change our forward rendering path to Deferred Lighting.
01:42And now we once again have dynamic shadows.
01:46Let's select our Generic Light again and look into a few more parameters.
01:52With Shadow Type, Strength is how dark the shadows are.
01:55And you see we can fade it out and bring it back stronger.
02:01Unity uses shadow, or depth maps, for making shadows, so the larger the map the
02:06more accurate the shadows, but the more memory used.
02:10This is in your resolution.
02:11Map resolution defaults to the quality settings from the Project Settings under
02:16Quality, but it can be overwritten in the individual lights.
02:20With both pro Shadow Types, you'll see a setting for Bias.
02:25This setting is what needs tweaking when shadows don't match up with the geometry.
02:29We see it mostly on things like fence posts or other tall narrow objects.
02:34In this scene you might find it at the tripod feet.
02:37If the shadow doesn't quite match up with the foot, and you are sure that the
02:41foot is going through the ground, that may be the problem.
02:45By carefully decreasing the Bias, you should be able to get shadows to match up to the objects.
02:50If you go too low though, you get nasty artifacting, so be careful.
02:55So let's recap on dynamic shadows.
02:57Directional lights are the only lights that cast dynamic shadows with forward rendering.
03:02Let's go back into the Player settings and set render mode back to forward,
03:08Edit > Project Settings > Player, and we'll set it back to Forward, and our shadows
03:16disappear once again.
03:17While we're here, let's try the other rendering path option, Vertex Lit.
03:24With Vertex Lit, lighting is calculated on each vertex and averaged between them.
03:30This older technology is more economical than pixel lighting where the light
03:34calculations are done on a pixel basis.
03:37In pixel lighting, more screen real estate gets more accurate calculation.
03:41Unity automatically drops down to vertex lighting when required by hardware.
03:46Vertex lighting does not support dynamic shadows.
03:50Let's set the render path back to Deferred, if you have pro, or Forward, if you don't.
03:56Render mode also drops the lighting modes to vertex lighting unless
04:00important, or more distant lights in your scene.
04:03You can change these settings individually in the Quality Settings.
04:07For that, Edit > Project Settings > Quality.
04:13In the Quality Settings the Pixel Light Count lets you define the maximum number.
04:18This, by the way, is a good place to see what features are high resource users.
04:23Let's set the Quality to Good and get back to our Generic Light. Next up is halo.
04:31Let's check Draw Halo.
04:34If your lights range is large and the intensity low, you might not notice a difference.
04:39Halos draw their intensity inversely from the light's range.
04:43As we decrease the range, the halo gets stronger.
04:47Halos are also affected by distance. When you zoom closer to halos, they fade out.
04:54Halos are drawn on flat planes that always face the camera, so they are prone to
04:58being clipped on geometry, but are good for effects.
05:02You may find that you have more control with two lights when you want a halo effect.
05:06We won't need the Generic Light anymore, so let's go ahead and delete it.
05:11Right-click, Delete, and we'll go ahead and reactivate the Directional light
05:16for the next video.
05:17So this should give you a basic idea on how lights and dynamic shadows work in Unity.
Collapse this transcript
Baking lighting with Beast
00:00One of the most useful features Unity brought on board is the Beast Light
00:04Mapper by Illuminate Labs.
00:06Even at its most economical, lighting, and especially shadows, are costly.
00:12So typically, we bake the lighting into textures that are internally added to our geometry.
00:17As you might guess, it's not free, texture size can greatly increase the
00:22file size of a game.
00:23Visually though, it can be well worth the extra memory usage.
00:28Although Beast is available in both the free and Pro versions, the free version
00:33has most of the goodies turned off. In this video we'll just cover the basics.
00:38The most important thing to remember about the Light Mapper is that it's sort
00:41of a one-shot deal. You don't bake objects individually.
00:45So while you may bake the scene occasionally just for aesthetics, while you are
00:49working, generally it will be one of the last things you do once all of your
00:54assets are in and set up. Let's open the Light Mapper and take a look.
00:58From Window > LightMapping. The first tab is Object.
01:03This is where you will deal with objects on an individual basis.
01:07Let's select one of the barrels, so we'll have something to look at.
01:11Light Maps Static is one of the places an object can be marked as Static.
01:16Static means the object will not be moving in the scene and will both receive
01:20light mapping and be included in the overall solution.
01:24It's very important to get your head around that.
01:27Anything that animates, or is controlled by physics, should not be marked as static.
01:32You can also set the static in the Inspector.
01:35If you set it in the Light Mapper, it works more as an override for only the LightMapping.
01:41Static is also used for creating the pathfinding nav maps, among other things.
01:46So best practice is to set in the Inspector. Let's focus in on the fountain base.
01:52I'm going to move the Light Mapper, and let's select the fountain base and the two
02:02FruFra, and in the Inspector up at the top, we're going to check them as Static,
02:08and you see that Lightmap Static also gets turned on in the Light Mapper dialog.
02:14Once you have decided to bake light into an object, it will need a second set of
02:18UVs or mapping coordinates.
02:20Unlike regular texture coordinates the second UV channel has strict rules.
02:25We found that out in the video on Importing Static Objects.
02:29After Static, if we scroll down a little bit, comes Scale in Light Map.
02:36This one lets you to find how much real estate an object gets on the texture maps.
02:41The larger the value, the more space it gets.
02:44Let's select the Fountain Base again, and zoom in on it.
02:50In the Scene view, Light Map Display check Show Resolution.
02:56If we zoom in closer, we can see that there are lots of checkers on the fountain base.
03:01The terrain resolution is handled on its own, but everything else is handled
03:05relative to each other.
03:07The tiny checkers mean that the fountain base will get a lot of mapping space.
03:12If we reduce it, to say five, you can see the checkers start to get bigger.
03:20If I bring it down even lower, maybe 0.2, now you can see the checkers are quite a bit larger.
03:27As we reduce it, the checkers get larger, meaning that its pieces will be
03:32smaller or get less real estate on the light maps.
03:36For those of us who are used to baking in our light maps with VRay, Brazil, or
03:40other third-party renderers in Max, Maya, or whatever App we use, the next bit of
03:45info is extremely important.
03:47A scale value of zero means no light map will be generated, but the object will
03:54be included in the overall solution.
03:57So if your object comes in with its own light map, it still gets marked as
04:02Static, so it will cast shadows, but it needs its Scale in Light Map set to zero.
04:10If we select the Terrain, instead of scale in Light Map we get Light Map Size.
04:15This for Terrain's only since they are always handled separately from the rest
04:18of the scenes objects, and we'll open it up here.
04:24I can probably stretch my dialog out a bit.
04:27Atlas index is the array number of the light map the object is on.
04:32The Terrain is automatically assigned minus one.
04:35Everything else is combined or atlased on several more maps in the array.
04:42If we select our directional light, and I'll need to move the dialog out of
04:46the way, we will see a couple of parameters from the inspector plus a couple of new ones.
04:51Bounce Intensity multiplies the bounce light originating from the slide.
04:56So if it shines on a bright green object, the green color would be picked up and
05:00intensified on surrounding objects. More so with a higher Bounce Intensity.
05:06This is a pro-feature, by the way.
05:07Shadow Samples increase the accuracy and resolution at the cost of baking speed.
05:14Shadow Radius softens hard shadows. We'll get some practice with this stuff later.
05:18The next tab, Bake, is where you set up the solution in general.
05:22Mode is where you set up for dual, or single, light maps.
05:26Single Lightmaps are used with the forward lighting path and generates full
05:31solution light maps.
05:33If you have Pro, and are using deferred lighting, you will need to use Dual Lightmaps.
05:38A near and far version of each map is created.
05:42The near only contains Indirect Illumination, Full Illumination from Baked Area
05:47Lights, Emissive Materials, and Skylights.
05:50The far version is a full solution version that is used beyond the Dynamic
05:54Shadow Range and includes Shadows.
05:58Directional Lightmaps allow normal maps to be included so Specular and Bump data can be seen.
06:04Let's move the dialog aside and look at our Scene view for a minute.
06:09In the Scene view's Lightmap display, you'll be able to set the Shadow Distance.
06:13This is the border where the Near Map plus the Dynamic Shadows are faded into
06:17the far maps and no dynamic shadows. It can be found in the Quality Settings as well.
06:23With our good-quality preset, we are using 40.
06:27Back in the Light Mapping dialog, Use in forward rendering, is a check box that
06:32should only be checked if you're planning on making Custom Shaders.
06:36The Quality presets are a quick way to set up baking without spending days and
06:40days tweaking and comparing results. We have a choice between High and Low.
06:46Bounces will bounce the lighting, more Bounces means brighter solutions, but
06:51slower calculation times.
06:53Towards the bottom, Ambient Occlusion is available for both free and Pro versions.
06:58Ambient Occlusion is calculated independent of scene lights, it's the stuff
07:02that darkens nooks and crannies by deciding how occluded or blocked the faces on the model are.
07:09If your meshes are fairly low poly, with little concave areas, they probably won't
07:14benefit much from Ambient Occlusion.
07:16Higher detail meshes, on the other hand, will have details pop out as the cracks
07:21and crevices are darkened. The last section is about light maps.
07:25It lets you set overall resolution, or map scale, as well as Padding.
07:29Padding is the amount of space between pieces on the light map.
07:33Small maps may need more Padding to prevent colors overlapping into each other's pieces.
07:38The Lock Atlas check box allows you to prevent a piece from recalculating
07:42the mapping layouts.
07:44And finally, in the last section, Maps, you'll be able to see the rendered maps
07:49and their index numbers once we have some to look at.
07:53Light Probes are a means of adding to dynamic shadows with localized areas that
07:58will contribute radiosity and emissive lighting effects in real time.
08:01They are beyond the scope of the Essential series.
08:06Let's go ahead and turn off Show Resolution in the Light Mapper display before
08:09we close the Light Mapper.
08:12So that's our run down of the basic features in the Beast Light Mapper.
Collapse this transcript
Experimenting with Beast
00:00If you've already baked light into the main level you know how long that can take.
00:04So before we bake the lighting in to main scene, let's try a few experiments
00:09in a smaller scene.
00:11Most of these will be with pro features, but a few will pertain to free as well.
00:15If you are using Pro make sure that Deferred Lighting is being used.
00:21Let's start by saving our current scene, then creating a new scene named light tests.
00:27File > Save Scene, File > New Scene, and File > Save Scene as, Light Tests, and let's
00:36remember to put it in our Scenes folder.
00:39Now we need to Import the Lighting Room package from the exercise files into our Project.
00:45Right-click, Import Package > Custom Package, up to our Assets folder, and
00:54LightingRoom, and we'll click Open and Import. We can find it in the imported Assets folder.
01:02In the Inspector, we can see that Generate Light Map UVs has already been checked.
01:08Let's go ahead and drag the LightingRoom asset into the Hierarchy, and we'll
01:12double-click on it to see it in the Scene view. And I am zooming in using my
01:17middle mouse roller, and I will just rotate it a little.
01:21Right now, we have no lights, so let's see what we can get with Skylights in Beast.
01:26Let's select all of the objects, or the parent, and click Static.
01:34Yes to, change children.
01:36Now we'll go ahead and open the Light Mapper from window, Light Mapping
01:41and click Bake Scene.
01:46If you toggle the Scene Lighting on, you can see the results, nothing.
01:51In the Maps tab, we can see the dual light maps and the Size shows 2.7 megs of well, nothing.
02:02Let's turn our Skylight Intensity to one and see what we can do.
02:07In the Bake tab, Skylight Intensity which was zero, we are going to change to
02:13one, and let's Bake Scene again. And now we can see our two light maps.
02:19In case you're wondering whether the scenes ambient light affects the baked
02:23light maps, we ought to test for that too.
02:26In the Render Settings, let's go ahead and turn the Ambient to 0, Edit > Render Settings,
02:33and we'll turn our Ambient Light to zero, and bake the scene again.
02:43Scene Ambient is definitely baked in.
02:46So let's go ahead and set it back to 50 before we move on, Edit > Render Settings >
02:52Ambient Light, and we'll bring it back up to about 49 or 50.
03:00If we look at maps in the preview they still look pretty much the same.
03:04That's because the only light so far is the GI type, Global Illumination.
03:10So let's go ahead and add a sun to the scene, a directional light.
03:13GameObjects > Create Other > Directional Light.
03:19And I am going to drag it up so I can see it easier, and we want to set its
03:23Shadow Type to Soft Shadows, and let's rotate it so we get a shadow off the
03:30right side of the room. I am going to set it 45, -90, and 45.
03:37And we'll Bake the scene again.
03:42Since most of the objects were in the shade, the map still looks similar, but if
03:47you look closely you should be able to see the shadows from the direct light
03:51only in the far map.
03:52Let'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:00This means all shadows in the scene are baked and coming from the far map.
04:05If we rotate the light coming from the right, since we have our Directional Light
04:09selected here, if we rotate it, we see no difference.
04:15As soon as I increase the Shadow Difference, we'll see when the dynamic light
04:20kicks in, and it's right about there.
04:24Let's go ahead and set our rotation back to 45, -90, and 45.
04:31So now let's see what happens if we Bounce Light.
04:35Right now we don't see any radiosity from the two colorful primitives.
04:39Let's add a point light inside there with them.
04:42So GameObject > Create Other > Point Light, and then we'll set its range at about
04:504 and its intensity to about 0.5.
04:56And I'm going to move it kind of over in the corner, then we can see it
05:01shining on the walls.
05:03We also want to tell it to have hard shadows, and then we can go ahead and
05:09Bake our scene again.
05:12If I zoom in close, I don't see any Radiosity from either the red or the green.
05:19Let's set our Bounce Boost and Bounce Intensity up and see if we can get some results.
05:26We'll bake the scene again.
05:29It's a little bright, but now I'm getting a little bit of a pinkish area around the box.
05:34So we'll just set it back to what it was before.
05:37I'm going to set it back to 0.5, and 1, obviously we need to turn down the
05:42intensity of the regular light to get the full effect on this.
05:45Next, let's find an emissive shader from Emissive Shader Material for the walls light panel.
05:52I'm going to zoom out, and if I rotate around we can see this panel here, and
05:57I'm going to move our light mapper for a minute, and in the Lighting Room there
06:05is our Light panel, and for Emissive we are going to change this material to one
06:12of the self-illuminated shaders.
06:14Self Illuminated Diffuse should be just fine, and I'm going to set my main
06:19color to a nice magenta. We'll go ahead and bake the scene again.
06:27The Emission on that material was set to 2, and yes there's plenty of my
06:32magenta showing now.
06:34In case you're thinking that this would bake a good TV screen, let's pop an
06:37image into the slot and see what we get.
06:40I'm going for one of the leaf materials, ColocaLeaf, and once again we'll bake.
06:48I should have turned the magenta off first. Let's do that and rebake it.
06:52You are seeing lots of green on the surrounding walls now.
06:59Before we switch lights, let's try something else.
07:02Let's select the Point Light again, in the Hierarchy, and in the Inspector let's
07:08tell it, under Light Mapping, to use Baked Only. Now the huge specular spot on the walls is gone.
07:16It won't light something dynamic that comes into the scene, but the light map
07:20looks much better without it.
07:23As long as we've got it set to Baked Only, you may want to go ahead and try an
07:27Area Light, if you do be sure and change the Point Light to an Area Light and
07:32then reduce its intensity quite a bit.
07:35Now that you're familiar with the basic process, feel free to tweak the settings
07:39and experiment on your own.
Collapse this transcript
Baking the game scene
00:00Now that we've gotten pretty comfortable with lights, lighting and baked light,
00:04let's finish up a few things in the game scene.
00:07We'll need to start by saving this scene, and opening our main level.
00:14And I'll go ahead and zoom in on the fountain.
00:17In the Structures for Scene, we want to turn all of these to Static up in the
00:23Inspector and Yes, change the children.
00:27Some of the doors animate, so we better turn off Static for all three doors,
00:32Sliding Door Left, and Right, and Solid Door.
00:39The Main Building Interior, and Stairs Interior, already have light maps, so we're
00:45going to select them and open light mapper again.
00:50Main Building Interior, and Stairs Interior. From Window open Light Mapping,
00:59and since they already have their light maps, we're going to set their Scale to zero.
01:04To use imported light maps you can use the legacy shaders light map shaders or
01:11if you have newer versions of Photoshop, you should be able to use the same file
01:15type as Beast and add the maps manually into the array.
01:19The Main Building Basement is also a special case.
01:23It should be pretty much in the dark.
01:25We'll need a flashlight to find our way through it.
01:27So it really only needs a small far and near map.
01:31The scale tops out at one being full-sized in relation to the rest of the objects.
01:37Let's select the Main Building Basement and set its Scale to 0.01.
01:44Now we need to do a little fiddling.
01:48If we turn the Ambient Light off while we bake light, and use Skylight instead,
01:52we'll get a nice solution, but with no ambient our dynamic objects will be too
01:57dark, so then we can turn Ambient up to match after baking.
02:03Once an object is using baked lighting, it no longer receives ambient because
02:07it was already baked in.
02:09So let's turn our Ambient Light to 0, once again Edit > Render Settings, and Ambient.
02:17And one more thing.
02:21We'd better turn the Trees back on because we need shadows baked for them.
02:27Select the Terrain, and in Settings I'm going to check, Draw, and our Trees are
02:35back, and now we can bake scene.
02:39Let me cancel that, I need to turn up the Skylight first.
02:43So in the Bake tab I am going to set my Skylight to 0.5.
02:48Now I'll go ahead and bake scene.
02:50In case, you're wondering about what happens when you add more static measures
02:54to the scene sometime down the road, the answer is simple, you have to rebake
02:58everything, and if you're tempted to try Bake Selected, it does just as it says.
03:04It bakes the solution using only the selected objects.
03:07So anything not selected will not be used in the calculation unless it has
03:12a scale set to zero.
03:14The worst thing, though, is that it clears all the other maps.
03:18Fortunately, they've hidden the Bake Selected object in the Bake Scene button
03:22dropdown in this version.
03:24If you are used to baking lighting in your modeling app, you're probably used to
03:28being able to bake things selectively.
03:30Just remember, in Unity, Light Mapping is more of a final solution, and there we go.
03:37Now that Beast is finished, we can focus on the barrels or some other dynamic
03:41object in the scene and move them into the shadows.
03:44Ours are actually pretty good, some are in and some are out of the shadows.
03:48So now we need to adjust the Ambient to match.
03:52From Edit > Render Settings > Ambient Light, I want to bring up the Ambient
04:01Light on the shadow part of the barrels, until it looks like it matches the rest of the scene.
04:07And it looks like somewhere around 55, it starts to look correct.
04:15With a little tweaking, my Dynamic and Baked Lighting is working together nicely.
Collapse this transcript
Creating lighting effects
00:00There's lots of nice light related effects we can play with, but first we'll
00:04need to import a couple of Unity packages.
00:07Let's start with Light Flares, right-click, Import Package, and select Light Flares.
00:16Import, and then let's select the scenes' Directional Light.
00:21From Component > Effects, choose Lens Flare.
00:28Lights have a Lens Flare section, but you will get more control with the component.
00:32Let's select Sun for the flare.
00:37If we click Play, and look up to the left, we'll see our sun flare.
00:44I'm hitting Escape to prevent the view from spinning.
00:47Exit Play mode, and let's try a different one.
00:51Let's try the 50mm zoom, click Play, and look up again, and now you see
01:00the typical Lens Flare.
01:04I'm hitting Escape, to prevent the view from spinning, and then I'm exiting Play mode.
01:11The docs say to use these sparingly, they have become a bit of a cliche, so
01:15use your own judgment. I'm switching mine back to just the Sun flare.
01:19Visually related to lights are the nice volumetric areas that are seen in dusty places.
01:25Pro has a shader for God rays, but we can get a nice cheap version with a line renderer.
01:32We used it earlier for the laser beam, but it's ideal for billboarded objects of any kind.
01:38The main thing to remember with the Line Renderer is to turn off use World coordinates.
01:44They take a while to set up though, so I've included a Prefab complete with a
01:47spotlight for use with the hanging lamp. It came in with an earlier package we imported.
01:54So all we need to do is find it in the Prefabs folder, FakeVolumetricLight and
02:00drag it into the Hierarchy. Let's double-click it to see where it came in.
02:05It should be deep in the basement, and there it is near one of the entry doors.
02:16I'm going to turn off Overlays in the Scene view so we no longer see the cross hair.
02:22And finally, we'll take a quick peek at projector lights.
02:26So let's import two more packages, right-click, Import Package, and this time we
02:33want Projectors, Import.
02:36And right-click, Import Package, and we want Light Cookies.
02:45And once again, Import.
02:48Let's focus back on the barrels to get us out of the basement, and I'll zoom back a ways.
02:56Let's locate the Projector's folder in the Standard Assets folder, and I'm going
03:00to go ahead and close up some of my folders. And here is our Projector's folder.
03:05And we're going to drag the Blob Light Projector into the scene in a shadowed area.
03:10So the Blob Light Projector, and I'm going to bring it right about here.
03:16And now we need to lift it up, until we can see the effect on the ground.
03:23These are the little creatures you often see parented to the characters in those
03:27three-quarter overhead games like World of Warcraft, and countless other world
03:31building strategy games.
03:33You could try a couple of textures out for the cookies, and we can see quickly
03:37that they will always need to set to clamp.
03:40Let's delete the Blob Light Projector now and try his opposite number, the
03:45Blob Shadow Projector.
03:48Right-click, Delete, and this time we'll bring in the Blob Shadow Projector.
03:54And I'm going to drag it into a sunnier area, and it needs to be lifted up as
03:59well, and we can see it casts the blob shadow.
04:05This guy is regularly seen parented to characters in games where real-time
04:09dynamic shadows are either not available or are too costly.
04:13With some careful tweaking, I have repurposed this one to add an ominous
04:18darkness to the smoky area.
04:20Let's import the Ominous Darkness package and drag it in from the Prefabs folder
04:25into the Hierarchy view.
04:27So right-click, Import Package > Custom Package, and from our Assets folder,
04:34we're going to bring in OminousDarkness, and click open, Import, and that guy
04:42should come in the Prefabs folder.
04:47Here he is right here, and I'll bring them into the Hierarchy.
04:51And if we double-click him, and rotate our view around, we can see that our once
05:01sunny area is now dark.
05:04If you want to see the difference you can deactivate, then activate.
05:09For even more fun, I've created a falling ash particle system that you can toss
05:13in that area as well.
05:16Let's bring that package in and put it into the scene, right-click, Import
05:22Package > Custom Package > Assets, and FallingAsh, Import, and we'll drag him into
05:34the Hierarchy panel. And there it goes right there.
05:40Before I click Play, I'm going to click on Maximize on Play so we'll get the
05:45full effect, now click Play, and let's drive into our ominously dark area
05:55now, by pressing W.
06:01And we can see now falling ash, smoke and fire, and darkness.
06:11And now we can go ahead and exit Play mode. I'm clicking Escape first.
06:18So now you can see how light, and light related effects, can add dramatically to your scene.
Collapse this transcript
Adding a flashlight
00:00In the basement area, our player might need a flashlight to find his way in the
00:05dark, since there's nothing new involved, I've prepared a flashlight Prefab to
00:09help us get the player through the dark.
00:11Let's start by importing the flashlight package and dragging the Prefab into the hierarchy view.
00:16Right-click, Import Package > Custom Package > Assets, and let's open our Flashlight, and Import.
00:30From the Prefabs folder, we'll go ahead and bring it into the hierarchy.
00:35To get started I'm first going to double-click on my first-person controller, so
00:41we can see him in the scene view.
00:46Right now he's facing the barrels, let's go ahead and turn him around, so he's
00:51facing the cliff wall, now we can select our flashlight and use, Move To View,
01:02to get him lined up with the player, and we'll need to rotate it, until we can
01:10see our flashlight in front of him, and that's probably a pretty good position right there.
01:15So now I'm going to go ahead and open the first-person controller's main camera,
01:21and I want to put my Flashlight in with my Weapon Handler.
01:25When we made our original Cannonball projectile, we fired it directly from the
01:29Update function in the projectile script.
01:32Now that we have a flashlight to handle, we can make the whole process much more
01:36generic by separating it out into a separate script, it will send out the fire
01:41message to which ever weapon or other device is currently active, in the
01:46Flashlight's case, Fire will toggle it off and on.
01:50So let's make a new script in our game scripts folder and call it Trigger Finger.
01:56Right-click, Create > Javascript, and we'll name this one TriggerFinger, and
02:03we'll open it in the Script editor. Double-click.
02:07In the Update function, we're going to be checking for the fire one button,
02:11you remember it, it's a virtual button defined in Unity's Game settings Input Manager.
02:17I'm going to go ahead and get the first bit of code from the snippets file.
02:20I'll go out to the desktop, Exercise Files09/09-08, and open my code snippets,
02:30and I'm going to copy this whole first section, right-click, Copy, and we're
02:36going to put this one inside the update function.
02:40So BroadcastMessage is a cousin of SendMessage, where SendMessage calls the
02:45specified function on any of the game objects components, BroadcastMessage calls
02:51it on the game object and all of its children's components.
02:55That means we'll be able to add different weapons or tools and trigger them all
03:00from the same script, as long as they have a fire function to do the work.
03:05Let's save the script and return to the editor.
03:09And now we'll drag the new TriggerFinger script onto the Weapon Handler and
03:14deactivate the Proxy Weapon, and we'll select the Proxy Weapon and deactivate it.
03:22Let's click Play and toggle the Flashlight off and on.
03:25That's either using the left mouse button or the Ctrl Key, Ctrl-Off and Ctrl-On,
03:32and we'll exit Play mode.
03:36The Flashlight already came in with the script, it's called Toggle Light, I'll
03:41open it, it's pretty simple.
03:42It has the usual stuff we need to prevent it from firing over and over again on a single input.
03:50Let's go back to the editor and make sure that the Proxy Weapon still works.
03:55I'm going to deactivate the Flashlight now and reactivate the Proxy Weapon.
04:02I'm also going to turn off Maximize on Play.
04:06So now when I click Play, and click on the Fire button, there we go, so it still works.
04:18Let's exit Play mode, I also need to turn Gizmos off in the window.
04:22So now we need a way to toggle between the flashlight and weapon, or maybe even
04:28cycle through any number of weapons, we'll do that with a keyboard key press,
04:33I'm choosing keyboard number pad 0, let's head back to the TriggerFinger
04:38script, and we're going to start by adding a variable for the current weapon,
04:44var, and I'm going to call it currentWeapon, and that's been a being of type
04:49int, because this is just a number assignment, and we'll go ahead initialize it to zero.
04:56This script is going to allow for multiple weapons or gear, so we're going to
05:01need to see how many children are in the Weapon Handler object, right now it
05:05just has two, but we need to give it a variable as well, and that we're calling
05:10totalWeapons, and it also is of type int.
05:14For the start function, I'm going to go and get the code from the Snippets file,
05:18and this is the line we want.
05:22Right-click, Copy, and then the Start function, we're going to assign a value to
05:30totalWeapons, and we're doing that with transform.childCount, childCount gets
05:37the number of children from the parent.
05:40In the Update function, we'll increment the weapon, then call a function to do
05:44the actual work, and I'm going to get that from the snippets file as well, and
05:49we'll copy this guy,
05:51right-click, Copy, and we're going to Paste this one,
05:56right-click, Paste beneath the fire one message.
06:02In this section the brackets around the zero tell us to check for the zero on
06:07the number pad, next we increment the current weapon by one, then we do a check,
06:12if that number is greater than the number of child objects we set it back to the
06:17first, element zero,
06:18and finally, we call the function that does the work, it looks like I missed the
06:23closing bracket for this bit of code, I'll just add it in now.
06:28Next we need the select Weapon function, it includes something we haven't yet
06:33used, a for to statement, that lets us iterate through an array, and that's what
06:38the children of an object are internally packaged as, an array.
06:43I'm going to get the code for that from the snippets file.
06:47And I want to make sure I get the closing brackets for that,
06:52right-click, Copy, and this is a different function, so down below my Update I'm
06:59going to use Ctrl+V to paste it in.
07:03A for loop uses a variable, traditionally I, and that's assigned the first
07:08value, in this case zero, the first element of the child array, and an end
07:14value, which is going to be the child count, which is just the length of the
07:18array, and finally instead of changing its active property to true or false
07:23directly, we use set active recursively. That will apply the value to the object
07:29and any of its children. And finally we need to add a line to the Start function
07:34to initialize the first weapon.
07:36In the Start function we're going to call our SelectWeapon function and pass it element zero.
07:45And now we can save the script.
07:49I'm going to deselect my Proxy Weapon, and then we'll click Play and use 0 on
07:54our keypad to cycle through the weapons, we should be able to see them become
07:58active and inactive as well as change in the scene.
08:03So clicking Play, I click my 0, and the Proxy Weapon is active, click it again,
08:09nothing is active, and I click it again, and now the Flashlight is.
08:14Let's go back and see why it turns both off before it restarts at zero, and
08:19let's exit Play mode.
08:20Let's go back into our script and see why it cycles through Flashlight, Proxy
08:25Weapon, and neither before it starts up again. Because we've used greater than
08:31total weapons here, instead of greater than or equal to, we get one number
08:35that's outside the child count number, this works in our favor because now we
08:40can have no weapon, the flashlight, or the proxy weapon, and we'll head back to the editor.
08:47Now the only issue is the Crosshair, if we made a child of the proxy weapon it
08:52would inherit its parents transform and would quickly go missing, so let's
08:56just disable it for now.
08:58When we get to the chapter on Unity GUI we'll be able to replace it easily, so
09:02I'm going to select the Crosshair here and deactivate it.
09:07In this video we've used a for loop to iterate through an object's children
09:13and then used set active recursively to change the state on all of the
09:18children's children as well.
Collapse this transcript
Exploring waypoints and death zones
00:00In the next chapter we'll be moving our player onto a new area, a platform
00:04jumper setup over the chasm. And, of course, the first thing he'll try is
00:09jumping into it. So let's start by moving our first-person controller to the lower platform.
00:15I'm going to focus on the lower railing rope to get there quicker.
00:19In Structures for Scene, inside the building group, I'm going to double-click on
00:24Lower Railing Rope, and use Alt and my left mouse button to kind of spin around a little bit.
00:30And now I can go up and get my first- person controller, and use, Move
00:37To view, to get him there quickly. I'll need to move them back, and I want to
00:42make sure that he's at a good height above the floor, if he intersects it he
00:48might drop through it, so I'm going to leave them a little bit higher, and we
00:53want to click Play and make sure. Yep, and he stays put, so he's good.
01:02I also want to spin him around, so he is facing out towards the other side,
01:09let's click Play, and see how helpful the chain is from keeping us from going over.
01:14I'm going to click Play, Click W, and then I'm hitting my spacebar, and I'm
01:21falling off into the abyss. So let's click Escape and get out of Play mode.
01:29It turns out the guardrail doesn't do a very good job, we can jump over it into the abyss.
01:34A common feature in several different genres is, the death zone. As soon as the
01:40player falls somewhere where we don't want him to have access, we move him to
01:43either a preset or maybe even a random location.
01:47These instant destinations could be referred to as spawn points, especially when
01:51instantiating enemies or other Prefabs.
01:54When used as goals, as in a racing game, they are often called waypoints.
02:00Let's make a spawn point at the first-person controller's position.
02:04Let's focus in on his current position in the Scene view and make a new empty
02:09game object, Create Empty, and we'll name this one Waypoint Start.
02:17It's created right where we want our first- person controller to appear after a fall.
02:22Now let's make a cube and name it Death zone,
02:26GameObject > Create Other > Cube, and now we're going to want to rotate our view
02:34a little bit and zoom out, and we will want to move this out towards the center
02:42and then scale it both directions, and let's rotate our view again and maybe
02:52we'll give it a little bit more height.
02:54And then we're going to drop it down into the chasm a little ways, we'll just
03:02give him a little way to fall before it catches him.
03:05We really only need its box collider, so you can remove the mesh render if you
03:09want, and then we need to set our Box Collider to Is Trigger,
03:14right-click, remove the mesh render, and for our Box Collider we're going
03:20to turn on Is Trigger.
03:22Now for the script. Let's create a new script in the Game Scripts folder.
03:28Right-click, create Javascript, and we're going to name this one Death Zone, and
03:34we'll double-click to open it.
03:38On the off chance we want our player to come back to life on different spots
03:42we'll make the waypoint variable an array, so let's add, var waypoint, of type
03:54Transform, and to make it an array we give it our two brackets, and once again
04:02auto complete adds things that I don't want.
04:06So let's save the script and go back to the editor and drag the Death Zone onto
04:13the Cube Object which I also need to remember to name Death Zone.
04:20In the Inspector, let's open up the Waypoint array, and since we only have
04:26one spawn point, let's set its size to one, and we can drag our waypoint
04:31start object into it.
04:35And I'm going to go out to the snippets file and grab our on trigger inter function.
04:40Exercise File09/09-09/Code Snippets, and I'll copy all of the OnTrigger Enter function,
04:52right-click, Copy, and because it's a function, I'm going to Paste it, Ctrl+V, in
05:00below the other functions, so we can save our script now.
05:05Before testing, we need to make sure that the first-person controller is
05:08tagged as a player.
05:11So we'll select him, and change him from Untagged to Player.
05:19Now let's click Play and test.
05:22If I run him off the ledge with my W Key he falls, and then he has popped right back up.
05:29So let's exit Play mode.
05:31Just in case you want to spawn them in different places, let's add the code
05:35to choose a random position from the array of waypoints, I'll get the next
05:39bit of code from the snippets file first, and I'll scroll down, and first we need a variable.
05:46I'll get the next bit of code from the snippets file, and back in the script
05:53editor, inside the if clause, I'll paste it in.
05:59I'm assigning a random number between zero and the length of the wave point to a
06:04variable called element.
06:06I'm going to go out and get the next line of code.
06:11Right-click, Copy, and this one replaces the victim line, Ctrl+V for Paste, and
06:21instead of zero in here, we have element, which is going to be the random number.
06:27I'm going to tidy that up a little bit.
06:29So I'll save the script and head back to the editor.
06:34Now that we've made a Death Zone you might want to put another one below the
06:37water over at the waterfall and give it some suitable waypoints of its own.
Collapse this transcript
10. Keyframing Animation
Platformer setup: Snaps and cosines
00:00In this chapter, we'll be delving into a lot of keyframe animation.
00:04Before we do, though, let's get some new assets to play with.
00:08The new zone is the Platform Jumper Zone.
00:10It lies over the chasm, so let's import the Platform Jumper Assets Start Package.
00:17Right-click, Import Package > Custom Package > Assets/PlatformJumperAssetsStart
00:29and Open and then Import.
00:35It contains some platforms, a couple of invisible walls, obstacles, and some power-ups.
00:41Let's drag the new Prefab Platform Objects Start from the Prefabs folder
00:46into the Hierarchy view.
00:47It should be aligned with the lower ledge where the basement lets out.
00:51And it looks about right. Let's start by deactivating the invisible walls.
00:56They'll keep our player from falling sideways 'til we deal with the navigation scripts.
01:01Open the Platform Assets Start and the top two, Invisible Wall Left and Invisible Wall Right.
01:10Unity has a very robust vertex snapping system. Let's use it to tidy up the first few platforms.
01:16I am going to pan over a little bit, and I might want to turn off my Scene Lighting.
01:23We start by selecting the object we want to move, I am going to select the
01:29second platform, and then we hold down the V key--V as in Victor--as you move
01:34the cursor around, it snaps to the various vertices.
01:38With my V key still down, I am now going to click and drag, and it snaps to
01:45the closest vertex. Let's try that again.
01:49I'll select this platform, press my V key, move my cursor over it and drag it
01:56until it snaps to the correct vertex and my view over it looks like this guy's
02:01a little high, so I am going to select him. This time I'm going to snap to the
02:06lower vertex, so I press my V key, click and drag, and I want to snap it to the bottom vertex.
02:15And always use your Alt and sort of rotate around and make sure you've got everything correct.
02:20You can also snap objects in units around the scene by holding the Ctrl or
02:24Command keys while moving the objects.
02:28I'm going to press Ctrl and pull up, and you can see that as the mouse moves the
02:37platform snaps to--it's probably set to 1 unit as a default.
02:42You can change the snap amounts from Edit > Snap Settings.
02:50Before you go off adding more complexity to the platform setup, let's make a
02:54couple of scripts to animate the platforms.
02:57The scripts will be very useful and generic, well worth the effort.
03:01So let's create a new script and name it V_position cycler.
03:06In my Game Scripts folder, right-click, Create > Javascript, and this is going to be
03:15V for vertical, underscore PositionCycler, and well go ahead and open it by
03:25double-clicking to get to the Script editor.
03:29Since we started a new chapter, let's go ahead and take the opportunity to clean
03:33up some of our open scripts. I'm going to close them off in their tabs.
03:40We are going to need several variables for this, so I'm going to go over to the
03:43Snippets file and get them.
03:46Exercise Files10/10_01/Code Snippets. And we want all of these.
03:56Right-click, copy, and we'll make some room for them up here and Ctrl+V to paste them in.
04:06This is for the vertical scroller so we've got an upRange and a downRange, and
04:12we've got a waveOffset, I'll explain that in a minute.
04:15We also have the Y Start Position, so the upRange and downRange are going to be
04:20added to the start position so it knows where to cycle between.
04:25In the Start function we'll need to get the starting position, the object's current Y location.
04:30I'm going to go out to Snippets and get that one to.
04:35Right-click, Copy, and this one goes in the start function and Ctrl+V to paste.
04:44And now we are going to change our Update function to a FixedUpdate, and this is
04:49so that the speed will be the same across all platforms, and that's got quite a
04:53bit of stuff in it, so I'm going to get this.
05:00Right-click, Copy, give myself some room and Ctrl+V to paste.
05:08So let's see what we've got. The first two lines calculate the position from the
05:12offset and the up and down range.
05:14By putting them in the Update instead of the Start function, you can adjust
05:18positions at runtime without restarting each time.
05:21The next line is the Mathf cosine function and uses the variable's values to
05:27adjust the speed and height of the cosine wave.
05:30waveOffset adds an offset to where we are in the cosine curve, and the last line
05:38adds it all up for the platform's position. If the math is confusing, don't panic.
05:44As you get more confident with scripting, you'll find tons of script from the Unity community.
05:49Bottom line, as long as you can figure out what it does and what it needs,
05:53you don't necessarily need to understand how it does it.
05:57Let's save the script and head back to the editor.
06:01Now we want to go ahead and drag the script onto the Platform Short Move V object.
06:08So here is my V_positionCycler script, and I want to move onto PlatformShort,
06:13Move V, that will be this one right here.
06:18Let's go ahead and deactivate the Terrain for now.
06:24Select the Terrain, and we'll just deactivate the whole thing.
06:28To get an idea of how far to raise that platform, we can use the Ctrl or Command
06:33key to snap while moving it up, then move it back down.
06:38I'm going to zoom out a little bit, adjust my view, select my platform, I'm going to
06:45hold my Ctrl key, and then count as it snaps upward.
06:491-2-3-4-5-6-7-8-9.
06:56So it looks like I'm going to need to move it up about 9 on the vertical.
07:05I can't see my variables here, so I am going to go back and make sure that my
07:09script got saved properly.
07:12And into the Script editor by double- clicking, and sure enough it wasn't.
07:17So I'll save back my scene. And now I've got my variables.
07:22So we decided that the upRange needed to be about 9 units, and I'll leave the downRange as 1.
07:29Let's click Play and see how it works.
07:35It goes down 1 and up 9, and we'll exit Play mode.
07:42The platform moves up and down using a nice cosine wave for speed and height.
07:46The horizontal version is pretty much the same, so I have included it in the
07:51Videos Asset folder and also in the snippets file.
07:54You can pull the script into the Game Scripts folder using Import New Asset.
07:58So I am going to select my Game Scripts folder, right-click, and Import New Asset,
08:06and here it is, H_PositionCycler. Import, and there we go.
08:13I am going to put this one on PlatformLong Move H, and I'll select it, and mine
08:21ended up needing to be about 16.8 to the left, and I slowed it down quite a bit
08:27and set the speed to 0.1. You can hit Play and test it if you'd like.
08:31We'll be taking a shortcut through the platforms to get the game developed
08:35quicker, 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:00For simple looping animations, scripts can be very useful. Once you get the
00:04formula worked out, you can apply the script to any object, adjust the
00:08parameters, and you're good to go.
00:10But for one-off animations or complex animations there is nothing like good old
00:14keyframing to make things look good.
00:17Besides the platforms, we also got a Heart and a key Prefab added to the Prefabs folder.
00:22Let's drag the Heart into the scene over the first couple of platform sections.
00:28In my Prefabs folder here is my Heart, and I'm going to drag it into the scene,
00:34and I can see it is sort of embedded in the platform, so I know it's going to be
00:39in a pretty good position, and then I'll go ahead and drag it up.
00:43We can use the scene gizmo to get to a right view by clicking on one of the side
00:49arrows, left, back, and right, so there we go.
00:54Then I am going to move it just high enough so that the first-person
00:59controller has to jump for it. And we'll go ahead and zoom in, and there we go.
01:04So now, let's go ahead and create a new camera so we can see it in both views,
01:08the scene and the game view.
01:11Game Object > Create Other > Camera, let's leave aside the Listener on for now.
01:18We'll need it when we disable the first-person controller's camera.
01:22Now from the Game Object menu, we'll use Align With View.
01:28In the Inspector, let's adjust the field of view down, so it looks similar to the scene view.
01:34And that's pretty good!
01:36If we click Play, the view might shift slightly, but we'll have a pretty good
01:40view of our target objects.
01:42So let's go ahead and look at Key Frame Animation.
01:44From Window choose Animation.
01:50The widow comes up showing the main camera, the object that's currently selected.
01:54Let's expand the camera component.
01:56Any variables exposed to the Inspector are also exposed in the Animation View.
02:03Now let's go ahead and select the Heart.
02:07We need two things before we can animate with keyframe animation, the first is
02:11an animation component, and the second is an animation clip.
02:16As soon as we create a clip, the animation component will be automatically added.
02:21So let's click in the blank area next to the object name bar, the option to
02:26Create New Click pops up.
02:28Let's select it. The browser opens up to our Assets folder.
02:33The key Prefab already has a couple of animations, they are in a folder called
02:38AnimationClips, and we're going to go ahead and use that for all of our clips.
02:41So I'm going to open my AnimationClips folder, and I want to name my new animation heart beat.
02:49All lowercase isn't really necessary, but it will help me remember when I'm
02:53working with an animation clip, and now we can click Save.
02:57In the Inspector we can see the animation component that was automatically added.
03:02In the animation view, let's go back and select the three scale tracks.
03:08Before anything can happen, we also need to click the Play button, that's the red dot.
03:14Now we can see current values, a time indicator at frame 0, and we also note
03:21that the Play controls at the top of the editor have turned red to remind us
03:26that we're in record mode.
03:28The first thing we want to do is set a key for the selected tracks to define the
03:32start frame of the animation.
03:34That's the little button with the Add Keyframe tooltip, the one to its right is Add Event.
03:40Don't click that one by mistake.
03:43So let's go ahead and click the Add Keyframe button.
03:46A white key is added at the top of the timeline, this is similar to a dope sheet
03:51that shows the keys on the timeline.
03:54In the list, the track keys are color coded a pale red, green and blue. RGB equals XYZ.
04:02When animating more than one track like we are with scale, it's usually easiest
04:06to do it in the viewport.
04:08So to start our animation, the first thing we need to do is to move the timeline
04:13indicator to where we want the animation to finish up.
04:16The timeline shows seconds and frames. The default is 60 frames per second.
04:22So let's move our indicator to 1 second, that's also 60 frames as we can see over here.
04:28Now in the Scene view, let's go ahead and scale the Heart up to about 1.3, and
04:36I'll be watching the Inspector in the scale section to see my numbers.
04:44And that's close enough, the curve--yes, it's called a curve even when straight--
04:49doesn't appear to have changed.
04:51But let's go ahead and click the Animation View's Play button. The animation
04:58plays, looping in the viewport, and as soon as you click it again, the graph is
05:04automatically zoom to fit.
05:06We can also scrub through the animation manually by dragging the indicator up on the time bar.
05:13The frames show to the left of the Add Keyframe button.
05:18So let's see about improving the animation.
05:20If we drag around the keys at frame 60-- yes, there's three in one spot--and
05:25right-click, we can change them to free smooth to get the Bezier handles that
05:31will allow us to affect the curves.
05:33For those of you who know your way around curve editors, you can also set the
05:37in and out tangent separately in the right-click menu.
05:40So let's make some changes. Grab the handle for each key and drag it up level
05:45with the non-animated part of the curve.
05:47I'm going to click, and again, and one more time.
05:56And we'll repeat for the keys at frame 0.
06:00Drag a region, right-click, Free Smooth, and we'll drag the handles down.
06:09We now have a classic ease-in/ease-out curve.
06:13If you're new to curve editors, reading them is easy, time is always on the
06:17horizontal, and the value that is getting changed is on the vertical.
06:22So the flatter the curve, the slower the animation, that's less change over time.
06:28The steeper the curve, the faster the animation, more change over time.
06:33A change in direction of the curve will make the values go backwards.
06:37So our animation starts out slow, speeds up, then slows back down. Let's click Play.
06:46It's a little hard to see the results, so let's slow down the animation a bit,
06:51and we'll stop play for a minute, and we are going to click the white key in the
06:55timeline at 1 second.
06:57I am going to drag it to 130. Let's exaggerate it and move it to 2.
07:07Now we'll click Play, and you can see it's a lot slower.
07:15We'll Stop Playback again, and maybe we want to adjust the amount of scaling.
07:20We could move the time indicator to its new position in the timeline, then
07:24adjust it in scene view again, but for more control, we can enter numbers
07:29directly in the track we want to change. So we could change them here.
07:34We could also move them in the graph itself. So let's see what happens in the actual game.
07:39We'll close the animation view and click Play and nothing happens.
07:46Let's Exit Play mode again. Let's look over in the animation component to see if
07:51we can figure it out.
07:53It is set to play automatically, but there's no clip selected as the default animation.
07:59Let's open the Animations array, it shows one clip, heart beat, but we can't drag
08:04it to the animation field from there.
08:07If we click on the browser to load our default animation, all kinds of animation
08:12clip show up which should remind you that naming your clips well is important.
08:17The best way to get it loaded often is to click on it in the array located in
08:21the project view and drag it in.
08:24It is pretty easy to figure out which one we want here, so I'm going to select it.
08:29Now let's click Play and Exit Play mode.
08:33As you might have suspected, it scales up and stops.
08:36To control looping and related properties, we can either select the clip itself
08:41and change its wrap mode in the Inspector, so I'm going to go up and find it
08:46here, Animation clips, here is heart beat.
08:52So we can change our wrap mode here. I'll set it to Loop. Or our other option is
08:59that we can open the Animation Window--and of course we need to select our
09:05object, make sure we are on the right clip--and down here to the right we can
09:12choose from here as well.
09:14And this one really should Ping Pong, so I'm going to change it to Ping Pong.
09:18If we zoom out in our graph--and we can do that the same as zooming out in
09:22the viewports with middle mouse ruler--we can see that the curve is now Ping Ponging.
09:29You can focus back on the actual animation the same as you do in the
09:33viewport with the F key. So I'll press my F key, and I'm focused back in.
09:40I'm going to go ahead and speed mine up by moving that last key back to 1.
09:45So let's go ahead and close the Animation Window.
09:48So there you've had your first taste of animation in Unity's animation view.
Collapse this transcript
Working with multiple animation clips
00:00So we got the Heart Animation looping and animating in the scene with no scripting, easy, huh?
00:06Well, what about when our player intersects its collider, which by the way,
00:09is set to as trigger.
00:11We could just have it disappear, but what if we wanted to call a
00:15different animation clip? Let's do that next.
00:18First we need a new animation, so let's select the Heart and open the Animation View.
00:24Window, Animation, you can see it also can be called up with Ctrl+6.
00:32Click the Clip Selection Box and select Create New Clip, once again, we'll make sure it
00:40goes into Animation Clips folder, and we'll name this one heart score.
00:49I like to name my animations after the object first, then what it does,
00:54that way all of the Objects Animation Clips will be together in the browser
00:58and the Project view.
00:59Let's check out the Inspector. The new clip has been added to the Animations
01:05array, so let's have the heart pop up, then shrink to nothing.
01:10First we need to turn on the Animation button, and then we're going to select
01:15the position Y track, and this time we're going to tell it to create a curve.
01:21We do that by clicking on the little bar to the right of the field and choosing Add Curves.
01:27It will automatically set keys at wherever we are in the timeline.
01:32So now let's move to frame 20, and I'm going to watch this as I move my time
01:39indicator, and I'm going to move it up in the viewport about a meter.
01:45Let's click Play and watch it and Stop.
01:51When it stops, we're shown all three position tracks even, though, we only animated Y.
01:56So let's scale the heart after it pops up.
01:59Select all three of the scale tracks this time, and I'm holding my Ctrl key
02:05to add to my selection, and we're going to move the time indicator to frame
02:0920, and once again we're going to use the little bar, click on it, and say Add Curves.
02:17Let's zoom and pan the graph view until we can move the time indicator to
02:21frame 60, or second 1.
02:24I could actually zoom in on mine, so I'm rolling my middle mouse.
02:29So we'll go ahead and move the time indicator to that frame, frame 60, 1 second,
02:36and in the viewport we're going to scale the heart up to about 1.5.
02:41Once again, that's easily done by using the regular scale function, and I'm
02:46going to watch my Inspector to see when my scale values reach 1.5-ish.
02:54Next we'll have it hold the scale, until frame 120, 80 frames.
03:00So let's scrub the time indicator to that frame, and this time we're going to
03:05use Add Keyframe--this button--to add keys, and this is going to do all three
03:13tracks, since we've got them all selected.
03:15And finally, let's add our last key at 110, 1.5.
03:21I'm going to use my middle mouse button to pan the view over a little bit.
03:26So now I'm going to move my time indicator to 110, and I want to scale the heart down to 0.
03:34This is one time when it's going to be easiest to do clicking in the Inspector.
03:43Click 0, Click 0, Click 0.
03:48Okay, let's go ahead and focus in on the curve. You'll need to re-click in the
03:52animation view to change focus and then press the F key, and there we've got our curve.
04:00It looks like our curve went a little bit wonky. Let's use the middle mouse
04:04ruler to zoom in on the area that should've stayed flat.
04:11The problem is the interpolation between the two scaled keys.
04:15To fix that, I'm going to drag a region around the left keys and from the
04:19right-click menu change their Right Tangent to Linear.
04:27Then I'll select the right keys, right- click and change their Left Tangent to
04:33Linear, and now our curve looks okay.
04:37If you're fussy, you could even adjust the Tangents for a smoother in and out on the two.
04:42Let's click Play and see the timing and Stop.
04:50We only see the time segment showing in the Animation View, so let's drag
04:54the left side of the bottom slider to the left to show the entire animation.
05:00Now if we click Play, we see the whole thing, then we'll stop.
05:08Just to note here, we don't need to manually add keys at the start of the scale
05:12tracks or the end of the position tracks. Unity considers the whole time frame the clip.
05:18To make things easier to view, we can also filter out for only animated tracks
05:24in the left, and we can toggle between Show All and Show Animated.
05:29So now we have got an animation clip for our power-up.
05:33You can save the scene if you want to, but the Animation clip is saved in the
05:37clip file every time you change it.
Collapse this transcript
Triggering keyframe animations
00:00Now let's see about triggering a new animation clip.
00:03In the Game Scripts folder, let's create a new script and name it PowerUp.
00:08Right-click, Create, Javascript, and we'll call this one PowerUp, and let's
00:18go ahead and open it.
00:20Double-click to bring up the script editor. Let's start by making a variable
00:25for the animation clip, and we're going to call it clip, var clip of type AnimationClip.
00:38And now, let's turn the Update into an OnTriggerEnter function, and inside it
00:44we're going to add animation.Play, and Play is a function, so it's capitalized,
00:53and it gets the open and closing parentheses.
00:56So without specifying an animation name, Unity will play the default clip, but
01:02we need it to play the other clip, the heart score clip.
01:06We'll feed in the correct clip, but we need to use its name as the function argument.
01:12So our variable clip, which is the actual clip, but all we really need is its named property.
01:21Let's go ahead and save the script and head back to the editor.
01:25And we need to add the new script to the Heart.
01:31We will select the Heart, find our new script, and we need to bring in the animation clip.
01:40We can click on the browser and here it is, heart score.
01:46Let's click Play and jump the first-person controller into it.
01:50Remember, spacebar to jump, click Play and test by jumping the first-person
01:58controller into it with the spacebar. It works.
02:02So let's Exit Play mode. If you need to adjust any of the timing, you can just
02:07select the heart, open the Animation view, select the heart score clip, and make
02:13adjustments that you need.
02:15Before we continue with the PowerUp script, let's go ahead and load a little
02:18package I've made for us, it's called ScoreKeeper.
02:22It's just an empty game object with a simple script.
02:26So right-click, Import Package, Custom Package, and from our Asset folder,
02:38we'll bring in ScoreKeeper. Clicking Open and then Import.
02:46It should turn up in our Prefabs folder, and there it is, and we'll go ahead and
02:53drag it into the scene.
02:55Let's take a quick look at the ScoreKeeper script, double-click it, and you can
03:00see it's really simple. It has a variable named score which is initialized at 0,
03:04and then it has a function called UpdateScore.
03:08It has a local variable called points that we will be passing to it, and that
03:12increments the score with the number of points we feed it.
03:16Let's head back to our PowerUp script now in the other tab, so we're going to
03:20need a couple of new variables.
03:21I'm going to go out to the Snippets file and Copy them.
03:27Exercise Files10/10-04/Code_Snippets, and we need these right here,
03:36pointValue and ScoreKeeper.
03:40Right-click and copy, back into the Script editor, and we'll put them right
03:45beneath our first variable.
03:47The pointValue is the value for each of our PowerUps and the ScoreKeeper is the
03:52game object that we just imported into our scene.
03:55He's keeping track of the overall score.
03:58Let's go ahead and get the next bit of code, and for the ScoreKeeper--I'm going
04:03to right-click and copy--we're going to send a message to its UpdateScore
04:09function to tell us what point value it should update the score by, and we can
04:14put this one underneath the Animation, paste, and then we may as well go ahead
04:20and put some sound effects in there.
04:22And we're going to var a sound effects variable to hold an AudioClip,
04:28right-click, Copy, add that variable up here and grab our final line.
04:35Right-click, Copy, and we'll Play our sound effects right here.
04:41Tab over, and I'm going to be neat and tidy and give myself one open line.
04:46Okay, so we're ready to save our script. The first thing we need to do is make
04:51sure we put our PowerUp script on the heart. On my console, it's giving me an error.
04:56I need to go back to my Script editor and make sure I capitalize GameObject.
05:01That will make it happy. Now I'll click Save, and now we can go back to the editor.
05:08In the Inspector, with our heart selected we now need to fill in our two new parameters.
05:13ScoreKeeper, we'll drag him into that parameter. And for the Sound Effects,
05:20I'm going to click on the browser and choose Ding.
05:25The heart and the key Prefabs already have an audio source with the Rolloffs set
05:29to Linear, so we should be able to hear it easily.
05:33Let's go ahead and click Play and see what happens now, W, spacebar, and there we go.
05:41You'll notice that when we trigger the new clip to Play, the first one is
05:45automatically turned off. Let's Exit Play mode, and if your first-person
05:51controller is falling off the platforms too often, you can go ahead and activate
05:55the two invisible walls again.
Collapse this transcript
Animating transparency
00:00Let's add another power-up, the key.
00:03Go ahead and drag the key Prefab into the Hierarchy view next to the
00:07Heart, Prefabs, Key.
00:11I'm going to drop it near the heart, so I can make sure it's going to be lined
00:16up with platforms, and then I can go ahead and move it over, according to the
00:21Game Window, I'm not, so I'm going to go ahead and go into perspective or maybe
00:27even top view, and move it into place.
00:32And then I'll switch back to my right view, by clicking on the Scene gizmo. There we go!
00:41So now we have a new power-up, and it already has some animation clips added
00:45to it, but we're going to try something that ought to be easy but has a catch to it.
00:49We're going to have this guy fade out on score, so let's start by opening the
00:55Animation View and check out its Key spin animation.
00:59Window, Animation, and it's already set to the Key spin clip, so let's
01:06click Play and watch it.
01:11And you can see it goes around, and we'll check out its key spin animation.
01:16It's pretty straightforward.
01:18Now let's select the keyscore clip and watch its animation.
01:23We'll click on our clips area and select keyscore, and we'll go ahead and click Play.
01:31So now it flips up, and it turns around, and we can stop Playback.
01:37For the fadeout, we need to access the material.
01:40That's found in the material track, brass in this case.
01:44So click this Open, and we're going to need the color.a or Alpha track at frame
01:5190, so let's turn on our Record button and move the time indicator to frame 90,
02:00we're going to click AddCurve.
02:03So click on the little bar and Add Curve, and it gives us a key at frame 90,
02:11and now we're going to set the Alpha value to 0, and I'm going to do it right
02:16in the track itself.
02:19So at frame 90, it's fully transparent.
02:24At about frame 60, when it's in the middle of the other animations, we want it
02:28to still be visible.
02:31So I'm going to add key, in this one I'm going to set to 1.
02:371 is fully visible, 0 is fully transparent, and if I focus in on my animation
02:45now with my F key, we can see that at 1, it should be fully visible and at 0
02:51it's all the way transparent.
02:53But if we look in the viewport, fully visible when it should be transparent.
03:01So what's the deal?
03:01It turns out--and this is a very important thing to remember in Unity--you must
03:07use a transparent shader to be able to affect the material's opacity through
03:12its color parameter.
03:14So let's select the key in the Prefab folder, because we want to change any keys we're using.
03:21So in the Inspector, we're going to change its Shader from Specular to
03:27Transparent Specular.
03:32Let's go ahead and select our key in the Hierarchy again, and now if we turn on
03:39Animate and scrub through our timeline, our key fades out as we expect it to,
03:49and we can close the animation view.
03:51So let's go ahead and add the PowerUp script to the key and go ahead and
03:55fill out its parameters.
03:59Power-up onto the key, fill in its parameters, point value of 5 is okay, we need
04:07the scorekeeper object, and you can choose a sound effect of your choice.
04:12I'm going to choose PortalWhoosh.
04:18And one more thing we need to do is we need to assign the Clip, which is going
04:25to be heart score, and in the Animation component, let's double-click, and yes
04:34it does have key spin as its default.
04:36Let's click Play and test our two PowerUps.
04:39I'm going to zoom out a little bit, Click Play, W, spacebar. Oops!
04:46I missed him.
04:48Press S, and there I go.
04:52So I'm going to Exit Play mode and double check to make sure that my keyscore
04:58was set as the clip.
05:01And there's the problem.
05:03I loaded heartscore.
05:05Back to the browser, key score, and now it should work, press W, and there we
05:20go, and Exit Play mode.
05:24So far we have just shrunk or faded out the power-ups, we really need to
05:29destroy them when they're finished animating, but different objects are
05:32finished at different times.
05:34It turns out just like the audio clips, we can get the length of the animation clips.
05:40So let's open up our PowerUp script again.
05:43I'll double-click it, and in the Script editor, we're going to use a yield
05:51WaitForSeconds with the clips length plus a little extra.
05:55I'm going to go out to my Snippets file and grab that line.
05:59Exercise Files 10/10-05/Code_Snippets, and we'll grab both of these lines,
06:08right-click, Copy, and we'll paste it inside the OnTriggerEnter function.
06:15Control V, so yield new WaitForSeconds, and we are waiting for the clip length,
06:21plus one extra second, and then we're going to destroy the Game Object.
06:26Let's save our script, click Play and test one more time, and this time if
06:32we watch the heart and the key in the Hierarchy panel, we should see them disappear.
06:38Click Play, and there they go.
06:47Both of them have now disappeared from the Hierarchy, and we can Exit Play mode.
06:52So our two takeaways are if we need to fade an object out, we need to make sure
06:57that it has a transparency shader on it, and we also found that we can get the
07:02length of an animation clip using clip.length.
Collapse this transcript
Keyframing events
00:00So, we've got a couple of power-ups working, but they are looking a little sparse
00:04despite our animations.
00:06It would be much cooler to have maybe a particle system explode at an opportune
00:11moment during the timeline. Well, guess what. We can do that.
00:15Before we go any further, though, let's go ahead and import a new package,
00:20right-click, Import Package > Custom Package and from our Assets folder, we're
00:30going to bring in Soap Bubbles 1 Shot, Open and then Import.
00:37In our Prefab, there they are, Soap Bubbles 1 Shot.
00:41Now let's go ahead and open up our PowerUp script and add the ability to
00:46instantiate a particle system or any other Prefab.
00:52Double-click, we're going to need to make this functionality in its own
00:57function, and we'll name it SpecialEvent.
01:00I'm going to go out to my Snippets file, and get the code,
01:05Exercise Files10/10-06/Snippets, and we're going to start with our empty SpecialEvent function.
01:15Right-click, copy, and we'll add it below our OnTriggerEnter function.
01:21Inside it, also from the Snippets file, we're going to instantiate our object.
01:26So, I'll grab that one, right- click, copy, and I'm going to paste--
01:34Ctrl+V--my new line inside there.
01:38So now we're going to have a local variable called clone of type GameObject
01:42that instantiates our eventFX in the current position and rotation of the
01:49object that the script is on.
01:51That means, of course, that we're also going to need a variable for the eventFX.
01:57Up at the top, var eventFX, that one is of type GameObject.
02:10So let's save the script, and get back to the editor.
02:14Let's go ahead and select the Heart, and then our script for the parameter,
02:19and in the Inspector, we'll go ahead and drag Soap Bubbles 1 Shot into our Event FX parameter.
02:28Soap Bubbles 1 shot already has a time destroy script, and it will go away on its own.
02:34Now let's open the Animation View,
02:36Window > Animation, and select the Heart Score clip.
02:42I'm going to click to see my clips list, and I want to choose Heart Score, and
02:49press my F key to focus in.
02:52And then we need to scrub through the timeline and decide when the Prefab
02:56should be instantiated.
02:59To do that, we need to turn on our Record button.
03:03So, I'm going to scrub through the timeline and decide where the Prefab should be instantiated.
03:08I'm thinking somewhere around frame 45 or 50. We're going to add an event.
03:13To do that, we could use the Add Event button which is right here, but in
03:20Windows at least, the dialog doesn't stay open. So let's go ahead and use another method.
03:25We'll right-click over the indicator and choose Add Animation Event that way, a single click.
03:34And now we have our new marker, and we also have a dialog that wants us to select the function.
03:42Events are sort of like using send message.
03:46They go out to a function of that name, regardless of which component it's on.
03:51So, we're going to click the dropdown and our script has special event, that's
03:58the one we want, and we can go ahead and close this.
04:02If we needed to edit the event, we only want to click once on the marker.
04:07A double-click will generate a new marker in the same spot, which will leave you
04:11wondering why it tells you there is no animation assigned.
04:14So be careful about that. Let's test it.
04:18Go ahead and close the Animation View, and then we'll click Play, and we'll jump
04:23the first-person controller at the Heart,
04:26W key, spacebar to jump, and there we go, and there's our bubbles. Here's the event.
04:35So the bubbles might be kind of hard to see in the game view.
04:39Let's try a rock Prefab instead. We'll use the small one, Rock3.
04:44That one won't get stuck on the invisible walls.
04:46I'm going to click Exit Play mode, select the Heart, and in our script, instead
04:54of Soap Bubbles, I'm going to drag the Rock3 Prefab into it.
05:00Let's click Play and try it, W, spacebar, and there's our rock.
05:07You've probably heard it ding twice.
05:10That's because the heart's collider isn't gone by the time the rock hits it.
05:14So we really ought to add a check to make sure that only the player gets the power-up.
05:19Let's exit Play mode, and we're going to add the Collider argument to the OnTrigger function.
05:26So we're adding a local variable, and we'll call this Collider, and it's of type
05:33Collider, and then we'll add the conditional that checks for the player tag.
05:39Our conditional needs to be at the top, and I'll tab over, and it's going to be
05:44if (collider.tag == "Player"), then, we get to do all the good stuff.
05:51We need to add our closing curly bracket, and I'm going to select the inside and
05:57right-click and indent the selection. So there we go!
06:03Let's save the script. We'll go ahead and click Play.
06:09W, spacebar, and this time, we only got one ding, and the rock didn't trigger it.
06:18So let's exit Play mode, and there we go!
06:21The addition of the event to call another function during the timeline opens up
06:26a lot of possibilities.
Collapse this transcript
Avoiding keyframing pitfalls
00:00Let's look at one more keyframe animation- related thing before we head on to imported animation.
00:06It's a kind of serious gotcha that you may run across with keyframe animation in general.
00:11Let's start by cloning the Heart object and naming it Heart2.
00:16I'll select my Heart, press Ctrl+D, and I'll name this Heart2.
00:23Now, we are going to move it beyond the first one.
00:26I'll go ahead and move it up beyond the key. Let's go ahead and click Play.
00:30Make sure you trigger the first heart before you go after the second one.
00:34Play, W, spacebar, there is its rock, and then we are going to go up and
00:42trigger the second one. So wait! What just happened? Let's exit Play mode.
00:49As soon as the first-person controller hit the second heart, that heart jumped
00:55back to the spot where the animation was created.
00:57Any object that's a single object created in Unity or imported as a single
01:02object is going to have this problem whenever its animation includes a position transform.
01:09The solution is to put the object with its animation in a group and then move the group.
01:15Remember, children inherit the transforms of their parents, and their own
01:20animations stay relative to the parent.
01:24So let's delete the moved Heart, Heart2, right-click, and Delete, and we'll make
01:31an empty GameObject in the original Heart's position.
01:34I'm going to double-click on it to make sure it's focused.
01:38GameObject, Create Empty, and I'm going to name this one Heart Group.
01:44Now, I'll clone the original Heart again, Ctrl+D, and I'm going to put that
01:51into the Heart Group.
01:53Now, I'll zoom out a little bit, and I'm going to move my Heart Group back where I had the other one.
02:02Let's click Play and see how this works, Play, W, spacebar, and spacebar.
02:13Well, the heart did what we expected it to this time, but the rock is
02:19totally missing in action.
02:21So, there's something else going on here. Let's exit Play mode.
02:25The rock was in the hierarchy, so we know it's been instantiated, but it's nowhere to be found.
02:31So it looks like we need to use the parents transform as the instantiation spot.
02:36That is of course if there is a parent. So, we are also going to need to check for that.
02:42Let's go ahead and open up the PowerUp script, and we're going to change the
02:48code in the SpecialEvent function.
02:50So, I'm going to go out and grab that code from the Snippets file,
02:54Exercise Files10/10-07/Code_Snippets.
02:59So this one, we're going to make sure that if it doesn't have a parent, so if
03:05no parent of that transform exists, it's going to go ahead and instantiate it
03:10in the normal place.
03:11But otherwise, that means it does have a parent, so now we're going to use
03:16transform.parent.position and transform.rotation is still okay.
03:22So, I'm going to right-click and copy all of this code, back into my script
03:28editor, and in the SpecialEvent function, we're going to replace the original
03:32line with the new condition, Ctrl+V
03:36Now we can save the script and head back to the editor.
03:40To be sure our new grouped power-up can be cloned and still work, let's group
03:45then duplicate the key and test it as well.
03:49So I'll focus in on the key, double- click it, create a new empty GameObject,
03:55and name it Key Group, duplicate the key with Ctrl+D, and move that one into the Key Group,
04:08zoom out, select my Key Group, and I'll move it over here.
04:17And now we are ready to click Play and test again,
04:19W, spacebar, spacebar, spacebar, and spacebar, and there we go. Everything is working.
04:35So now would be a really good time to exit Play mode and update our original to Prefabs.
04:42This time, we're going to overwrite them with the Key Group and the Heart Group.
04:47So we'll drag Key Group into the Key Prefab, and we'll say Replace anyway.
04:56Then we'll drag Heart Group onto the Heart Prefab and tell it to replace anyway.
05:04Now, we can delete our two extra objects in the Hierarchy and Delete.
05:12So to recap--and this is another one of those really important concepts--if you
05:18want to move an object that has keyframed animation on its root, be sure to put
05:23it in a group or empty GameObject first.
Collapse this transcript
11. Animating Skinned Meshes and Controlling Characters
Importing skinned meshes
00:00So now that we've covered the basics of native keyframed animation, it's time to
00:04look at imported animation.
00:06Let's start by selecting the Imported Assets folder, and then import the
00:10Lenny.FBX file with Import New Asset.
00:15Imported Assets, right-click, Import New Asset, and in our Assets folder, here
00:22is Lenny, and we'll import.
00:24Let's drag Lenny into the Scene view from the Imported Assets folder.
00:29Now we'll focus on the Heart and select Lenny and use Move To View to bring him in line.
00:35If we move him aside and zoom in, we'll notice that he is pretty small.
00:42Let's select him back in the Imported Assets folder again, and change his import Scale Factor to 0.08.
00:52Notice we're not generating colliders, but we've made a change, so let's click Apply.
00:58Now, we can rotate him 90 degrees on the Y, and he is in line with the rest of our power-ups.
01:05I'm going to zoom out, then I'll go ahead and move them up above the upper ramp.
01:10Let's click Play and watch his animation, and exit Play mode.
01:18If the teeth didn't clue you in before, by now, we can see he is a threat to our
01:23poor little first-person controller. Let's hold Alt and click the root object.
01:29The expanded hierarchy shows several bones and a set of teeth.
01:33Let's select him in the Project view again.
01:36We've changed his Scale Factor, we've decided not to generate colliders.
01:41So the next thing is animations.
01:44Since he has a hierarchy of bones that deform his mesh, we need to use Store in
01:49Root, and that's the default, so we're good to go.
01:52So, where is the animation stored? Let's open him in the Imported Assets folder.
01:59And at the bottom, we see something called Take 001.
02:03That's the default name for animation clips generated on import.
02:08By now, though, you've probably guessed that we're going to break the original
02:11clip into a couple of clips, one for each behavior.
02:15Unlike native animations where the clips exist independent of each other--
02:19at least from what we get to see--on import, we'll see the object's entire timeline.
02:26Our first task will be to separate it into his behaviors, the animation clips.
02:31So, right below the Split Animations check box is the list of our clips, or
02:36it will be shortly. We'll start by clicking the plus button.
02:40A new clip is generated. The default name is idle.
02:44We're going to make it a bit more descriptive and rename it Lenny Idle.
02:48In 3ds Max where I made him, I was using 30 frames per second.
02:53His idle behavior started at 10 and went to frame 100.
02:58Unity knows how many frames per second were used when making the animation.
03:02That information is included in the FBX file.
03:05So now we need to set the start and end to those values.
03:08We'll set this one to 10 and the end to 100.
03:14For Wrap mode, we want to choose loop, and we'll check the Loop check box.
03:21For our second clip, we'll once again click the plus button, and this time
03:27we're going to rename this one Lenny Attack.
03:31This one goes to 160, and for a Wrap mode we want to choose Once.
03:38Now we can click Apply.
03:40In the project file, the original Take 001 clip disappears and the two new
03:46clips take its place. Don't try to move them from that folder.
03:49Let's see what the clips in animations look like in the animation component.
03:54So we'll select Lenny in the hierarchy again and see what we've got.
03:59The array has been made, and it contains both of our clips, and unlike the
04:03native clips, our first clip is already loaded as the default.
04:07Let's go ahead and open the Animation View now and see what we've got.
04:11The first thing you'll notice is that the clips we defined are Read Only.
04:15We'll turn on the Record button so we can at least scrub through the animation and see it.
04:20I'm going to need to zoom out to get the full idle.
04:26Let's click Play and see how it looks in real-time.
04:29The animation is nice, but we really ought to have him moving up and down to give
04:34the player a chance to go either under him or over him.
04:37But the animation clips were Read Only.
04:41Well, guess what. We can combine the scripted animation with the keyframe animation.
04:46Since we've already got the V_PositionCycler script, let's drop it on Lenny
04:50and see how it works.
04:52I'm going to close the Animation View, find my V_PositionCycler, and drop it onto
04:59him, and I'll go ahead and close Lenny while I'm at it.
05:03It's set up to default to up and down range of one, so if we click Play, we
05:08should see the results immediately. They work really well together.
05:12Let's exit Play mode.
05:14Next, we'll go ahead and drop the PowerUp script on him.
05:18Since we chose not to have a mesh collider generated for him on import, we're
05:21going to need to give him a collider as well.
05:24Component > Physics, and this time we'll use a Sphere Collider.
05:29If we watch the animation, he pretty much stays in a spherical configuration for the idle behavior.
05:35So, we'll just set Is Trigger, and then we'll adjust the Collider Radius and Position a little bit.
05:41I'm going to set the Radius up to about 1.3, and I'll move it up a little bit on the Y.
05:48One more thing we'll need before we set up the PowerUp script is an audio component,
05:53so Component > Audio > Audio Source.
05:58We've got a message telling us there's two audio listeners in the scene.
06:02We should go up to our camera and right- click, and remove one of the extras.
06:09So now we can go back to Lenny and fill up his PowerUp script parameters.
06:13For the Clip, we want Lenny Attack, for the Point value, he is sort of a
06:21power down, so I'm going to choose -10, for the Score Keeper, I'll drag that
06:28object into the parameter.
06:30And for the Sound Effect, I'm just going to use ChestOpen for lack of anything better.
06:37We don't need an eventFX for him, so we're good to go.
06:41Let's click Play and see if we can run our first-person controller into him
06:46using my W button. And I missed him, and there I go!
06:54Now, problem is that Lenny has disappeared.
06:58It would be really nice if he stayed around to eat the first-person controller.
07:02So let's exit Play mode and open the PowerUp script in Script editor.
07:09Let's make sure we're in the PowerUp script, and then we're going to add a new
07:13variable called dontKill.
07:17This is going to be of type Boolean, which will give us a check box in the
07:23Inspector, and we're going to initialize it to False, because most of our
07:27power-ups we do want to disappear after they've been hit.
07:32Now, we're going to carry out our dontKill option right above the yield.
07:38So, if dontKill is true, we're going to say, if (dontKill) return.
07:45And as we saw in a previous script, that's going to bump us out of the function
07:50before we get to the destroy.
07:53Let's go ahead and save the script and Tab back to the Game editor.
07:58It looks like the console is reporting an error.
08:01If I select the Heart parent, I can see that it has an extra PowerUp script from
08:07when the Prefab was updated. I'll just remove it and check the original.
08:11Right-click, Remove Component, and then I'll check the Original, and there is
08:18our missing Score Keeper.
08:21I'll take the Score Keeper object from the hierarchy and drop it into the
08:25correct parameter in the Inspector. We'll also need to do that for the key.
08:31Select the key, remove the extra power-up, check its original key, and it's also
08:39missing the score keeper.
08:41So, in the hierarchy, we'll drag the score keeper into the correct spot.
08:46Now, there's one more thing we need to do.
08:49Since we added the dontKill variable, we need to select Lenny and turn his dontKill on.
08:59So now we should be able to click Play and run our first-person controller
09:04through the power-ups. And there we go!
09:11The heart and the key disappear and Lenny persists.
09:15Let's exit Play mode.
09:17With imported character animation or any objects with a hierarchy or linked
09:22animated objects, we need to use Store in Root.
09:27We can break the original Take 001 clip into separate animation clips below the
09:33Split Animation check box.
09:34Well, we've also discovered that keyframe animations and scripted animations
09:40can play together nicely.
Collapse this transcript
Adding to imported animations
00:00Lenny is kind of a colorful character. It would be fun to make his animation even more outrageous.
00:05Like maybe suspending the player input while Lenny gnaws on him, that would be
00:09triggered with an event.
00:11Or maybe just a color change while he is chomping away.
00:14Either way we need access to that attack clip, but it is part of the imported
00:20asset, and we can't touch it--it is read-only.
00:23We can, however, clone it. Let's do just that.
00:27Let's select the lenny attack clip in the Imported Assets folder and use
00:33Ctrl+D to duplicate it.
00:34So the first thing that happens is the clone is created outside of the Imported
00:39Assets folder. That gives us the opportunity to rename it.
00:44I'm going to name this one lenny attack e--for edited--and then I'm going to move
00:51it to the folder with the rest of the animation clips.
00:54The first thing we'll need to do is select Lenny, and we need to swap out our
01:00new attack clip with the old one.
01:06And we need to do it both in the Animation component and in the PowerUp script.
01:12Now when we open the Animation View, Window > Animation and click the dropdown,
01:20we see that we've got a lenny attack e clip that can be edited.
01:25So we'll select it.
01:26In the LennyMesh child object we can find the material Skin. Let's change the
01:33color to red while it chomps then back again, and so we don't lose it, we're
01:37going to set keys for the color at the start and the end of the animation first.
01:42We'll select our RGBA color tracks. I'm using my Control key to add to my selection.
01:48And we'll click record.
01:50And we're going to click Add Keyframe, and now we have a key at frame 0.
01:57His animation for the attack sequence goes to about frame 59. By 50 I think he
02:03should be back to his normal color.
02:05We'll drag the time indicator over to frame 50, and we'll click Add Keyframe again.
02:12These two keys will ensure his regular green color.
02:16Now somewhere around frame 10, let's select the LennyMesh object in the
02:21Hierarchy view and change the skin color--also known as main color--directly to a reddish-orange.
02:29Here is our LennyMesh, here is our Skin, we're in animation record mode,
02:36and we're going to select his Main Color and change it from green to a reddish-orange.
02:43If we scrub through our time slider now, he is green, he is orange, and he
02:50goes back to green. So there we go, we're all set to play.
02:55Close the Animation View, let's deselect him, and click Play.
03:01And now we can run our character W key, jump up, and we see it worked.
03:10So there we go. Let's exit Play mode.
03:13So our main takeaway here is that we can't change imported animation clips
03:17directly, we need to duplicate them, and then we can use the new versions.
Collapse this transcript
Dynamic parenting
00:00While storing animations in the root is perfect for characters where the top
00:04parent in the hierarchy controls all, sometimes we need to be able to access the
00:09animation on different parts of the imported asset independently.
00:13Store in roots allows us to do just that, even when the animations are at the
00:19same place on the timeline.
00:21In this video we'll import an old- fashioned cage lift to move the player from
00:26the compound up to the platform area.
00:29Let's bring the Lift Finish Package into the Project.
00:34Right-click Import Package > Custom Package > 11-03/Assets/LiftFinished,
00:45and we will click Open, then Import.
00:50Now let's take the LiftFinished Prefab into the Hierarchy view and focus in on
00:55it in a perspective view in and zoom out a bit.
00:57LiftFinished, and we'll drag it in here, double-click on it to focus in and
01:04then just click on perspective on the scene gizmo and zoom in a bit, and we'll click Play.
01:13The lift animates between the lower compound platform and upper will be
01:17relocating our platform assets.
01:21The appropriate doors open and shut to allow them in at bottom and out at the top.
01:28Let's go ahead and exit Play mode.
01:31Let's select the Lift in the Imported Assets folder.
01:35In the Inspector under Animations we can see that it's using Store in Original Roots.
01:43Take 001 has been split into two clips, elevator open and elevator closed.
01:50Both door groups use the same positions on the timeline.
01:54So now, let's select the LiftFinished in the hierarchy again.
01:58Let's open the Animation View, Window > Animation, and we'll use our F Key to
02:06see the whole animation.
02:08Besides the animations on the door that came in with the imported asset, we also
02:12have a lift operator clip that was created in Unity, and we can see that it is
02:18going to lift the whole group on the Y up and then back down.
02:24It also has four events that trigger the open and close animations on the two door groups.
02:30Let's close the Animation View now. Let's get back to our right view in the
02:36scene window, and I'm going to zoom back a little bit because we want to see
02:41where it comes out at the top.
02:43So now we can click Play, and the doors will be opening on the bottom, allowing
02:49the player time to get into the lift, and then it goes up to the top where it
02:54pauses to allow him back out.
02:58Let's pause the animation while it's at the top, select the Platform asset's
03:03Start group, and move it up to match.
03:07Since we are in Play mode, this will not be a permanent change, so we need to go
03:11over to the Inspector and copy the Y value, right-click and Copy.
03:18We'll stop playback, then we go back and right-click and Paste.
03:23So our platform group is now up where the elevator is going to be stopping.
03:29Now we can take our Key, Lenny and Heart power-ups, and drag them up to match. We're all set.
03:37And we also need to relocate the first platform, or it will be in the way of the lift.
03:43So I am going to select it, and I'll just move it over and maybe even a little downward.
03:49When we drive the first-person controller into the lift and let him take the
03:54trip up to the top, we are going to see from the Scene view that it looks pretty smooth.
03:59But in the Game view when it starts to rise--especially if we look up--we'll be able
04:05to see a lot of camera jitter. Let's go ahead and try that.
04:09I'll click Play, drive my first-person controller forward, and the doors will
04:15close, and if we look up now especially you can see a lot of jitter going on.
04:23So let's exit Play mode and figure out how to solve this.
04:27Well, it turns out we can script the first-person controller to be temporarily
04:33parented to the lift.
04:35So let's go ahead and create a new script named Parent Manager.
04:39From Game Scripts right-click, Create > Javascript, and this one is going to be ParentManager.
04:49I am going to go ahead and get the code from it from the snippets file as soon
04:54as I open it in the Script editor.
04:57Exercise Files11/11-03/Code_Snippets, and this is the code we'll be using.
05:06So I'm going to right-click and Copy, and then tab back to my Script editor, and
05:14I'll replace the whole thing. Right-click and Paste.
05:18Our passenger is going to be the first- person collider but we're going to do an
05:23extra check just to make sure.
05:26If the collider is marked as Player, then we go ahead and parent the passenger to
05:32the object this script is on, which will be the lift.
05:35When he leaves on trigger exit he gets unparented, and that's pretty easy,
05:40passenger.parent = null.
05:43So let's save the script and go back to the editor.
05:46And we need to drop our script on the LiftFinished, and there we go.
05:53So now, let's keep the LiftFinished Hierarchy open, I'll close up our
05:57Platform Assets Start, and we want to keep this open so that we can watch our
06:02first-person controller and see when he gets parented and unparented from the LiftFinished.
06:08So I am going to click Play, drive him forward, and you can see now he's now in
06:16the LiftFinished group, and as soon as he goes up to the top, we'll go through
06:21and get a power-up and get out of the lift at the same time.
06:27Before I exit Play mode, note that once again he is back where he belongs, and
06:33now we can exit Play mode.
06:34So we now have the means to dynamically move our player around a scene on a
06:41large assortment of vehicles.
Collapse this transcript
Exploring character controllers
00:00Through scripting, Unity provides us with the means of making all kinds of cool things happen.
00:06Unfortunately, it means we're stuck with the task of doing it.
00:10Unity only ships with a few character controllers preset and ready to go and
00:15most are derived from the Lerpz Tutorial available on the Unity web site.
00:20If they happen to do what you envision for your game, you're in luck.
00:23Otherwise, you'll either need to learn to write your own, find a programmer to
00:28write them for you, or riffle through the example projects available online and borrow their scripts.
00:34Writing a character controller is beyond the scope of the series, but we will at
00:39least test out what Unity gives us to start with.
00:42Character controllers are usually tightly integrated with camera control, so
00:46let's get a fresh scene to play around in.
00:49Let's start by importing the Character Tests package, right-click, Import
00:54Package > Custom Package and from 11-04/Assets we're going to bring in Character Tests.
01:04Open and Import. This one comes in as a scene, so let's go ahead and load it.
01:11Here it is on the Scenes folder, Character Tests, and we'll double-click to
01:16bring it in, and we can save our previous scene.
01:20In the Hierarchy view, let's focus on the Platform and then go ahead and disable it.
01:26From the Standard assets folder, let's open the Character Controllers folder and
01:31select the Third-person controller Prefab.
01:35Standard Assets > Character Controllers, and here's our 3rd Person Controller,
01:40and we're going to go ahead and drag him into the scene, like so.
01:45We want to drag him up out of the ground, so let's go ahead and click Play and try him out.
01:51As soon as we click Play, his own camera comes into view, and we see him in the
01:56game window, W-A-S-D, and if we click W again, spacebar, he jumps and Shift to run,
02:11and run and jump. He is pretty entertaining. Okay, let's stop.
02:18Then exit Play mode, and then let's go ahead and see what makes him tick.
02:23We'll do that by opening the Third person controller script on him over in the
02:28Inspector here is the script, double- click it open, and it comes in first.
02:35You can see by the size of the scroll tab that it's a pretty lengthy script.
02:41Let's go ahead and get down to somewhere between 320 and 350 and look at something here.
02:46What we see is animation.Crossfade. That's how we can smoothly transition between
02:53different clips, an idle to walk, a walk to a run, et cetera.
02:59So that's a good one to remember. Let's tab back to the editor.
03:02So here is the important question. How useful would he be for our platform area?
03:09We've seen when we make him go forward and backwards the turn is usually
03:13instant, but once we use the strafe keys he moves in the direction he's
03:18facing, for that we could use input.getaccess to bypass the horizontal input,
03:24but he's also got a camera that's wired to his code.
03:27For that we could probably disable the camera script, but the crucial test is
03:33can he ride a platform?
03:35The platform in our scene already has a rigid body, and it's set to kinematic.
03:40Let's go ahead and activate it, and then we'll need to move spin a little bit higher.
03:45So we'll select the Platform and activate it, we'll move our character a little
03:51higher, and then we need to get some movement.
03:55I've added the V_Position Cycler script and the H_Position Cycler script.
04:01Let's try out the vertical one first.
04:04Let's click Play, and if we move him, you can see he does go up and down, but
04:13the movement activates his walk cycle. Let's stop playback and switch from the
04:18vertical to the horizontal and click Play.
04:22And this time you can see it pretty well has no effect on him whatsoever.
04:28So let's exit Play mode. Clearly platforms are not supported for the
04:33Third-person controller in this version of Unity.
04:36I'm hoping this one will be converted to the newer motor system, but assuming
04:40it hasn't yet been updated we'll do a bit more tinkering to get something we can use.
04:45So let's Save this scene, File > Save Scene, Delete the 3rd Person Controller,
04:52right-click, Delete, and we'll save this for Character Test 2 for the next video.
04:59File > Save Scene as in our Scenes folder Character Tests2, and click Enter to save.
Collapse this transcript
Importing an animated character
00:00Let's start by importing the Platform Character package into the project.
00:05Right-click, Import Package > Custom Package, and from 11-05/Assets, we're
00:14going to bring in PlatformCharacter. And we click Open, and Import.
00:21From the Prefabs folder, let's go ahead and drag our PlatformCharacter into the scene.
00:26And here he is right here, and I'm going to drag him right on top of our platform.
00:30He is just a simple character I made with the CAT tools in 3ds Max.
00:36Let's check out his import settings.
00:38In the Imported Assets folder, Select CAT2, and let's see what we've got.
00:43Under Animations, Store in Root, and I've already given him an idle, walk, jump, and run clip.
00:52The Third-person controller didn't suit our needs, so let's see what we can get
00:57if we use the platform input controller script to move this guy around.
01:02This time, let's get our script from a different location, Component > Character > Platform Input Controller.
01:11This one can also be found in the Standard Assets folder.
01:15In the Inspector we brought in the Platform Input Controller, but it also loaded
01:21the Character Motor (script) and the Character Controller.
01:25Let's open the PlatformInputController script to see how that happens.
01:30We'll double-click on it, and at the bottom of the script we see these funny
01:36things here that have an @ sign in front of them.
01:39The RequireComponent is what adds the component to the game object.
01:43AddComponentmenu is what puts it up in the menu.
01:48Let's go ahead and close out a bunch of these now.
01:52And I'll tab back to the editor.
01:53So back to our PlatformCharacter, as you can see his capsule is a little bit low,
02:01so we need to move his collider up a bit.
02:04So I'm going to move his center up about a meter.
02:08Now let's press Play and test him with the platform.
02:11I'm going to click on my Platform and see which script is active.
02:15Looks like the Horizontal Position one is.
02:18Let's click Play, and sure enough he rides the platform.
02:24Let's go for the second test.
02:27Let's turn on the Vertical Platform Cycler, and there he goes.
02:32Sort of looks like we have a winner.
02:36If we stop playback, and turn off both position cycler scripts, we can try
02:42running him around the scene.
02:44Like the other characters, he uses W-A-S-D, spacebar to jump, and Shift to run.
02:51Let's click Play and test. W-A-S-D, jump, and we will skip run for now.
03:04And let's exit Play mode.
03:06This character controller was meant for an environment using a 3D space, and
03:11it has no built-in controls for managing the character animation, but it does support platforms.
03:17Let's tinker with the navigation first. It's pretty close, but there's a couple
03:21of things we still need to do.
03:23So we'll select our character again, in the Platform Input Controller (script),
03:29double-click it, and in line 15, we are going to rearrange the input.
03:37I'm going to go out to my snippet's file and get the replacement.
03:41Exercise Files11/11-05/Code_Snippets 05.
03:47So the only changes we're making really is we're putting a 0 in the X axis,
03:53we're moving our horizontal to the Y, and we are leaving 0 in the Z.
04:00And I've gone ahead and commented out the one that we removed.
04:02So I'm going to right-click and Copy, back to my script editor, and we're
04:10going to replace line 15.
04:13Right-click and Paste, and we'll move it over again.
04:18Now Save the script, and let's get back to the editor.
04:22So basically what we've done is we've blocked any input from the vertical.
04:27Click play, and now the only keys that should work are A and D or your left and
04:34right arrow keys and spacebar, you can still jump.
04:39And let's exit Play mode.
04:41Just out of curiosity, you might want to know why this controller supports platforms.
04:46If we open the CharacterMotor component in the Inspector we notice it has moving
04:52platform as one of the parameters. Let's look in the script.
04:57This is another really big one, but if we go quite a ways down here at some
05:02point we're going to start seeing things about platform, activePlatform,
05:06movementTransform, movingPlatform again, and if we continue to look through it, MoveWithPlatform.
05:16We've discovered that a pretty good chunk of this script is about dealing with platforms.
05:22Let's go ahead and get back to the editor, maybe half or more of the script is
05:27dedicated to the Platform option.
05:29The bottom line is the velocity of the platform is added to the velocity of the character.
05:35And then there's all kinds of extra equations to deal with jumping when on
05:39platforms, landing while jumping and all kinds of other fiddly bits.
05:44So rather than trying to add platform support to the Third-person controller, I've
05:49opted to add some simple animation controls that will work with the
05:52CharacterMotor. That means it should work with either the first-person controller
05:57or the platform input controller. We'll do that next.
Collapse this transcript
Activating the character animation
00:00Next we'll add at least a little bit of animation to our character.
00:04From the exercise files folder for this video, let's import the
00:09CharacterMotorAnimation script into the scene.
00:11We can do that with Import New Asset, and let's make sure we add it to the Game Scripts folder.
00:17Right-click, Import New Asset, and we need to get to 11-06/Assets, and here it
00:26is, CharacterMotorAnimation, and we'll Import.
00:30And now we can go ahead and drag it onto the PlatformCharacter.
00:35Select him and at the bottom of the Inspector we'll notice that it looks very
00:41much like the Third-person controller.
00:42We'll need to add each of these animations into the proper slots.
00:47Let's click on the browser and see if we can find the Idle Animation.
00:50Well, it turns out we've got a couple to choose from.
00:53So this is one of those times when you better off to select it this way.
00:59Click on it here, and now we know which one it is, and we can drag it into the idle.
01:06Go for the walk. It selects it.
01:10It looks like we'll be pretty safe to go this way, walk, jump, and run.
01:17So, how will this script know what to do?
01:20Well, it will need four values sent to it from the Character Motor.
01:24It needs to know the character's velocity for the idle and run animations, and
01:30it needs to know if the character is on the ground or in the air.
01:33So, we can know whether to override the idle or run animations with the jump
01:37animation, and it needs to know when the jump starts and stops.
01:42For the last two, the Character Motor already has a couple of send messages.
01:48For the first two, we are going to need to add a couple of more, and since
01:52grounded and velocity are needed by the CharacterMotorAnimation in every frame,
01:57that's where we'll add the code, inside the Update function.
02:00I am going to go out to the Snippets file and get the code we need.
02:06Exercise Files11/11-06/Code_Snippets.
02:12So basically, we have our gameObject.SendMessage, and we are going to send it to
02:18a GetGrounded function, and what we're sending is the grounded variable.
02:23In this one, GetVelocity, we're sending movement.velocity, and the Character Motor
02:30keeps track of these two variables throughout.
02:34So let's right-click and Copy, back into our editor and go ahead and open the
02:41CharacterMotor script.
02:44I've already done a search for the Update function, and I've already found it at line 337.
02:51So let's get down to that, and there it is, the Update function, and we can go
02:56ahead, give ourselves a little space and paste our new send messages into it.
03:03In case you're curious, the On Jump message is at line 454 and the On
03:09Land message is at 295.
03:12Let's go ahead and save the script and get back to the editor.
03:18If you want it to open the CharacterMotorAnimation script you would find the
03:22GetGrounded and GetVelocity functions are just setting flags that are used in
03:27the Update function. Let's go ahead and test him.
03:30I'm going to deselect him, click Play, and remember we aren't using W and S
03:37anymore, we are using A and D.
03:41So his run sequence works, let's try jumping him, and there he goes.
03:45He kind of gets out of frame, but that's okay.
03:48I'll jump him way out here.
03:51Run him back and jump, and we can exit Play now.
03:57Unlike the Third-person controller, he has just one speed, which is fine for a platformer.
04:02I hooked it up to use the run animation, and the speed matches the animation
04:06pretty good, so we shouldn't need to adjust it.
04:09The only thing we really noticed, though, is it looks like when we jump he is got
04:13a Jet Pack just like in the Lerpz Tutorial.
04:15We need to make a few adjustments in the Character Motor component, Jumping section.
04:20So let's select him again, and in the Character Motor section under Jumping we're
04:27going to set his Extra Height to 0.1, and that will get him down sooner, but now
04:34he won't jump high enough so we need to set our Base Height to about 3 or 4,
04:38and you can test this on your own.
04:41And then in Movement, let's go ahead and set his Gravity to about 30.
04:47And finally, in the Platform Input Controller we're going to turn his
04:52Max Rotation Speed way up. I'm going to try about 2000.
04:56This will ensure that he makes a full turn anytime we which keys.
05:01So let's click Play and test.
05:03I am going to deselect him, try running with the Arrow keys Left or Right or the
05:10A or D keys, and then I'll press my spacebar to see how he jumps, and you can
05:16see his jump is much better now. And we can exit Play mode.
05:21So, there's only one more thing.
05:23He is going to need to trigger the Power Ups, and they are set to look for the Player tag.
05:28So we need to set a new character, PlatformCharacter and take him as Player as well.
05:36So that should just about do it.
05:38Let's go ahead and update the Prefab for him by clicking Apply in the Inspector,
05:43and let's be sure and save this scene.
05:46So, we have found that we can tinker with the existing controllers without
05:51having to write pages of code.
Collapse this transcript
12. Working with Cameras and Layers
Introducing cameras
00:00In this chapter we'll be looking into cameras.
00:03Unity's cameras have many of the features you may already be familiar with, plus
00:07several unique to game engines.
00:09Let's start by opening the MainLevel scene, and then we're going to activate the
00:14camera and deactivate the Camera on the first-person controller, and its
00:19Children, and also let's go ahead and turn the Terrain back on.
00:23So let's adjust our Scene view to get a nice view of the platforms, with a
00:27little bit of the sky.
00:29I'm going to select the platform, focus in on it, and then use my Alt and my
00:34middle mouse button to pan, and if you want you can turn the sky on in the Scene view.
00:39This is the Overlay button, and so that's kind of a good view.
00:42So now we're going to create a new camera, and we'll name it Camera 2.
00:46GameObject > Create Other > Camera, and we'll name it Camera2.
00:52It's drawn over the existing camera. Let's try turning it off and on just so you can that.
00:57Activate and Deactivate, and you can see that it's drawn over the other one.
01:02Now let's go ahead and use align with view on our new camera, Camera2,
01:05GameObject > Align With View, and it pretty much matches the one we have in our Scene view.
01:12As long as we've got it selected, let's also deactivate its Audio Listener, so
01:17we're all set to look into cameras.
01:18The first thing we want to investigate is Clear Flags. It's set to Skybox.
01:23Let's choose Solid Color.
01:25If you had assigned one, the Skybox is turned off--it's a shader, by the way.
01:30And now we can adjust the Background color.
01:32We'll click on the Color Swatch, and we can change it in the color picker.
01:39And we'll close that. Let's try the next one, Depth only.
01:43This one turns the sky off altogether, and guess what shows through. The other camera.
01:48Turn this camera off and on to make sure you can see that that's what's happening.
01:52The next one is kind of funky, it's called Don't Clear.
01:56It's sort of combines everything in an unpredictable manner.
02:00The doc suggests it might be useful for specialty shaders. Let's go ahead and switch back to Skybox.
02:06The next parameter is Culling Mask.
02:09Unity lets us assign objects to layers. The cameras can be set to selectively
02:13render different layers in different orders.
02:16We'll experiment with that when we get to the Depth parameter.
02:19Projection allows you to choose between a Perspective view where we can adjust
02:23the field of view or an Orthographic view, where there is no perspective.
02:27With Orthographic you adjust its size rather than the Field of view. Let's try it.
02:32Instead of Perspective, we'll select Orthographic, and we can adjust its Size.
02:39I'm going to start with a value of 10 and zoom it back and forth.
02:44With orthographic cameras, objects in the distance do not appear smaller.
02:49We could opt to use Orthographic for a platformer section since it takes place
02:53pretty much on one plane.
02:55But as long as we have 3D assets adjusting the perspective will be visually more
03:00interesting, so let's switch back to Perspective.
03:03The thing we see is Clipping Planes.
03:05This tells the camera how far to start and stop drawing the scene.
03:09Let's turn off the other camera before we try adjusting these parameters.
03:13So I'm going to select Camera, uncheck it, and then select Camera2 again.
03:20With Near you can see the clipping planes move through the scene in the Game view.
03:25Let's set Far to 100 before we experiment with it, and we'll drag this one, and
03:30you can see the clip coming closer and going back farther away.
03:35Let's go ahead and reset these.
03:37This one is at 1,000 and Near was about 0.3.
03:41Far when used in conjunction with fog provides a very cheap way to cull objects
03:46and improve frame rate.
03:47For the next section, Normalized view Port Rect, allows you to dictate how big and
03:53where you want this camera to render.
03:55Let'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:05The camera now renders in the upper- left of the screen. Position, by the way,
04:08is calculated from its lower-left.
04:11Let's see what happens if we turn our other camera back on.
04:15When we turn the other camera on, our Camera2 is hidden.
04:19But wait! The new camera used to be rendered on top of the old one.
04:22This is where the Depth parameter comes in. It allows us to order the camera for rendering.
04:27A lower number is drawn before a higher number.
04:30So let's set our Camera 2 to a Depth of 1.
04:34Zero is the default, so when we set this to a higher number it's drawn last.
04:39Now it draws over the other camera predictably, and you can see how this might
04:44give you a nice mini map superimposed over the main view.
04:47Next, 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:00Now that we've seen how we can control camera draw order, let's take it one step
00:04further and find out how layers work.
00:06Layers are similar to Tags in that they are an ID system, but we use layers
00:11mainly with lights and cameras.
00:13Let's go ahead and select Camera2 again, and we'll set its Normalized view Port
00:17Rect X and Y back to zero, and the W and H back to one.
00:24In the Scene view, let's use Align view to select it, GameObject > Align View to select it.
00:32Now let's create a cube and scale it up so it takes up about a quarter of the
00:36view, GameObject > CreateOther > Cube, and I'm going to scale it until it takes
00:45up about that much room.
00:47Now we're going to make a Cube layer to put it in.
00:50At the top of the Inspector click the layers button and choose Edit layers.
00:57Below the Tags array we can see the layers.
01:00The first eight--and it started at 0, remember--are used for Unity predefined layers.
01:06Select layer number eight, and we'll name her layer Cube.
01:10As soon as we click in this area we'll find the text entry area, Cube and Enter.
01:15Now let's select the Cube again and assign it to the layer Cube.
01:21Let's select Camera2 and open its Culling Mask dropdown, and we're going to
01:25uncheck the Cube layer, the Cube disappears. So now, let's make a layer just for the Cube.
01:32We're going to duplicate Camera2 using Ctrl+D, and we'll name this one Camera Cube.
01:39We'll set its Depth to 2, so it draws last on top of everybody else, change
01:45its Culling Mask first to Nothing, the sky will appear, then to Cube, now a cube appears.
01:52Let's take a look at one of the components, the Flare layer.
01:55As you probably guessed, it allows flares to be drawn by the camera.
01:59We'd better turn this one off.
02:01Okay, so now we can set the Clear Flags to Depth only, and our Cube layer is
02:07drawn on top of the other camera.
02:08This is a technique often used to prevent first-person weapons from going into
02:12walls as the player gets too close.
02:15The weapon is drawn on its own layer with its own camera.
02:18You're probably wondering what happens when the view of the player from
02:22the other layer moves.
02:23Let's see what happens by selecting Camera2 from the hierarchy and then
02:27rotating it around in the scene window. We'll switch to Rotate, and I'm going
02:33to get a Top view here.
02:34No matter where the Camera2 is looking, the Camera Cube layer is always drawn on top of it.
02:40Let's use Ctrl+Z to undo the rotations.
02:43So the question is is the cube interactive?
02:46Well, that depends. Our first-person controller is nowhere close to it, so he
02:51can't intersect with it physically.
02:52But if we add our old RotationController script to it, we should be able to pick
02:57it and toggle the rotation off and on. Let's try it.
03:00Let me scroll and find the Practice scripts folder. We'll open it, and here's our
03:06old RotationController script, and we'll drop that on the cube.
03:11To refresh your memory, this one should toggle the rotation off and on as we
03:15pick it, so let's click Play, immediately click Escape so we get our cursor
03:19back, and try picking the cube.
03:23I click, and it stops, I click again, and it starts, and we can exit Play mode.
03:30This means we can create things like remote inventories, 3D menu interfaces, and
03:37a lot of other cool stuff.
03:382D GUI objects are often kept on their own layers as well, only they don't need
03:43a special layer because the cameras also have a GUI component.
03:47We won't do any test with these because Unity's newer GUI is totally script driven.
03:52We've got just a few more parameters, so let's select our Camera2 again.
03:56Rendering Path lets you override whatever is set in the player's settings on
04:00a per camera basis.
04:02Target Texture allows Pro users to render the camera to a texture, so it could
04:07be applied elsewhere as a map; a surveillance camera monitor is an example of that.
04:13We'll try a simple one in a later video.
04:15And finally, the HDR check box enables High Dynamic Range rendering for the camera.
04:21This is a pro-only feature, and you can find more about it in the Manual/Advanced HDR.
04:27Okay before we move on, let's delete the Camera Cube and the Cube.
04:32So I'm going to select Camera Cube, right-click and Delete, select the Cube, right-click and Delete.
04:38As you can see, cameras and the layering system open a lot of new possibilities.
Collapse this transcript
Activating the platformer scene
00:00At this point you're probably wondering how to transition the player from the
00:04first person to our platform character.
00:06We could script it to turn one off and the other on, but to make it easier for
00:11ourselves we'll just turn the platformer section into its own level.
00:14Since we want some continuity in the game, we'll change levels as soon as the
00:18player gets out of the elevator, so we'll get to see what he's in for.
00:22Let's use Save Scene as and name the duplicate Platformer.
00:25File > Save Scene as, and in our Scenes folder we're going to name it
00:31Platformer, and we'll click Save.
00:33Now we're going to delete everything but all of the platform stuff, the Death
00:37Zone, directional light, and the power-ups,
00:39the heart, Lenny, and the key.
00:41It's probably going to be quicker to select all and then deselect the ones we need.
00:45So I'm going to click BigTree and at the bottom holding my Shift key I've got
00:50everything selected. With my Ctrl key I'm going to deselect the Death Zone, the
00:56power-ups, Heart, Key, Lenny, and our Platform Assets Start.
01:02Do a quick double-check and then right-click and Delete.
01:07We don't want our platform character to have access to the working lift.
01:11It had too many animations to turn off anyway.
01:13So we're going to import the static lift package from this video's exercise files.
01:19Right-click > Import Package > Custom Package > 12-03 > Assets and here is our LiftStatic, Open and Import.
01:32Let's drag the LiftStatic Prefab into the Hierarchy view from the Prefabs folder, and here it is.
01:40Let's go ahead and focus in on it. It should line up with the platforms.
01:44Double-click, and I'm going to switch to a perspective view and use my Alt and
01:49left mouse button, and there we go. So it looks about right.
01:53Now let's go ahead and save our platformer scene. File > Save Scene.
01:58Next, from the Prefabs folder, let's bring in our PlatformCharacter, and we're
02:03going to put him in front of the lift.
02:05So PlatformCharacter, and I'm going to try and get him standing on the platform.
02:11You want to double-check by hitting the top view here, and yup, he looks good.
02:15So I'm going back to perspective, rotating my view a little bit, and I'm going to zoom in.
02:21I want to move him back a little bit.
02:25This is where we're going to have our next spawn point.
02:28So since he is likely to fall off at some point, at least with me driving, we're
02:32going to focus in on him now.
02:34Double-click and make our new empty GameObject, and we'll name it Spawnpoint.
02:38GameObject > Create Empty, and we're going to name this Spawnpoint.
02:44Then we'll select our Death Zone, and we can drag our new Spawnpoint into its Element 1.
02:51Feel free to move the Death Zone up a ways so the wait won't be so long if he does fall off.
02:56I'm going to zoom back and check the location of mine, and there it is way down there.
03:01So I'm going to bring it up higher, and I also need to increase the size of it,
03:05especially the Z direction.
03:11You might want to check it in the top view as well, and I'm going to toggle off
03:15my overlays button so I can see the collider better, and it looks like I could
03:20stand to shift mine a little bit.
03:23Back to perspective view, and we should be pretty good.
03:29Next, we're going to need a camera. So let's go ahead and create one.
03:33GameObject > Create Other > Camera, and it's going to need the main camera tag.
03:39So over in the Inspector tag I'm going to click the down arrow and select main camera.
03:46A sophisticated camera for a platform jumper game is probably as complicated as
03:50a good character controller script.
03:53There's a nice one in the 2D platform or example project on the Unity web site.
03:57It's several hundred lines of code. We'll use a simple alternative.
04:02Let's select the camera and rename it Camera Platformer, and now let's create a new script.
04:08We'll name that one Platform Camera Manager, and let's put it up in the
04:12Game Scripts folder.
04:13Right-click > Create Javascript, and this one is Platform Camera Manager, and
04:21we'll go ahead and open it up.
04:22Double-click and the first thing we'll need to do is to tell the camera whose
04:26transform it's going to be watching.
04:28So let's add our first variable, var camTarget of type Transform.
04:34Now in the update function we're going to add transform.LookAt(camTarget).
04:41Let's save the script and head back to the editor,
04:44Alt+Tab, and we need to drag our new script onto the Camera Platformer.
04:49Select it, and we need to give it the target, which is going to be the Platform Character.
04:55Now we'll do a bit of a cheat.
04:57Let's reduce the field of view to about 5, and we'll need to rotate it -90 on
05:03the Y, and we're going to adjust its distance so it's about 210 on the X.
05:09This is just a start.
05:10In the top view, let's move the camera about midway along the platforms.
05:15So I'm going to click on Y, on the scene gizmo and zoom out with my middle
05:20mouse roller, and then I want to position my new camera about midway from the right view.
05:27So I'm going to click my perspective and then get to a right view.
05:33Zoom in a little bit, I want to make it a little closer to the bottom of the
05:38platformers rather than the top, and I think that's going to be about right.
05:41The sky cube image is inherited from the scene render settings, but that can be
05:45overridden on the camera.
05:47So let's just set the clear flags to solid color and use the background color,
05:52and you might want to adjust it a little by clicking on the color swatch.
05:56We've already got our character working off of A and D--or the left and right
06:01arrow keys--but now we need to make sure that he's going in the right direction with those.
06:06So let's open the platform input controller script, and we can find that by
06:10clicking on our platform character.
06:12Here's our platform input controller, and we'll double-click to open its script.
06:17Let's cut the 0 from the X position using Ctrl+X, and put it after our input
06:25control horizontal, Ctrl+V. This should get him going in the right direction when
06:30we use our virtual horizontal keys.
06:32Let's save the script and Tab back to the editor.
06:35Okay, let's click Play and see how it goes.
06:38There he is waiting for us, and I'm going to use my Left Arrow key, and there he
06:43goes, and we'll exit Play mode.
06:46It's not perfect, but not bad for just a few lines of code.
06:50Feel free to make further adjustments to the camera.
06:52There is just one more thing we need to do.
06:54I forgot to bring in my Score Keeper object with the platformer scene.
06:58So let's drag the Score Keeper Prefab into the Hierarchy view and then assign it
07:03to the Heart, the Key, and Lenny. That should do it.
07:09Now that we can get most of the way through, you can see where all those offset
07:14values on the cycler scripts could come in handy.
07:16You'd want a skillful player to be able to make each connection without waiting around.
07:21There's only one thing missing now.
07:23We'll set up a physics push for our character in the next video.
Collapse this transcript
Adding obstacles and pushing physics
00:00While we were in the Platformer scene, let's look at one more important concept.
00:05You've probably noticed that your character isn't able to push aside the rocks.
00:09It's not that they have too much mass, it's just that Character Controllers
00:12aren't set up to be able to push things. That would require a lot more overhead.
00:17We can, however, give him a script that will give in that behavior with a lot less overhead.
00:23It finds out what direction he's going when he hit something,
00:25then it applies a physics force to the object in the same direction.
00:30This script comes straight out of the docs when you search OnControlColliderHit.
00:34Let's go ahead and look for that.
00:36Help > scripting Reference, and we're going to search OnControllerColliderHit
00:43and enter, and we can see it says it's called when the controller hits a
00:47collider while performing a move.
00:51This is the code we're going to be using, but it doesn't have any carriage returns.
00:55So I am going to go out to the snippets file and get my version.
00:59Exercise Files12/12-04/snippets. I'll highlight them, right-click, and Copy.
01:10Now let's tab back to the editor, create a new script, and name it Platformer_Push.
01:16In the Game Scripts, right-click > Create > Javascript Platformer_Push and Enter.
01:25We'll go ahead and open it up in the Script editor, and we can just replace
01:30what's in there and use Ctrl+V to copy in our new script.
01:34The first of var pushPower, that's going to be the force we are going to use, and
01:39then on the OnControllerColliderHit function,
01:42we're going to feed in a local variable hit, and that's the
01:45ControllerColliderHi