Unity-Specific Tools
Coverage
🛠Unity skills
- Platformer support: Rigidbody2D (Dynamic)
- Coroutines: near-term, fixed-count periodic actions
- Scriptable Objects: a templated graphical interface to data
- Particle Systems: the beginning of creating effects
💡Concepts
- Nothing much here: mostly how to use Unity to accomplish specific tasks.
Examples for Module 5
Support for Platformers
| D | Slides toward the right. Watch out: moving right is only possible on ThePlatform (the upper brown platform) or in the air; you cannot move right on TheFloor (the black platform). Awkward to control and no fun, but it makes the point that different (types of) platforms can have different behaviors. |
| A | Moves left |
| W | Strange: seemingly wants to jump |
| Space | Flies upward |
Make sure to look at the Console printout, and tell “Collision” apart from “Trigger”!!
- Brown (ThePlatform) / Black (TheFloor) / Orange (StationaryObstacle): simple platforms
- White (Collide-And-Overlap): only detects collision (allows overlap)
- Pink (Collide-And-Push): detects and maintains collision (no overlapping)
Scene setup
| Object | BoxCollider2D | Rigidbody2D |
|---|---|---|
| Hero | Is Trigger off: it's not just for detecting collisions, it's more. Try switching it on and watch the hero free-fall. (When on, you only want to know there's a collision.) | The active party in collisions: this object collides with others.
|
| Platforms (brown/black/orange) | Yes | None: they're not active colliders. Other active objects (with a Rigidbody2D) are expected to collide with them. |
| Collide-and-Overlap (white) | Is Trigger on (only for detecting collisions). That's why the Hero can detect colliding with it, and can overlap it. | None |
| Collide-and-Push (pink) | Is Trigger off | Dynamic: you can push the box. Kinematic: the box stays stationary. |
The Hero also has the HeroMovement script, described next.
HeroMovement.cs
mHeroPhysics: a reference to the Rigidbody2D component.[SerializeField]: notice this attribute; it allows access to private data from the editor.Update():- A/W: try to change the position directly. Notice W doesn't work well at all; it fights with the physics after the first y-movement!
LessonWhen Dynamic is on, changing the position directly may not work. (Moving right seems to work because physics isn't operating while the Hero rests on a platform.)
- Space: changes the traveling velocity (it goes back to zero because of gravity).
- D: only allows rightward movement when touching the brown platform, or not touching anything (in the Default layer).
- A/W: try to change the position directly. Notice W doesn't work well at all; it fights with the physics after the first y-movement!
| Callback | When it's called |
|---|---|
OnCollisionEnter/Stay/Exit | Collision with objects whose Collider's Is Trigger is off. Default: collide and stay (e.g., standing on a platform), unless the other object has a Dynamic Rigidbody2D, in which case it's pushed. |
OnTriggerEnter/Stay/Exit | The objects will overlap: detects a collision with no behavior assumptions. |
- How to build a platformer with Collider2D and Rigidbody2D
- Collider2D Is Trigger: on = only triggers, and objects overlap; off = triggers, and with a Dynamic Rigidbody2D, pushes the object
- Rigidbody2D Body Type: Dynamic for simulating gravitational physics; Kinematic for stationary
- Constraints: freeze the relevant rotations in the physics simulation
- In the air, you hold D and Space together. Does the hero fly up and to the right? Look at the order of the checks in
HeroMovement.Update().Show answer
No, it flies straight up. D sets
linearVelocity = (mSpeed, 0), but the Space check comes later in the sameUpdate()and setslinearVelocity = (0, mSpeed), replacing the whole velocity. The last assignment wins, so the sideways part is lost. - The hero's Rigidbody2D has Freeze Rotation Z checked. What would you see without it, when the hero runs into the orange StationaryObstacle?
Show answer
The hero would tip over and start tumbling. A collision pushes on the edge of the hero's box, which makes a Dynamic body rotate. Freezing the z rotation keeps the physics from turning the hero, so it stays upright.
Coroutines
Same scene and controls as above; the only interesting thing is the white block.
- From the right: the white block blinks yellow/magenta
- From the left: the white block goes through a series of color changes
Scene setup
Identical to the above. Recall that the white block:
- does not have a Rigidbody2D (it can't actively collide with another object), and
- does have a Collider2D with Is Trigger on, so it can report collisions (through the
OnTriggerfunctions).
WhiteMagic.cs on the white block
mColorChanging: of data type Coroutine; when notnull, the white block is in color-changing mode.OnTriggerEnter: tries to enter color-changing mode.OnTriggerExit: tries to exit color-changing mode.ColorChangeFromLeft/Right(): note theyield returnstatement. This is where the function yields execution until later.EnterColorChangeMode():rightFunc: of data type IEnumerator, which can hold the address of a function.- Calls
StartCoroutine()to start either the left or the right color-changing mode.
ExitColorChangeMode():StopCoroutine(an argument of data type Coroutine): you can have many coroutines running and choose a specific one to stop.StopAllCoroutines(): stops every single coroutine.
Update() calls of all components). This is powerful and can be confusing, and, very importantly, it is very challenging to debug! Use with care; don't misuse it.
Reference: Unity Manual: Coroutines ↗
ChangeRateis 0.5 seconds and the color sequence has 7 colors. You move the Hero into the white block from the left and keep it there. How long until the block turns white again?Show answer
About 3.5 seconds.
ColorChangeFromLeft()shows each of the 7 colors, then waits 0.5 seconds (yield return new WaitForSeconds(ChangeRate)) before the next one, so 7 × 0.5 = 3.5 seconds. Then it callsExitColorChangeMode(), which restores white. If the Hero leaves earlier,OnTriggerExit2D()stops it right away.- You replace
yield return new WaitForSeconds(ChangeRate);withyield return null;. What do you see now?Show answer
Just a brief flicker.
yield return nullresumes the coroutine on the very next frame, so all 7 colors go by in 7 frames, about a tenth of a second at 60 fps.
Scriptable Objects
- White/Black/Red block: collide from the right and it blinks between two colors; collide from the left and it goes through a series of color changes.
- Pink/Orange: on collision, spawns an egg at the Hero's location that behaves like a Red block.
Scene setup
Similar to the above. Take note of the Resources folder:
- a Sprite: Egg
- the ColorBlocks folder: three ColorBlocks (these are ScriptableObjects, discussed next)
ScriptableObject/ColorsForBlocks
How it works (see ColorsForBlocks.cs):
- Create a new C# class that subclasses
ScriptableObject. - Take note of
[CreateAssetMenu()]:fileName: the default file namemenuName: what shows in the Create menu
WarningIf you change these argument strings, you'll probably have to restart Unity. - Now code any data you want to provide; in this case, the colors for the WhiteMagic behavior from the previous example. Notice it only provides data: no behavior and no modification of the data.
How to use: ColorsForBlocks is like a Sprite
In the Assets folder, you can now create an instance of ColorsForBlocks: right-click in the Project window, then Create › Create colors for Blocks (the name set by [CreateAssetMenu(menuName = ...)])!
| Egg (a Sprite) | RedBlock (a ColorsForBlocks) | |
|---|---|---|
| Create | Drag in an image to create a new Sprite, and rename it Egg | Right-click › Create › Create colors for Blocks, and rename it RedBlock |
| Use | Drag onto any GameObject's SpriteRenderer to give it a look | Drag onto any ColorBlock to provide its colors for color-changing |
| Change | Change the image, and all GameObjects referring to Egg change appearance | Change RedBlock's colors, and all ColorBlocks referring to RedBlock get the new colors |
The three Resources/ColorBlocks are three instances of ColorsForBlocks with different color values: data for the ColorBlock script.
ColorBlock.cs
This was the WhiteMagic.cs script. Instead of defining the color data in code, it now has a reference to a ColorsForBlocks:
DynamicBlock.cs
- Shows/verifies how to create a ColorBlock from scratch.
- The pink/orange blocks have this component.
- While the game is running, you select the RedBlock asset in
Resources/ColorBlocksand change its colors. Then you stop the game. Are the new colors still there?Show answer
Yes. RedBlock is an asset, not part of the scene, so the “Play mode changes aren't saved” rule doesn't apply: edits to a ScriptableObject asset during Play mode stay. Every ColorBlock that refers to RedBlock, including the eggs the pink and orange blocks spawn, uses the new colors right away, too.
DynamicBlockcallsAddComponent<ColorBlock>(), then setsmColorMagicon the next line.ColorBlock.Start()readsmColorMagic. Why isn't itnullthere? When would it be?Show answer
A newly added component's
Start()doesn't run duringAddComponent(); it runs later, just before the component's firstUpdate(). By then the next line has setmColorMagic.Awake(), though, runs immediately insideAddComponent(), so if ColorBlock readmColorMagicinAwake(), it would still benull.
References
Particle Systems
- Take a look at the Unity Manual: Particle systems ↗
- Focus on the Built-in Particle System.
- Imagine a collection of points following a pseudo-random function.