Week3 Examples: Here is the source
code to the examples.
- Many Function Plots: (Last GTCSLib example)!
- With proper abstraction, it is trivial to support large instances
- XButton: cycles through all the plots
- Try cycle through the plots and press-B button to see the PlotBox.
- Bunch of random plots, interesting? May be yes? no? looks
interestingly complex/chaotic, and yet we have absolute control!!
- Class to check out: FunctionPlot:
- Abstract the area upon which to plot the function as: PlotBox
- Abstract x/y coverage of function to plot (mFunctionXCoverage
and mFunctionYCoverage).
- Notice: we can implement PlotFunction() even though we have no
idea what is the function!!
- GetYValue(x): is a virtual function, subclass can implement any
function!
- Check out the SineFunctionPath: implements a sine function.
- Class to check out: ParabolaFunctionPath:
- GetUseX(x):
- must translate x by PlotBox.Width/2 (to see the negative
side of the x values)
- Scale the x values to cover the entire width of the
PlotBox.
- Notice that in UI, when you change the xCoverage, the
plot does not change! (because we compensate the by the
above scale).
- This is done to show the curve stretching/squeezing with
the PlotBox scale.
- GetYValue(x):
- Must call GetUseX(x) to offset and properly scale the x
value
- Scale the y-value such that, yCoverage value touches the
upper corners of the plot area.
- This means, when yCoverage is larger than plotBox.height,
the traveling circle will go outside of bounds.
- Class to check out: FunctionPath:
- the update function now accepts a rotDelta (delta rotate)
parameter.
- causes the PlotBox to rotate.
- Class to check out: PlotBox
- Is a Rectangle: must set Center/Width/Height to be seen!
- ComputePosition: uses the center position and width to compute
LeftCenterPos.
- Instance variable: NormalDir: this variable is always
90-degrees of FrontDirection
- With FrontDirection and NormalDir, we have the x (FrontDirection)
and y (NormalDir) directions.
- In GetBoxPosition(x, y): we compute the actual position in the
box by offsets to the x-direction vector (FrontDirectoin) and
y-direction vector (NormalDir).
- Unity in 2D with basic control:
set to look in the positive z-direction. (default 2D window)
- Main GUI: Game Editor Window, Inspector, Hierarchy, Project
- Remember: to create defualt 2D game (no worries if you don't
remember, just set the MainCamera accordingly).
- Unity project file: under Assets folder. Make sure you know
where is your project!
- 2D Environment: Main Camera setting (refer to the Inspector):
- Position: (0, 0, -10)
- Rotation: (0, 0. 0)
- Projection: Orthographic
- Size: 100 (this is half the world vertical size, from the
middle of the screen to the top of game window)
- Clipping Planes: Near (0.3 is good). Far: 1000
- Now, our world:
- +-100 in height (notice the total vertical size is actuall 200)
- Left/Right is X (transform.right is the unit X-vector)
- Up/Down is Y (transform.up is the unit Y-vector)
- transform.forward: is the z axis direction.
- To view the 3-D world: click on the 2D button at the top/left
of the game editor window
- To zoom into the game camera:, select "Main Camera" (from Hierarchy
view):
- GameObject-> Align View to Selected
- The "Arrow" is an empty GameObject:
- GameObject->CreateEmpty
- Select the newly created object, in Inspector->Add Component ->
Rendering -> Sprite Renderer
- Drag image into the Project folder (import the image, will
copy the image over to the project folder)
- Drag the image from Project/Assets to SpriteRenderer->Sprite
- Make Arrow size 10x10 (otherwise, you can't see it ... 1x1 can
be difficult to see)
- InteractiveControl.cs script:
- this.transform.poition: location of the object
- this.transform.up: Up/Down direction (use the up/down arrow)
- this.transform.right: Right/Left direction (left/right arrows)
- this.transform.RotateAround(Vector3.up, radians): rotates the
object where Up/Right is rotated appropriatedly. After rotation,
Up points
in the rotated up direction.
- Time.smoothDeltaTime (in second units). Hero's speed is 20 units
per second and rotates at 45-degress per second.
- Try this: for the HeroSpeed, change the private
declaration to public and notice this becomes changeable from the UI
(in the Inspector).
- WARNING:
any changes made in game mode will not be saved! (e.g., in
this case if you change the HeroSpeed while in game mode, this
change WILL NOT be saved!)
- Debug: You can stop in the script, single step, examine variables, etc!
- Start game from Unity: in IDE Run->Attach Unity Debugger
- in IDE: Green Button (Attach to Unity) [next time you run the
game, debugger will be active]
- Movements within Game Window Bounds:
- GameManager: an empty GameObject (hanging off the MainCamera)
- GlobalBehavior.cs script is hanging off here
- mWorldBound, mMainCamera: see how these are initialized
- UpdateWorldWindowBound() // <-- MUST be called when
MainCamera is moved/zoomed
- Derived current bound by orthographicsSize and aspect
ratio.
- ObjectCollideWorldBound(): returns the public enum status of
WorldBoundStatus
- EnemyBehavior.cs: Notice:
- NewDirection():
- We can change transform.forward to set a new heading
for the game object.
- But! this method does not work well at all (notice the spinning airplane!)
- How to fix this? Next example
- Update():
- How we access the globalBehavior object by using Find() +
GetComponent()
- InteractiveControl.cs:
- Map left/right arrow to rotation, more intuitive?
- Improved Enemy Behavior: All changes are in EnemyBehavior.cs
- Smaller world
- Desire behavior after colliding with the world boundary: new
direction is towards the world center rather than random (which may
be continue away from the world, and can result in enemy spinning at
the world edge).
- Notice the new control on EnemyBehavior: mTowardsCenter:
- Range is between 0 to 1
- 0: Random half circle towards the world center
- 1: Fly exactly towards the world center
- Algorithm: refer to code comments.
Here is the explaination.
- Creation of Prefab (drag to
Project/Asset from Hierarchy) + Many Enemies:
- Prefab creation: "programming by example" drag an object (Enemy)
from Hierarchy to Asset!
- Created a subfolder to keep Asset folder proper.
- NOTE: the "Resources"
folder name is not an option!! Resources.Load(): depends on it!!
- Deleted the Enemy object from the world
- Changed EnemyBehavior::Start() (random spawning locations)
- GlobalBehavior.cs::SpawnAnEnemy
- How we keep track of time.
- How to load from Resources folder.
- How to Instantiate() from sample.
- Support for collision:
- Both colliding bodies: must have collider defined and enabled.
- To response to a collision: two attributes
- isTriggered: flag on Collider2D must be on.
- RigidBody2D: must be defined.
- You can choose for both bodies to response to collision, or just one.
- In our case: Hero shhots Eggs, Egg and Enemy collide, Eggs participate, Enemy responses.
- Hero (Arrow): InteractiveBehavior
- Check for "Fire1" (left control)
- Instantiate Egg as projectile (again, Egg must be in the Resources
folder)
- Notice: use GetComponent<ClassName> to get access to EggBehavior to
set forward direction
- Note: can also change GameObject's attributes (to change the egg's
position)
- Egg:
- Must put a "collider" on all the collision parties
(Component->Physics2D->Circular Collider 2D [easy to work with]).
- NO need to check the "isTriggered" flag: only the
collision handler [Enemy, in this case] needs it.
- Prefab game object (don't forget to drag in EggBehavior!)
- Behavior: allows outside to set its forward direction and simply
moves forward
- Speed:
100 units per second (multiplied with the Time.smoothDeltaTime)
- How to shoot eggs at a slower rate?
- How to destroy eggs outside of bound?
- Enemy (the plane): colliding GameObject must have RigidBody, and IsTriggered (on Collider) switched on
- First: RigidBody
- Component->Physics 2D -> RigidBody 2D
- Set Gravity Scale to 0 (switching off gravity)
- Second: Collider
- CircleCollider2D: IsTrigger: switched on
- Third: implement OnTriggerEntered2D()
- Notice the Destroy(gameObject) function to remove an object
- Notice: Unity3D run time instantiated object names: "Egg(Clone)"
- Changing Texture + GUI Text:
- Moved textures into Resources/Textures folder (for runtime
loading)
- All actions in GlobalBehavior.Update() function (SpaceBar
to see what the effects)
- To change texture:
- 1. Find the object
- 2. Get the "SpriteRenderer"
- 3. Set the sprite with what we want, in this case we
load a texture that is already imported into Unit3D
- To echo gui text::
- 1. Create GUIText object (GameObject->UI->GUIText),
give the text a proper name
- 2. At run time, simply get the object, get the Component,
and change!
- Also changed: EnemyBehavior.OnTriggerEnger2D
- Audio:
- Background: e.g., hang off GlobalBehavior (Add Component->Audio->AudioSource)
- Loop + Play on Awake (on)
- Hero eggin:
- Build: File->Build Setting