Tuesday, July 28, 2020

Coordinating Multiplayer Game: Photon Bolt



Documentation:

Overview:
  • Feature Comparison between Bolt Pro and Bolt Free:

  • Photon Bolt Requirements:
 
  • Photon Public Cloud Prices:

Bolt Basics Tutorials:
  • Bolt 101-102:
    1. When modify the font size of the button text, the center alignment of the text is lost. Code to change font size: [Bolt 102]
      •     private GUIStyle customButton = new GUIStyle(); // *** create a new variable

      •     void OnGUI()
      •     {
      •         GUILayout.BeginArea(new Rect(10, 10, Screen.width - 100, Screen.height - 50));
      •         customButton.fontSize = 30; // *** change the font size
      •         customButton.normal.textColor = Color.blue;
      •         customButton.hover.textColor = Color.blue;

      •         if (GUILayout.Button("Start Server", customButton, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
      •         {
      •             // START SERVER
      •             BoltLauncher.StartServer();
      •         }

      •         if (GUILayout.Button("Start Client", customButton, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)))
      •         {
      •             // START CLIENT
      •             BoltLauncher.StartClient();
      •         }
      •         GUILayout.EndArea();
      •     } 
    2. Line 42 of Menu.cs needs to be updated: [Bolt 102]
      •                 sceneToLoad: "Quad" 
    3. Network - Server vs. Client vs. Connection: [Bolt 102]
      • Server: A server is the connection that is hosting the game. 
      • Client: A client is normally anyone who is connected to the game who is not considered to be the Server. In short every remote connection from the Server is a Client.
      • Connection: Within Bolt a connection is considered to be a link to another Client/Server over the network.
  • Bolt 103:
    1. Bolt vs. Unity: [Bolt 103]
      • Bolt.EntityBehaviour<T> class inherits from MonoBehaviour.
      • Unity: Start(), Bolt: Attached(); Unity: Update(), Bolt: SimulateOwner().
      • BoltNetwork.FrameDeltaTime property wraps the Unity Time.fixedDeltaTime property,
    2. Entity - Owner vs. Controller vs. Proxy: [Bolt 103]
      • Owner: The creator of the Entity is the Owner. Bolt considers the one that Instantiates the object (through BoltNetwork.Instantiate()) to be the Owner of the created BoltEntity.
      • Controller: An Entity that is controlled by either the server or a remote player. Both the Server and a Client can gain control of a BoltEntity. In most scenarios the Server will be the Owner so one will often read the Server is taking control and other clients are assigned control.
      • Proxy: An Entity that is basically a dummy that is not locally controlled, he is only a replicated puppet. A BoltEntity is considered a Proxy in your connection/game if you're not the Owner or Controller.
    3. Movement Control by Arrows: [Bolt 103]
      •         if (Input.GetKey(KeyCode.UpArrow)) { movement.z += 1; }
      •         if (Input.GetKey(KeyCode.DownArrow)) { movement.z -= 1; }
      •         if (Input.GetKey(KeyCode.LeftArrow)) { movement.x -= 1; }
      •         if (Input.GetKey(KeyCode.RightArrow)) { movement.x += 1; } 
    4. Bolt Tutorial 103 App: Execution file for Mac (Quad_103).
  • Bolt 104:
    1. Global Senders and Entity Senders: [Bolt 104]
      • An event in Bolt can be sent in two different ways: Globally or to a specific Entity. 
      • A global event will be received in the classes which inherits from Bolt.GlobalEventListener and can be sent freely without the need to have an actual Bolt Entity as the target. 
      • An entity event will be received only on the scripts which the entity is sent to and that inherit from Bolt.EntityEventListener.
    2.  Create Events and Assign Properties: [Bolt 104]
      • In Bolt you use EventName.Create(); to create a new event, you then assign the properties you want and call eventObject.Send(); to send it on its way.
    3. Change font size of displayed messages: [Bolt 104]
      • public class NetworkCallbacks : GlobalEventListener
      • {
      •     private GUIStyle customButton = new GUIStyle(); // *** create a new variable
      •     List<string> logMessages = new List<string>();

      •     void OnGUI()
      •     {
      •         customButton.fontSize = 20; // *** change the font size
      •         customButton.normal.textColor = Color.white;
      •         customButton.hover.textColor = Color.white;

      •         // only display max the 5 latest log messages
      •         int maxMessages = Mathf.Min(5, logMessages.Count);

      •         GUILayout.BeginArea(new Rect(Screen.width / 2 - 200, Screen.height - 100, 500, 200), GUI.skin.box);

      •         for (int i = 0; i < maxMessages; ++i)
      •         {
      •             GUILayout.Label(logMessages[i], customButton);
      •         }

      •         GUILayout.EndArea();
      •     }
      • ......
    4. Inside a Bolt class (e.g., class CubeBehaviour), the order of the methods count! [Bolt 104]
    5. Bolt Tutorial 104 App: Execution file for Mac (Quad_104).
  • Bolt 105:
    1. Objects and Arrays: [Bolt 105]
      • Bolt supports built-in replication of complex types called Objects and Arrays.
      • Objects are defined in the Bolt Assets window and can be used as the type for an Array or Object property on a state or another object.
      • Objects gives you an easy mechanism to encapsulate a group of properties and allows you to implement complex hierarchical data in Bolt that is easily re-usable across different Bolt states.
    2. Bolt Tutorial 105 App: Execution file for Mac (Quad_105).
  • Bolt 106:
    1. Download and import Robot package: [Bolt 106] 
    2. Mecanim (State Wide): [Bolt 106] 
      • Using Animator Methods: If you are adding Bolt to a game that already exists and that's using the standard mecanim way of setting parameters on the animation controller it is best to leave this at the default and use the normal mecanim methods like animator.SetFloat and animator.SetBool to change the animator values.
      • Using Bolt Properties: If you are building a new game with Bolt, use the Bolt state properties.
      • Mixed Mode (WARNING): Some properties are set to Using Animator Methods and some are set to Using Bolt Properties. It is easy to cause confusion.
    3.  Disable the Unused Parameters: [Bolt 106] 
      •  Reason: Disable network replication for the Shot and AimWeight parameters, as these are controlled by curves inside of the animations and not directly by the user.
      • Disable: 
        • Remove them.
        • Set the Mecanim setting to Using Animator Methods and then Replication to Local for Each Player. This means that Bolt will read out the values from the curves and expose them in properties for you, but it will not send anything over the network.
    4. Setting Parameters of Bolt Entity for Robot: [Bolt 106] 
      • IPriorityCalculator Query - Use Global
      • IEntityReplicationFilter Query - Use Global
      • Remove 4 extra scripts at the beginning to get rid of errors.
    5. Bolt Tutorial 106 App: Execution file for Mac (Quad_106).

Friday, July 17, 2020

Playing Videos

  1. Playing Video In Unity - Introduction and Session Goals [1/8]:
    • Video Player with First Person Shooter (FPS):
      • Create a scene to play using a video player and a FPS character by shooting it.
      • When we shoot the Play button, the video player will play a video clip on our giant video screen and the Play button will turn into a Stop button.
      • The video has been rendered in real time into a texture of a stretched out cube and at the end it will loop back to the beginning.
      • At the bottom of the screen, the length of the clip and the current time in minutes and seconds are displayed. 
      • If we shoot the Next button, the next video clip will be player. 
      • If we shoot the Stop button, the video will freeze 
    •  Session Goals:
      • Learn how to play video automatically using the Video Player component by dropping a video in the editor and play it when the scene starts.
      • Learn how to control the Video Player via C# script.
      • Learn to create a 3D video player that players can interact with using first person shooter (FPS) controls including: 
        • how to display the time from the video on the UI, and
        • how to map video into an object.
    • Assets Download:
    •  Overview of Video Player:
      •  Import video clips and play them using the Video Player component.
      • The system allows us to feed video footage directly into the Texture parameter of any component that has one. Unity then plays the video on that Texture at run time. There are two different ways to do that.
      • Unity's video features include the hardware-accelerated and software decoding of video files, transparency support, multiple audio tracks, and network streaming.
      • The Video Player component and Video Clip asset, introduced in Unity 5.6, supersede the earlier Movie Texture feature.
    • Next Step:
      • Set up the video player to play on its own in a scene before we get into the scripting.
      • Get a quick overview of the Video Player.
  2. Playing Video In Unity - The Video Player Component [2/8]:
    • Set up a separate Static Video Player in space. It's an empty game object with an Audio Source attached. We also have a Camera which is a child of the game object, and there is a Cube in front of the Camera.
    • If we want to display our video and have it played automatically when our scene starts, all we need to do is add a component which is under Video > Video Player. 
    • The Video Player works in a way very similar to the Audio Source works.
      • The first thing is to decide what is the Source for this Video Player:
        • a video clip in our assets, or
        • a URL. You can streaming in video from a server by providing a URL.  
      • We are going to use Video Clip mode and we have a field for a video clip asset.
      • Drag and drop a video clip from the asset folder into the Video Clip slot.
      • Play On Awake: The checkbox should be checked which means as soon as the game object wakes and receives the awake callback. In this case, it will be the start of the scene.
      • Wait For First Frame: The checkbox should be checked means starting the counter only when the first frame is actually ready such that there is no perceptible delay in this setup. (Or, we can start the counter and wait for the video to catch up.)
      • Loop: Should be on and we can adjust the Playback Speed.
      • Render Mode: Render Texture is the default and we will use the render texture for our 3D example. However, for now, we are going to use Camera Far Plane mode so that we can see them.
      • Camera: This empty field came up due to our selection of Camera Far Plane mode. Drag in our child Camera of the Static Video Player. We are going display the video on this Camera's Far Plane. Camera Far Plane is the huge rectangle at the end of the Camera's view right frustum, i.e., the rectangle that is the farthest plane that the camera can see. The Camera Near Plane is the smallest, nearest rectangle that the camera can see. We can choose either the Near or Far Plane mode.
      • In order for these two render modes to work, we need to set the Rendering Path in our Camera to Forward by clicking Camera > Rendering Path > Forward.
      • Before we start playing, we need to disable our FPS Controller by clicking FPSController > uncheck the FPSController.  
      • Now, we can run and the Camera (using Far Plane) will take over. Our video is the background and our scene geometry (Cube) is being drawn in front of it.
      • If we switch to Near Plane, we are going to play our video in full screen.
      • Aspect Ratio: Allow us to stretch or scale our video.
      • Audio Output Mode: Should be in Audio Source mode. Direct mode may not be working on some platform (2017).
      • Audio Source: Drag the Audio Source component to the slot as a reference.
      • Track: We can choose which track to play if there are multiple tracks in the movie.
      • Now, we can play the video in full screen and the audio plays through the Audio Source.
    • Next Step:
      • Set up the interactive 3D video player.
    •  Q&A:
      • Can the video be played on non-flat surface? Yes, the video will be put into the Texture, so it can be played on any surface.
      • Can we jump skipped video to certain point? Yes, however, you will lose audio sync. So, it only work without audio. Currently (2017), it cannot skip without losing audio sync. An alternate way is to use multiple clips.
  3. Playing Video In Unity - Texturing Objects With Video [3/8]:
    •  
    •  
    •  
    •  
    •  
    •  
  4. Playing Video In Unity - Playing and Pausing [4/8]:
    •  
    •  
    •  
    •  
    •  
    •  
    •  
  5. Playing Video In Unity - Playing A New Clip [5/8]:
    •  
    •  
    •  
    •  
    •   
    •  
  6. Playing Video In Unity - Displaying Current Time and Clip Length [6/8]:
    •  
    •  
    •  
    •  
    •  
    •   
  7. Playing Video In Unity - Animated Playhead [7/8]:
    •  
    •  
    •  
    •  
    •  
    •  
  8. Playing Video In Unity -Questions and Answers [8/8]:
    •  
    •  
    •  
    •  
    •  

Thursday, July 16, 2020

Designing Levels

  1. Build Levels Easily with Unity Snaps!
    • Advantages Using Snaps:
      • Snaps are pre-build assets built by Unity which allows us to quickly build the level in minutes by just snapping them together.
      • All the Snaps asset packs are built with ProBuilder that allow us to customize them as needed.  
    • Get Snaps Assets:
      • Go to the Assets Store and searching for Snaps.
      • Two types of Snaps assets: snaps prototype and snaps art HD. Both types basically have the same shape. However, the snaps prototypes are super lightweight models whereas these snaps art HD are very good and working high-definition assets. 
      • We can easily swap between the snaps prototypes and the snaps art HD by clicking a button! 
      • Purchase the prototype version and click Open in Unity. Download and import it.
    • ProGrids:
      • Click Tool tab > ProGrids to open ProGrids window. ProGrids allows us to easily snap an object onto a grid. 
      • There are buttons in the ProGrids window to interact with the Grids such as making the grids visible or not, or enable or disable the snap. 
    • Build Level with Snaps:
      • Drag a floor into the scene and it will snap into the grids. All the objects have been built in a standard way in order to snap into each other.
      • We can click the Snaps Settings > Snaps Value and change the scale of our grids from 1 to 3.
      • We can duplicate and set up all our floor tiles.
      • Now we can drag some walls and rotate them as needed. Continue the same things to build up a level.
      • Pick up Point Light from the hierarchy and place them in the placed needed. We can change the color of the light.
      • Pick up Area Light from the hierarchy and place them in the placed needed. We can change the length, intensity and color of the light.
    • Swap to Art HD Assets:
      • Get the Art HD assets from the asset store. Click Open in Unity. Download and import it.
      • In the Project folder, under Assets > UnityIconCollective we have the ArtHD folder. Here we can find the exactly the same prefabs as in the prototype version.
      • Go back to asset store and search for Asset Swap Tool. Open it and we will see a Snaps Menu (tab) on top.
      • Click it and open the Asset Swap Tool.
      • Under Tool Settings, select the proper directory for the Snaps Prototype and select the proper directory for the Art HD.
      • Under Bulk Swap in the Scene, click Swap All to Snaps Art HD prefabs button and everything changed to the HD quality.
      • Under Bulk Swap in the Scene, click Swap All to Snaps Prototype prefabs button and everything changed to the Prototype quality.
    • ProBuilder:
      • ProBuild is a tool allowing us to do 3D modeling inside the Unity. We can easily edit our assets to fit our needs.
      • First, install the package. 
      • Click Tools > ProBuilder > ProBuilder Window. Now, with this window we can modify our assets. 
      • Click the ProBuilderize button in the window and now we can click anything, add a Mesh by clicking the Mesh tab and start changing it.
  2.  
    •   
    •  
    •  

  3.  
    •  
    •  
    •  

Saturday, July 11, 2020

Creating Terrains

  1. How to make Terrain in Unity!
    • Get Terrain Tools:
      • Click Window > Package Manager and make sure we have All Packages selected and go under Advanced >Show Preview Packages and click Open.
      • Search for Terrain Tools (it's a preview package) and click Install.
      • Click Download Asset Samples from Asset Store button. Or we can click the Asset Store tab to open Asset Store and search for terrain sample assets.
      • Download and Accept this free pack which features more brushes that you can use while sculpting and painting as well as some cool sample textures. 
      • Click Import and Import again to finish the setup.
      • In our Assets folder, we can now find a Samples folder with all the Terrain Tools including
        • BrushTextures
        • TerrainBrushes
        • TerrainLayers
        • TerrainTextures
    • Create a New Terrain:
      • There are two ways to create a Terrain:
        • Control-click the hierarchy > 3D Object > Terrain to spawn in a huge piece of terrain into our scene.
        • Window > Terrain > Terrain Toolbox with a new window to easily set up terrains. Grab the Terrain Toolbox and dock it next to the Inspector window.
      • We can change the Width, Length and Height of the Terrain.
      • Hit Create to create a terrain in our scene.
      • Now we have a new folder called Terrain in our Assets and within it we have a Terrain Data Object which stores all the information about our terrain such as where are the hills and slopes and which texture we apply.
      • In the hierarchy we can also see a new object in the hierarchy called TerrainGroup_0 and within this a Terrain Object. 
      • This object has two components:
        • Terrain Component: is used to configure our terrain and change our sculpting and painting settings.
        • Terrain Collider: creates a Collider so that physics objects will interact with our terrain.
    • Sculpt Terrain:
      • Go to the Environment tab on top to disable the Fog so you can see everything clearly.
      • Go to Lighting to make sure the Auto Generate (Generate Lighting) is turned off. 
      • In the Terrain component, select Paint Terrain tool. There are many modes.
      • Raise or Lower Terrain:
        • First, make sure that we have Raise or Lower Terrain selected and now we can choose various brushes to paint the terrain.
        • Pick a soft brush, hover around our terrain and press to start sculpting.
        • We can adjust the Strength (a), Size (s), Rotation (d) and Spacing (f) of the Brush. 
        • Shortcuts can be changed by Edit > Shortcuts...
        • We can also hold down the Control to inverse the effect - lowering the terrain and reduce the size of the brush.
        • Change Spacing will change the distance between each individual brushstroke and we can also use Scattering to randomly scatter our brush.
      • Set Height:
        • Change from Raise or Lower Terrain to Set Height which allow us to set the terrain to certain height.
        • Drag the Height slide-bar to certain value and do a soft brush and increase the size. 
        • Now we can paint everything with this height.
      • Smooth Height:
        • Select Smooth Height mode and it allow us to smooth out our terrain.
        • We can adjust the brush strength to reduce the impact of the smoothing.
      • Add Noise:
        • Select Sculpt > Noise to allow us to paint noise to our terrain.
        • We can go to the Noise Height Tool Settings. We adjust the Scale of our noise such as (20, 20, 20), and change the strength.
        • Now we can paint this type of noise and add details onto our terrain.
      • Build Bridge:
        • Select Sculpt > Bridge to allow us Control-click a starting point and then click another place in our terrain to create a bridge or road across it.
      • Terrace:
        • Select Sculpt > Terrace to divide our terrain into terrace or layers.
        • We can adjust Terrace Count to change the appearance of the effect.
      • Erosion:
        • Select Erosion > Hydraulic to erode the terrain according to fluid simulation. We can change the Advanced option of the Simulation Scale of the Hydraulic Erosion Controls component to smooth out the terrain.
      • Change Settings:
        • Click the Terrain Settings tab of the terrain to change any settings. For example, under Mesh Resolution (on Terrain Data), we can change the Width, Length and Height of the terrain to (2000, 2000, 500). 
        • If we need to adjust the settings of multiple terrains, we can use the Terrain Toolbox to do that instead going to each one individually. 
      • String Multiple Terrain Tasks Together:
        • The terrain system allows us to string together multiple terrain tasks. 
        • Click the first tab to create four neighboring terrains and the heigh data is going to seamlessly onto the terrain.
        • We can create all four of them and start to paint.
        • To do this we need to make sure that all the terrains sharing the same Grouping ID. Grouping ID can be found by clicking Settings tab and under the Basic Terrain. Also, they need to have the same resolution.
      • Paint Texture:
        • Change the mode to Paint Texture and working Terrain Layers.
        • Click Edit Terrain Layers... > Create Layer... to create a new layer since there is currently no layers. (Add Layer... means adding existing layers)
        • A panel will pop up and we can select a texture (e.g., dirt_albedo) to create a new layer.
        • Now we can see a new texture for the Terrain Layer and the is a new object called New Layer in the Assets. Let's click it and rename it Dirt Layer. 
        • In the Inspector window we can see the settings such as Diffuse. We can also input the Normal Map by selecting dirt_normal and input the Mask Map by selection dirt_mask. We can adjust metallic and smoothness, and see the effect applies to our entire terrain. We can also adjust the Tiling Settings to, e.g., 10 x 10.
        • Now we can add another Layer by clicking the Edit Terrain Layer... button and select Add Layer... In this sample assets, we can add rock layer, sand layer, scree layer, snow layer and moss layer. We are ready for painting.
        • We can increase the Brush Size and play around the Opacity. 
        • Add rock, moss, scree. sand and snow to the terrain.
    •  Create Terrain from a Height Map:
      • Height maps are gray-level images storing height information. White parts are high and black parts are low. There are lots of free height maps online.
      • The format of the height maps needs to be ".raw" and we can use photo-editing software like Photoshop or Gimp to convert them. 
      • Drag the terrain into the Unity and add to the Assets.
      • Go to the Terrain Toolbox > Create New Terrain > check the checkbox of Import Height Map > Select Heightmap File > clicking and select the Height Map.
      • We can change the Tile Height Resolution (doesn't need to be the same as the height map) to 512 and adjust the Height Remap to decrease the max. height.
      • We also want to make sure that we aren't create this in the same grouping ID as our previous terrain (0), so set it to 1.
      • Hit Create button and we just create a new terrain based on the height map.
      • Go back to Lighting and re-enable Auto Generate and it's going to generate a light map for your terrain.
      • We are Done!
    •  

Thursday, July 2, 2020

Basic Unity Tutorials

  1.  How to make a Video Game - Getting Started
    • Video game creation team: 3D modeling, programming, concept art and sound design. 
    • Game engine: rendering, networking, sound, collision, AI, threading, localization, physics, animation, asset pipeline, scripting, etc.
    • Source engine: Half-life 2, Counter-strike and Portal
    • Free engines: Torque, RPG Maker, Mar ma lade, Unreal engine, Unity, Gamebryo, Construct 2, Source, Impact, Cocos 2D, Cryengine, and GameMaker Studio 2.
    • 2D game: GameMaker Studio 2 is easy (Spelunky, Undertale and INK). Only export to Windows using the free version.
    • 2D & 3D game: Unity can export to variety of platforms. Games such as Hearthstone, Superhot and Kerbal space program. Also good for mobile developers.
    • Advanced game: Unreal Engine. Games such as Unreal tournament, Gear of War and Arkham Knight.
    • Unity: diversity. Support 2D and 3D and deploys to both web, desktop, mobile and console. Programming includes C# and JavaScript.
  2.  How to make a Video Game in Unity - BASICS (E01)
    •  Install Unity.
    •  Create new project with 3D.
    •  Scene view (middle) user interface:
      •  up/down of 2 fingers on trackpad to zoom in/out.
      •  option key and 1 finger on the trackpad to pivot around.
      •  option & command keys and 1 finger on the trackpad to pan around
    •  Hierarchy Panel (left) displays all the game objects in the scene.
    •  Inspector Panel (right) display the properties of an object. Each collapsable thing in the Inspector window is called Component. Components make objects do different things.
    • Project Panel (down) shows all the different game assets that we can drag into our scene and make them appear in our hierarchy.
    • The user interface can be rearranged randomly and reset by clicking the Layout tab (upper-right corner) and select Default. Any window needs to be open can be selected by clicking the Window tab (top) and selecting the specific window.
    • Create Ground Plane:
      • Click + > 3D Object > Cube (upper right corner) or control-click hierarchy panel > 3D Object > Cube.
      • Focus the object: Select the object and type f.
      • Reset the position: Control-click Transform component > Reset will move the cube to (0, 0, 0) and scale (1, 1, 1).
      • Game view: Can be drag and placed next to the Scene.
      • Change view: Select the camera and move it, and the Game View will change accordingly.
      • Scale the cube: From (1, 1, 1) to (15, 1, 100).
      • Rename: Just type the new name, Ground, in the Inspector.
    • Create a Player: 
      • Create another object: Click + > 3D Object > Cube (upper right corner) or control-click hierarchy panel > 3D Object > Cube.
      •  Reset the Transform to center on the Scene and use the Green Arrow to move it up to stand on the Ground.
      •  Rename it to Player.
      • Change Player color or Assign Material to Player: control-click the Project Panel > Create > Material and rename it to Player Made for Material. Now we can adjust properties of the material.
      • Move our Camera to view the Player at better position.
    • Add Physics to Player:  
      • Go to Inspector Panel and Add Component > Physics > Rigidbody.
      • Hit Play and the Play should fall down.
      • Use tools (upper-left corner) to manipulate the Player: Hand Tool (Q), Move Tool (W), Rotate Tool (E), Scale Tool (R) and Rect Tool (T).
      • After rotating the Player, Play again.
    • Duplicate the Player: 
      • Undo the rotation.
      • Command-d to duplicate the player and move it upward and over a bit. 
      • Play again. 
    • Components:
      • Transform: Universal to all objects including position, direction and scale.
      • Mesh Renderer (Optional): Make object visible by drawing objects on screen.  
      • Box Collider (Optional): Allow objects to collide with other objects.
      • Rigidbody (Optional): Add physics to objects. We need both Box Collider and Rigidbody to have realistic physics.
      • Cube (Mesh Filter) (Optional): Choose the shape of the object. It can be changed to sphere, capsule, cylinder, etc. 
    •  Change Cube to Sphere:
      •  Cube (Mesh Filter) > Sphere.
      • Remove Box Collider.
      • Add new component: Sphere Collider.
      • Any change in the Play mode will be discarded once exiting the Play mode.
    •  Change Skybox:
      • Select Main Camera > Clear Flags > Solid Color and pick a color.
      • Maximize the game view by shift-space.
      • Save the Scene by command-s or File > Save. 
  3. How to make a Video Game in Unity - PROGRAMMING (E02)
    •  Goal: Use C# to Change properties and add force to an object.
    •  Create a Script:
      •  Click on the object and Add Component > New Script > Name (Player Movement) and Language (C Sharp) > Create and Add.
      • It will create a script file in the Project Panel. That means we can apply the Script to another object by clicking a new object and drag the Script file to the Inspector Panel under Add Component.
      • Double click on the Script file and it will open the editor.
    •  Download Visual Studio for Mac:
    •  Hello World!
      • Delete first two using lines.
      • Start function: Execute when you start the game. Add Debug.Log("Hello World!");
      • Command-s and hit Play.
      • Click the Console tab next to the Project window to see the output.
      • Console also displays warnings and errors.
      • We can modify values, add forces to objects, add explosions, create game timers and menus, etc.
    •  Go into Rigidbody and Disable Gravity from the Object:
      • Add: public Rigidbody rd; before void Start ().
      • Now, in the Player Movement (Script) component, we can see an Rb with value None (Rigidbody). 
      • Drag Rigidbody into that None (Rigidbody), and it will become Player (Rigidbody).
      • We can now replace the Debug.Log statement by rb.useGravity = false;
      • Now run it again and the Use Gravity property of Rigidbody will be unchecked.
      • Duplicate the Player and run. The cubes will bounce toward both directions.
    •  Add a Force to the Rigidbody:
      •  Replace rb.useGravity = false; by rb.AddForce(0, 200, 500); This will only apply force at the beginning.
      • To add force to the object every frame, remove void Start () and add rb.AddForce(0, 0, 500 * Time.deltaTime); Time.deltaTime  = 1/Frame Rate. So, it will even out the force.
      • Change FixedUpdate () instead of Update () whenever calculating Physics (force, velocity, etc.).
    • Add another Object:
      • Add another cube.
      • Move it to the path of the Player and hit run.
  4. How to make a Video Game in Unity - MOVEMENT (E03)
    • Download free Assets from www.devassets.com for free.
    • Freeze Motion in Certain Direction: 
      • select the object (Player),  
      • click Rigidbody > Constraints > Freeze Rotation > x/y/z in the Inspector panel. 
    • Create a Frictionless Motion:
      • select the object (Ground), 
      • command-click the Assets panel > Create > Physics Material, 
      • rename it as "Slippery",
      • set both the Dynamic and Static Friction to zeros,
      • drag the Physics Material (Slippery) to the Object (Ground) in the Scene.
      • Now, the Box Collider component of the Ground object will have a Material: Slippery.
      • Run it and there will be no friction.
    • Make the Force to a Variable: 
      • Variables can store numbers, text, dictionaries, stacks, lists, graphs, trees, queues, animation, matrices, arrays, structs, maps and custom classes. 
      • select the Player and double-click its Script,
      • declare a variable: public float forwardforce = 1000f; and change the force to a variable (forwardforce).
      • Now the variable forwardforce can be edited in the Inspector.
    • Get Player's Input:
      •  Add the following code:
        •         if (Input.GetKey("d"))
        •         {
        •              rb.AddForce(500 * Time.deltaTime, 0, 0);
        •         }
        •         if (Input.GetKey("a"))
        •         {
        •             rb.AddForce(-500 * Time.deltaTime, 0, 0);
        •         }
      • or, change the sideway force to a variable sidewayforce:        
        • public float sidewayforce = 500f;
        • if (Input.GetKey("d")) 
        •     rb.AddForce(sidewayforce * Time.deltaTime, 0, 0);
        • }
        • if (Input.GetKey("a"))
        • {
        •       rb.AddForce(-sidewayforce * Time.deltaTime, 0, 0);
        • }
      • The current way to handle player movement is not the optimal way:
        • when we want to do smoothing player input or supporting alternate keys or even a controller, there is much better way to handle player input.
        • currently check the player input in the FixedUpdate(), and it's okay to just handle movement. For jumping or one-off events, if the FixedUpdate() runs slower, we can miss some player input. It means that the input gets slightly delayed.
        • The better way is to check for an input in the update method then store that input in boolean variables (e.g., moveRight and moveLeft). Set it true when the keys pressed and false if the keys released. And then check those variables down here to add a force.
  5. How to make a Video Game in Unity - CAMERA FOLLOW (E04)
    • Making camera following the player can be done simply by dragging the Main Camera to the Player. This will make the Main Camera become the "child" fo the Player and follow the Player all the time. The problem of this method is when the Player rotates, the Main Camera will also spins and it will create a very confusing view. So, the better way is to use scripts.
    • Create Camera Script: 
      • Select Main Camera, click Add Component and search for a public class called FollowPlayer, then click Add and Create.
      • Remove the first two line of using statements and the Start () method.
    • Snap camera position to the Player each frame by doing the code in the Update () method.
    • Reference to and Follow the Player:
      • Declare public Transform player; and save it. Transform is a data type representing the position, rotation and scale of an object. 
      • Now we can see an empty slot, None (Transform), in the Player property of the FollowPlayer Script component.
      • Drag the Player into the empty slot to make the connection and point to the specific Player.
      • Now, each time we write player in our code, it refers to the Player.
      • To test it, we can write Debug.Log(player.position) into the Update () and run it. We will see the position of the Player in the console following the position in the Inspector window.
      • Now, we can take the camera Player position and feed it the the camera by writing transform.position = player.position;. The "transform" refer to the Transform of our current object. We make the camera's position equals to the Player's position every frame.
      • Run it and we will get the first-person view of the world as the camera is locate at the center of the Player. 
    • Create Offset to the Camera Position:
      • Declare another variable: public Vector3 offset;Vector3 is a data type store 3 float numbers.  
      • Now we can see an offset property of the FollowPlayer Script component and we can set it to x = 0, y = 1, z = -5.
      • Rewrite the code: transform.position = player.position + offset; and run it!
      • Now camera will follow behind the Player wit offset position and when the Player rotates, the camera will not.
  6. How to make a Video Game in Unity - COLLISION (E05)
    • Add a new script to the Player: 
      • Select Player and Add Component by creating a public class called PlayerCollision and click Create and Add.
      • Delete the first two using statements and remove both Start () and Update () methods.
    • Add an Obstacle (Cube):
      • Use the existing Cube and rename it to Obstacle.
      • Change the Scale to (2, 1, 1).
      • Create Material, name it ObstacleMat and drag onto the Obstacle.
      • Change Albedo color, Metallic and Smoothness.
      • Add a Rigibody and set the Mass to 2.
      • Play!
    • Add Code for Object Collision: 
      •  Unity has a specific function to handle collision: void OnCollisionEnter (). This method will be called whenever the object is collided with something.
      • We can add this collision script to any object as long as it has a Rigibody and a Collider.
      • Put code Debug.Log("Got Hit!!!"); in the void OnCollisionEnter () method to display collision message.  
      • There will be two messages including hitting Ground and the Cube.
    •  Check What has been Collided:
      • Replace the current method by the following code:
        • public class PlayerCollision : MonoBehaviour
        • {
        •     void OnCollisionEnter(Collision collisionInfo)
        •     {
        •         Debug.Log(collisionInfo.collider.name);
        •     }
        • }
      • Run it and it will display the object when collision. 
    • Check whether an Obstacle has been Hit: 
      •  Replace the current method by the following code:
        • public class PlayerCollision : MonoBehaviour
        • {
        •     void OnCollisionEnter(Collision collisionInfo)
        •     {
        •         if (collisionInfo.collider.name == "Obstacle")
        • {
        • Debug.Log("HIT OBSTACLE!");
        • }
        •     }
        • }
      • Run it and it will only display when collides with Obstacle. 
    •  Check whether an Obstacle with Certain Tag has been Hit:
      • When there are lots of obstacles, check individual names can be impossible, and when the objects are renamed, the code will no longer work. The better way is to check tags. Tags can be used to group object together.
      • Go to Tag property of the Obstacle and click the Untagged > Add Tag.... Click + sign, type in Student and then Save. Click Obstacle again and click Untagged and select Student. No we have created a new tag, Student, for the Obstacle.
      • Replace the current method by the following code:
        • public class PlayerCollision : MonoBehaviour
        • {
        •     void OnCollisionEnter(Collision collisionInfo)
        •     {
        •         if (collisionInfo.collider.tag == "Student")
        • {
        • Debug.Log("HIT STUDENT!");
        • }
        •     }
        • }
      •  Run it and it will display "HIT STUDENT"!
    • Stop Player after Collision: 
      • Add a new variable: public PlayerMovement movement; where PlayerMovement is the name of our script. Save it.
      • Now we can see there is an empty slot, None (Player Movement), appeared in the Player Collision property.
      • Drag the Player Movement (Script) into that slot to create a reference from the Player Collision script to the Player Movement script.
      • Replace the current method by the following code:
        • public class PlayerCollision : MonoBehaviour
        • {
        •     void OnCollisionEnter(Collision collisionInfo)
        •     {
        •         if (collisionInfo.collider.tag == "Student")
        • {
        • movement.enabled = false;
        • }
        •     }
        • }
      • Run it! We will see the Player stopped after collision and the Player Movement (Script) property turned off!
  7. GAMEPLAY - How to make a Video Game in Unity (E06)
    •  Use prefabs: Prefabs are used when we need multiple objects of the same types.
      • Drag the Obstacle to the Assets panel to create a Prefab.
      • Drag the prefab in anywhere into our scene.
      • If we modify the properties of the prefabs, all the objects will be updated at once.
      • For example, if we change the mass of one Obstacle and then click Apply, all the masses will be changed.
    •  Extend the Ground Plane:
      • On common thing to do when creating endless-runners is not actually move the players, but instead move all the obstacles and environment pieces closer to the player as the game progresses. So the ground element is stationary.
      • In order to have some cool physics effects and that look better if we move the actual player. So, we should scale up the ground.
      • Change the Scale to (15, 1, 10000) and the Position to (0, 0, 4980).
    • Sketch out the Level:
      • Get the right view in the scene by using the the axis sphere:
        • Click x, y or z to see different perspective view from that axis.
        • Click the center cube to get isometric view.
      • Enable/Disable the Environment: 
        • Click the Environment to enable or disable all the Skybox, Fog, Flares, etc. 
        • Click the pull-down menu to toggle individual component. 
      • Turn On/Off the Grid: 
        • Click Grid to turn on or off the grid.
        • Click the pull-down menu to toggle grid in individual direction.
      • Add Layers to Ground:
        • Select Ground, click property Layer > Add Layer... and add a layer call Environment.
        • Click property Layer again and select Environment.
        • Click Layer tab on the upper-right corner and lock the Environment.
        • Now we can no longer select Ground in the scene (though we can still select it from the Hierarchy). It will make selecting objects in our scene much easier.
      • Move Object Snapping to the Grid:
        • Select an Obstacle and click the green square, we can drag it anywhere along the x-z plane.
        • Click Edit > Grid and Snap Setting to set up how objects snap to the grid.
        • Change Increment Snap > Move to 2, Scale to 0.1 and Rotation to 15, then close it.
        • Now if we move the Obstacle and hold on command key, the object will snap to every 2 units.
      • Duplicate the Obstacles:
        • Select an Obstacle or multiple Obstacles and click command-d to duplicate.
        • command-click and drag the duplicated objects and move them around.
      • Level Design by Adding Objects:
        • Collectable coins.
        • Obstacles move back and forth.
        • Stuff to jump over or go beneath. 
    • Force Mode:
      • In order to make the manipulation more responsive, change the Force Mode can improve the sensibility. Because adding forces to objects, it takes time to build up the momentum and change direction.
      • Double click the Player Movement (Script).
      • Add ForceMode as the fourth parameter to the rb.AddForce() and choose VelocityChange mode.
      • Code:
        •         if (Input.GetKey("d"))
        •         {
        •             rb.AddForce(sidewayforce * Time.deltaTime, 0, 0, ForceMode.Impulse);
        •         }
        •         if (Input.GetKey("a"))
        •         {
        •             rb.AddForce(-sidewayforce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        •         }
      • Four Force Modes: 
        • Force (= 0): Add a continuous force to the Rigidbody, using its mass.
        • Impulse (= 1): Add an instant force impulse to the Rigidbody, using its mass.
        • VelocityChange (= 2): Add an instant velocity change to the Rigidbody, ignoring its mass. 
        • Acceleration (= 5): Add a continuous acceleration to the Rigidbody, ignoring its mass.
      •  The force should be smaller now for the VelocityChange mode. Set the Sidewayforce to 120.
    • Add Drag:
      • Drag is air resistance. The higher the drag, the faster the object is going to be stopped by air. It also means we need to increase our ForwardForces in order to move at the same speed. 
      • Change the Drag to 1 and increase the Forwardforce to 2000.
      • Use command-p to Play.
    • Add Fog:
      • Make the game more interesting.
      • Click Window tab > Rendering > Lighting Setting and there will be a Lighting window pop up.
      • Under the Scene tab, scroll down to find Fog and click the checkbox to enable the Fog.
      • Set the Fog Color to the Skybox's color such that everything is blended in.
      • Increase the density to 0.1.
      • Shift-space to maximize the view and command-p to Play!
  8. SCORE & UI - How to make a Video Game in Unity (E07)
    • Create folders to organize Assets: Scripts, Materials, etc.
    •  Fix Issue: Players Sometimes Pass through the Obstacles 
      • To get more accurate physics detection, select Obstacles, change the Collision Detection property in the Rigibody component from Discrete to Continuous.
      • Do the same thing for our Player.
      • Click Edit tab > Project Setting > Time to reduce the Fixed Timestep to 0.01. This means Unity will update physics more frequently and the chance to miss a collision is decreased.
      • This also means we need to select the Player and increase the Forwardforce a little bit to 2500. 
    • Create UI:
      • Control-click the Hierarchy > UI > Text to create a Canvas. Canvas is a place to display all our differentUI elements and a text object.
      • Switch to 2D mode by clicking the 2D tab in the Scene. Select Text in the Hierarchy and hit f to zoom out to see the entire canvas.
      • The canvas will resize automatically to fit our Game View.
      • Drag the Textbox to the upper-center of the canvas.
      • Change the alignment of the text both to the center horizontally and vertically. 
      • We can resize out Textbox (boundary of text) by dragging the corner of the Textbox.
      • To scale the actual Text needs to change the font size to 70. Make sure the Textbox is large enough to hold the highest score. 
      • Set the Horizontal Overflow from Wrap to Overflow such that the text will keep going even reaches the boundary.
      • Change the Text value to 250 as an example.
      • When resizing the Game View, the Text (250) does not change size and always the fixed distance from the center.
      • To fix the resize issue, click Canvas, change the UI Scale Mode from Constant Pixel Size to Scale with Screen Size. Now if we maximize our Game View, the font gets resized too.
      • Change the Color of the Text.
      • Download and Change to New Fonts:
        • Go to the browser and Google Roboto.
        • Download the font and unzip it. 
        • Select all the font files and drag them into the Unity Assets.
        • Create a folder called fonts and drag them into the folder.
        • Now we can change font to Roboto.
    •  Updating Text:
      • Text (score) can be updated with time or distance traveled by player. Let's try distance.
      • Create a new script, Score, on the Text object.
      • Remove the first 2 using statements and the Start() method.
      • Add a variable: public Transform player;
      • Add a statement in the Updated():
        •     void Update()
        •     {
        •         Debug.Log(player.position.z);
        •     }
      • Select the Text object and drag the Player form the Hierarchy to the Player property of Score (Script) component.
      • Hit the Play and see the Console.
      • Add statement using UnityEngine.UI; whenever dealing with UI functions.
      • Add variable public Text scoretext;
      • Add a statement in the Update(): scoretext.text = player.position.z.ToString("0");   where scoretext.text is a string and player.position.z is a float and ToString("0"); converting float to String with zero decimal numbers.
      • Drag the Text component to the Score Text property of Score (Script).
      • If the Text doesn't look crisp, select Canvas and choose Pixel Perfect to make the UI rendering much sharper.
      • Now hit the Play and go!
  9. GAME OVER - How to make a Video Game in Unity (E08)
    •  Create a Game Manager:
      • Control-click the Hierarchy to Create Empty and rename it to GameManager.
      • Create a new component (Script) called GameManager. This component will be responsible for changing the states in our game. 
      • The states of the game:
        • Start and stop a game.
        • Restart a game.
        • Display UI on the screen for score counter.
        • Game over screen.
        • Transition to other menus like a main menu or level selector.
    •  Restart a Game When Hitting Obstacles or Fall Off the Edge:
      • Open the GameManager Script.
      • Delete the first 2 using statements and 2 standard functions, Start() and Update().
      • Write a new function void EndGame()
      • Write a statement to check whether the game is ended at the right time: Debug.Log("Game Over");.
      • Save it and go back to Unity.
      • Now our GameManager has a function called EndGame() that will display a message in the console. But we need a way to access our GameManager and call this function.
      • Assessing Functions inside a Script through Variables:
        • The normal way to access something within another script is to use the reference such as declaring a variable: public GameManager GameManager; and save that.
        • Then Drag the GameManager in the Hierarchy to the Game Manager property of the Player Collision (Script) component of the Player. 
        • The problem is when we remove the Player (if Player dies) and restart with a new Player, the reference in the player is gone!
        • So, instead using a variable, we search the GameManager when we need it since Unity has a nice way to search for a script.
      • Assessing Functions inside a Script through Searching:
        • Remove the variable declaration we have done earlier.
        • Insert a statement: FindObjectType<GameManager>().EndGame();. into the if statement to find the GameManager and its function.
        • By the same token, we can also replace movement.enabled = false; by GetComponent<PlayerMovement>().enabled = false;.
        • Now the code will be look like:
            • using UnityEngine;

            • public class PlayerCollision : MonoBehaviour
            • {
            •     public PlayerMovement movement;

            •     void OnCollisionEnter(Collision collisionInfo)
            •     {
            •         if (collisionInfo.collider.tag == "Student")
            •         {
            •             //movement.enabled = false;
            •             GetComponent<PlayerMovement>().enabled = false;
            •             FindObjectOfType<GameManager>().EndGame();
            •         }
            •     }
            • }
                                              • The EndGame() is not visible because it is a private function of the GameManager. To make it visible, change the EndGame() to public by:
                                                • using UnityEngine;
                                                • public class GameManager : MonoBehaviour
                                                • {
                                                •     public void EndGame()
                                                •     {
                                                •         Debug.Log("GAME OVER!!!");
                                                •     }
                                                • }
                                            •  Display GAME OVER when Player Falls off the Edge:
                                              • Select Player and open PlayerMovement script.
                                              • Add statement to check the y position below certain number (-1):
                                                • if (rb.position.y < -1f)
                                                • {
                                                •      FindObjectOfType<GameManager>().EndGame();
                                                • }
                                              • By doing so, Unity will detect the fall and printout many "GAME OVERs".
                                              • To get rid of the extra ones, modify the GameManager by
                                                • Add a variable: bool gameEnded == false;
                                                • Add an if statement to print the GAME OVER only once.
                                                • Code: 
                                                  •     public void EndGame()
                                                  •     {
                                                  •         if (gameEnded == false)
                                                  •         {
                                                  •             Debug.Log("GAME OVER!!!");
                                                  •             gameEnded = true;
                                                  •         }
                                                  •     }
                                              • By doing so, we will only display the GAME OVER once! 
                                            •  Restart a Game:
                                              • In the GameManager, add a function Restart().
                                              • Add a function call to Restart() in EndGame().
                                              • Add using UnityEngine.SceneManagement; to go to a different Scene or reload the Scene we are already on.
                                              • Add a statement into the Restart() to restart.
                                              • Code:
                                                • using UnityEngine;
                                                • using UnityEngine.SceneManagement;

                                                • public class GameManager : MonoBehaviour
                                                • {
                                                •     bool gameEnded = false;

                                                •     public void EndGame()
                                                •     {
                                                •         if (gameEnded == false)
                                                •         {
                                                •             Debug.Log("GAME OVER!!!");
                                                •             gameEnded = true;
                                                •             Restart();
                                                •         }
                                                •     }

                                                •     void Restart ()
                                                •     {
                                                •         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
                                                •     }
                                                • }
                                            •  Now the game will restart, but there are two issues: 
                                              • Lighting in restart is discontinuous.
                                              • Needs delay between two scenes.
                                            • Lighting: 
                                              • Click Window tab > Rendering > Lighting Setting and the Lighting panel will pop up.
                                              • Uncheck the Auto checkbox and click the Auto Generate button next to it since during the scene change, Unity has no time to calculate the lighting.
                                            •  Delay:
                                              • Instead of calling the Restart() in the EndGame(), use Invoke and create a variable restartDelay as the following:
                                                • using UnityEngine;
                                                • using UnityEngine.SceneManagement;

                                                • public class GameManager : MonoBehaviour
                                                • {
                                                •     bool gameEnded = false;
                                                •     public float restartDelay = 3f;
                                                •     public void EndGame()
                                                •     {
                                                •         if (gameEnded == false)
                                                •         {
                                                •             Debug.Log("GAME OVER!!!");
                                                •             gameEnded = true;
                                                •             Invoke("Restart", restartDelay);
                                                •         }
                                                •     }
                                                •     void Restart ()
                                                •     {
                                                •         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
                                                •     }
                                                • }
                                          • Add Scene to the Build Settings: 
                                            •  Click File tab > Build Settings and click Add Open Scenes or drag it from the Project panel. The box contains all of the scenes we want to include when we export our game. 
                                            •  The check box show whether the scene is included and the build index on the right is used for downloading the scene.
                                        • WINNING LEVELS - How to make a Video Game in Unity (E09)
                                          •  Create a Trigger and Place it at the End of the Level:
                                            • Control-click the Hierarchy > 3D Object > Cube to create a cube and rename it to END.
                                            • Switch to the 3D mode, Reset the Transform on the Cube and hit f to focus on it.
                                            • Scale the cube to (15. 5, 5) size and position it to (0, 3, 0).
                                            • Click the y-axis and switch to isometric by clicking the center cube.
                                            • Zoom out and drag it to the end of our level. 
                                            • Disable the Mesh Renderer to make it invisible.
                                            • Select the Box in the Inspector window and Select green color to create a Label. Make sure the 3D Icon box is checked in the Gizmo tab in order to show the label.
                                            • Check Is Trigger property in the Box Collider component.
                                            • Add Script by adding a component called End Trigger (Script).
                                            • Edit the End Trigger (Script):
                                              • Delete the first two using statements and remove both Start () and Update () methods.
                                              • Add a method: void OnTriggerEnter() and call a function from GameManager called CompleteLevel().
                                              • Code:
                                                • public GameManager gameManager;

                                                • void OnTriggerEnter()
                                                • {
                                                •      gameManager.CompleteLevel();
                                                • }
                                              • Open the GameManger script and create a new method called CompleteLevel():
                                                • public void CompleteLevel ()
                                                • {
                                                •          Debug.Log ("Level Won!!!");
                                                • }
                                              • Click the End object in the Hierarchy and drag the GameManager to the empty slot of the Game Manager property of the End Trigger (Script) component.
                                              • Run it and we will see the message when reaching the end!
                                          •  Show UI to Complete the Level:
                                            • Create Text for Level Completion:
                                              • Control-click Canvas > UI > Panel to create a panel. Panel is an image that fits the entire screen.
                                              • Switch to 2D mode and hit f to focus on it.
                                              • Change the default Background Source Image to None (Sprite).
                                              • Change color to make it white and remove the transparency by bumping up the Alpha.
                                              • Rename it as LevelComplete.
                                              • Control-click on LevelComplete > UI > Text to add Text.
                                              • Scale up the Textbox and center it both the x and y.
                                              • Change font to Roboto and bump up font size to 100.
                                              • Change the text to LEVEL and rename the Text to Level.
                                              • Duplicate Level, rename it to Complete and change the text to COMPLETE.
                                              • Change the font to Roboto and shift-drag (in only one direction) it down and bump down the font size to 53.
                                              • If font size doesn't work, make sure change the Horizontal Overflow and Vertical Overflow properties of the Text to both Overflow.
                                              • Adjust their position to look nicely.
                                              • Rename the previous Text object displaying soft score to Score to eliminate confusion.
                                              • Finally, disable the LevelComplete so we won't see it at the beginning.
                                            • Modify GameManager to Show the Text:
                                              • Add a new variable: public GameObject completeLevelUI;.
                                              • In the CompleteLevel(), add a statement: completeLevelUI.SetActive(true);.
                                              • In GameManager, drag LevelComplete to the empty slot of Completer Level UI.
                                              • Run it and the UI will display once we trigger it.
                                            • Add Animation:
                                              • Select LevelComplete object and reenable it such that we can see what's happening.
                                              • Click Window tab > Animation > Animation. Animation window has timeline to allow us to animate different properties on any objects in Unity. (Animator window is to play animation and transition from animation to another.)
                                              • In the Animation window, click Create button.
                                              • In the pop up window, create a new folder called Animation and Save.
                                              • In the Animation folder in the Assets window, we can find two assets: the Animation itself and the Animation Controller.
                                              • Click the Animation and disable the Loop Time since we only need the animation to play once.
                                              • Click the Animation Controller and we can add any Animations and connect them by clicking-and-dragging among them as network to create very complicated behaviors.
                                              • Unity will automatic add our first Animation, LevelComplete, and play it as soon as our LevelComplete gets enabled. We don't have to trigger it anywhere.
                                              • Now go back to the Animation window and we can see the Record button is red since we are in recording mode. Any changes we made are going to be recorded as key frames.
                                              • For example, if we de-color the image by bumping down the Alpha after 0.5 seconds, a keyframe is created at the 0.5 second mark and at the 0 second mark. In the beginning, the Alpha is normal and then it starts fading out. It's only happening on the background.
                                              • We can reverse it by grabbing and switching the positions of the two keyframes. Now our background fads in!
                                              • We can do similar things to our two text objects and make them happen a little bit later. Now the background fads to white and then the text fads in!
                                              • Get out of Record mode by clicking the button and disable our LevelComplete object.
                                              • Now run it and the animation will automatically play! 
                                          •  Load Next Level after Few Seconds:
                                            • Zoom out the timeline by using two fingers moving up.
                                            • Click LevelComplete object and add a new script: LevelComplete.
                                              • Delete the first two using statements and remove both Start () and Update () methods.
                                              • Add a function: public void LoadNextLevel ();.
                                              • Add a using statement: using UnityEngine.SceneManagement;.
                                              • Add a statement to load new Scene to the LoadNextLevel(): SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);.
                                              • Each Scene has a Build Index associated with it. We can find the Index by clicking File tab > Build Settings to find out.
                                              • Code:
                                                • using UnityEngine;
                                                • using UnityEngine.SceneManagement;
                                                • public class LevelComplete : MonoBehaviour
                                                • {
                                                •     public void LoadNextLevel()
                                                •     {
                                                •         SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
                                                •     }
                                                • }
                                            • Pick 2 second mark and add an Event by clicking Add Event tab in the Animation window. 
                                            • Select the Animation Event > Function > LoadNextLevel(); to load next level whenever we reach this point in time.
                                            • Duplicate the Level 1 scene to create Level 2 scene. We can delete a few objects from Level 1 to make it easier.
                                            • Run it and we will see level change!
                                        • FINISHING UP - How to make a Video Game in Unity (E10)
                                          • Create Multiple Levels:
                                            • There are many ways to create multiple levels:
                                              • Duplication: Keep duplicating the first Level and going into each level to modify them. The problem of this way is that it's very hard to change settings in all the levels.
                                              • Prefab: Drag all our Player, GameManager, Main Camera, END and Canvas to the Asset window, and turn them into Prefabs. It will be easier to change something and it will change on all the levels. This way is fine for beginners' games and that's why we are going to do it here.
                                              • For larger game, we would either make some kind of editor tool that makes it easier for you to create levels, or
                                              • Have all of our level data in a separate scene that we then load on top our main scene.
                                            • Use Prefabs:
                                              • Delete Level 2 to optimize the process.
                                              • Create Prefabs: Player, GameManager, Main Camera, END and Canvas.
                                              • Create a Folder: Put all the prefabs into the Prefab folder and Save the scene.
                                              • Duplicate Levels: Duplicate Level 1 to create Level 2 and Level 3.
                                              • Modify Levels: Remove more obstacles in the lower levels.
                                          • Make a Credit Screen:
                                            • Create a Panel:
                                              • Create a new Scene by clicking File tab > New Scene.
                                              • Create a UI by control-clicking the Hierarchy and select UI > Panel to create a Panel.
                                              • Switch to 2D mode and hit f to focus on it.
                                              • Remove the Source Image and make it non-transparent and make it a little bit Gray.
                                              • Rename the Panel as Credits.
                                            • Create Three Text Objects:
                                              • On top of Credit Object, control-click and select UI > Text to create a Text and hit f to focus on it.
                                              • Resize the Textbox and change the text to "Thanks for Playing!"
                                              • Change the font size to 50 and font to Roboto.
                                              • Now if we maximize our Scene by shift-space, the Text remains the same size.
                                              • To fix this issue, select the Canvas, change the UI Scale Mode from Constant Pixel Size to Scale with Screen Size and drag the Match to fit the screen size (1).
                                              • Rename the Text as Thanks.
                                              • Control-d on the Thanks to duplicate it and change the text to "Made By".
                                              • Change the font size to 20 and font to Roboto-Medium.
                                              • Rename the Text to "Made By"
                                              • Duplicate the Thanks again and change the text to my name.
                                              • Change the font size to 50 and font to Roboto.
                                              • Rename the Text to "My Name".
                                              • Create a Button to allow user to exit the game.
                                            • Create a Button:
                                              • Control-click Credit object > UI > Button to create a Button.
                                              • Move it down and scale it up.
                                              • Delete the Source Image and keep it White.
                                              • Add a new component, Shadow. This allow us to cast a hard shadow onto the background. Select x = 0, y = -2, and then decrease the opacity.
                                              • Change the Text of the button to Quit.
                                              • Change the font size to 20 and font to Roboto.
                                              • Rearrange the Text and Button positions to look nice.
                                              • Now we are ready to hook up the button to a Script.
                                            • Create a Script:
                                              • Select Credits, add a script and call it Credits.
                                              • Whenever we want to trigger some code using a button, we need to make sure that the function we create is marked as public.
                                              • Perform basic clean up.
                                              • Make a function: public void Quit ().
                                              • Create an application in the Quit(): Application.Quit();. We won't see this happening to close down the window until we export it.
                                              • So, we add a statement: Debug.Log("QUIT!");.
                                              • Code:
                                                • using UnityEngine;
                                                • public class Credits : MonoBehaviour
                                                • {
                                                •     public void Quit()
                                                •     {
                                                •         Debug.Log("QUIT!");
                                                •         Application.Quit();
                                                •     }
                                                • }
                                              • Click the Button, add an On Click () Event by clicking the + sign.
                                              • Drag the Credits object to the empty slot of Object (None(Object)) to be notified by the clicking. 
                                              • Replace the No Function with Credits > Quit(), so each time the button been clicked, the Quit() will be executed.
                                              • Play it and each time we click the button, it will print out QUIT!.
                                              •  Save it as Credits.
                                          •  Make a Welcome Menu: 
                                            • Create the Menu:
                                              • Duplicate the Credits Scene and rename it to Menu.
                                              • Select the Menu Scene.
                                              • Change the Thanks for Playing! to Welcome To and change the Made By to Cubethon; delete My Name.
                                              • Resize the Cubethon to font size 70 and change the text color.
                                              • Rearrange the Text and Button positions to look nice.
                                              • Rename Credits object to Welcome; Thanks text to Welcome;Mad By text to Cubethon; Text of the Button to START.
                                            • Create a Script:
                                              • Click Welcome object and remove the Credits script.
                                              • Add a new script called Menu and open it.
                                              • Add a using statement: using UnityEngine.SceneManagement;.
                                              • Clean up and add a function: public void StartGame ().  
                                              • Add a statement in the public void StartGame () to activate the Level 1 scene: SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);.
                                              • Code:
                                                • using UnityEngine;
                                                • using UnityEngine.SceneManagement;
                                                • public class Menu : MonoBehaviour
                                                • {
                                                •     public void StartGame ()
                                                •     {
                                                •         SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
                                                •     }
                                                • }
                                              • Click the Button and drag the Welcome object to the empty slot of Object (None(Object)) to be notified by the clicking. 
                                              • Replace the No Function with Menu > StartGame(), so each time the button been clicked, the StartGame() will be executed.
                                            • Build Settings:
                                              • Click File > Build Settings and add all the Scenes in order: Menu, Level 1, Level 2, Level3 and Credits.
                                              • Drag the two new scripts into the Scripts folder to clean up.
                                              • Now, we are done with the game and are ready for export to different platforms!
                                              • Play it!

                                        Coordinating Multiplayer Game: Photon Bolt

                                        Documentation : Photon Bolt Documentation Photon Bolt Engine API Overview : Feature Comparison between Bolt Pro and Bolt Free: Photon Bolt R...