{"id":21377372,"url":"https://github.com/zeyu-li/unity-user-guide","last_synced_at":"2025-03-16T09:45:08.484Z","repository":{"id":120382081,"uuid":"241944371","full_name":"Zeyu-Li/unity-user-guide","owner":"Zeyu-Li","description":"A Unity User Guide that supplements the Unity Documentation, along with some tips and tricks! Is a collection of my 2D and 3D notes on Unity :video_game:","archived":false,"fork":false,"pushed_at":"2023-05-19T05:05:16.000Z","size":34388,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-22T22:09:19.480Z","etag":null,"topics":["3d-game","tutorial","unity","unity-2d","unity-3d","unity-tutorial"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Zeyu-Li.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"Zeyu-Li"}},"created_at":"2020-02-20T17:17:51.000Z","updated_at":"2023-05-19T05:05:15.000Z","dependencies_parsed_at":"2023-06-05T19:15:44.097Z","dependency_job_id":null,"html_url":"https://github.com/Zeyu-Li/unity-user-guide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zeyu-Li%2Funity-user-guide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zeyu-Li%2Funity-user-guide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zeyu-Li%2Funity-user-guide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zeyu-Li%2Funity-user-guide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Zeyu-Li","download_url":"https://codeload.github.com/Zeyu-Li/unity-user-guide/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243852432,"owners_count":20358270,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d-game","tutorial","unity","unity-2d","unity-3d","unity-tutorial"],"created_at":"2024-11-22T09:20:30.045Z","updated_at":"2025-03-16T09:45:08.444Z","avatar_url":"https://github.com/Zeyu-Li.png","language":null,"readme":"# Unity User Guide\n\n## About\n\nThis is a combination of the [2D](https://github.com/Zeyu-Li/Unity-Tutorial-2D) and [3D](https://github.com/Zeyu-Li/Unity-Tutorial-3D) tutorial repos. I will go through 2D and 3D games along with general tips and tricks for solo and team-based projects. Without future ado, let's begin! \n\n\u003ca name=\"top\"\u003e\u003c/a\u003e\n\n## Index\n\n1. [Installation](#install)\n2. [General](#main)\n3. [Unity Editor Overview](#unity)\n4. [2D](#2D)\n   1. [General](#2dg)\n   2. [Sprites](#spr)\n   3. [Movement](#move)\n   4. [Camera](#camera)\n      * [Background](#background)\n      * [Camera Follow](#camera_follow)\n   5. [Prefabs](#pref)\n   6. [Particle System](#partsys)\n   7. [Collectibles](#coll)\n   8. [Animation](#anim)\n   9. [Events](#events)\n   10. [Pixelated](#pix)\n   11. [Music \u0026 Sounds](#music)\n   12. [Parallax](#par)\n   13. [Odds and Ends](#odds)\n       * [Linking Scenes](#linked_scenes)\n       * [Death Zone](#death_zone)\n       * [Enemies](#enemies)\n       * [Pausing](#pausing)\n       * [Quiting](#quit)\n   14. [End Note](#end2d)\n       * [End Product](#finished) (Demo)\n5. [3D](#3D)\n   1. [General](#5a)\n   2. [3D Models \u0026 Bodies](#5b)\n       * [Resources](#m_res)\n       * [Software](#software)\n       * [Libraries](#libraries)\n       * [Unity](#m_unity)\n   3. [Movement](#5c)\n   4. [Camera](#5d)\n   5. [Lighting](#light)\n   6. [Prefabs](#5f)\n   7. [Particle Systems](#5g)\n   8. [Animation](#3anim)\n   9. [Collectibles](#3coll)\n   10. [Events](#3events)\n   11. [Music \u0026 Sounds](#3music)\n   12. [Odds and Ends](#3odds)\n       * [Pausing](#3_pausing)\n       * [Quiting](#3_exit)\n   13. [Demo](#3demo)\n6. [Title Screen](#3_title)\n7. [Scripting](#script)\n8. [Building](#build)\n9. [Cloning Guide](#guide)\n10. [Collaboration](#team)\n    * [Unity's Collab](#unity) (recommended)\n    * [GitHub](#git)\n11. [Resources](#help)\n\n\u003ca name=\"install\"\u003e\u003c/a\u003e\n\n### 1. Installation\n\nBefore installing, note that Unity is **completely free**, if you or your company makes less than $100 000 (USD). \n\nFollow the link [here](https://store.unity.com/download) and download the free installer (the plus version is definitely not necessary). Follow the instructions and download the installer. The Unity installer is simple and easy to use nevertheless, this [video](https://www.youtube.com/watch?v=KMuMhA6Lk0I) for Windows is a tutorial in installing it. Also note that you may need a Unity account or just use your Google/Facebook account to sign in. \n\nIf you want a new version of Unity, go to the Unity Hub and click the **Installs** tab on the left and **ADD** (top right) the desired version (it is recommended that you pick a version with **long term support** or LTS); however do be warned that this tutorial was made in **2019.3** so in newer versions, things might have moved places or removed entirely 😞. Afterwards, the installation will take quite a while, even with a fast internet connection. \n\nWhen installing Unity, it might ask you to install **Visual Studio** along-side Unity. If you have Visual Studio, do not install again, it should automatically detect the current VS on the system. Otherwise, it is optional and MonoDevelop (comes with Unity) is good enough for handling coding in Unity. \n\n\n\n\u003ca name=\"main\"\u003e\u003c/a\u003e\n\n### 2. General\n\n**Unity** is a 3D game engine built in **C#** but can be used for 2D. Before you freak out about programming, let me assure you, it is quite trivial. If you have programmed before, especially in C++, it is a huge plus. If you have not, don't worry, it's just a bunch of copy and pasting. The most important thing is don't be frustrated and \n\n```c#\nDebug.Log() // logs to Unity console\n```\n\nis your friend. \n\nBeing organized in Unity is a must, especially for big projects. Have organized folder will help a ton, in addition, using empties as folders within the scene is *+1 organization*. \n\n\u003ca name=\"unity\"\u003e\u003c/a\u003e\n\n### 3. Unity Editor Overview\n\nUnity is a panel based application. These panels can be rearranged however you like and saved as default. \n\n![layout](images/layout.png)\n\nThis is my default setup. The **Scene** panel is the most important viewport. This is where you modify the scene. The **Game** scene only turns on if you hit play. It is a preview of what the user will see if you build the current scene.\n\nOn the right hand side, we have the **Project** directory (folder) panel on the bottom. This is where all your assets are (ie art, music, scripts). The **Hierarchy** is like a layers panel in Photoshop. It is an arrangement of all elements in the scene. For every element of the scene can be hidden from the view by hitting the eye button when hovering on the element. The lock button is the pointer icon. The **Inspector** contains all modifiable aspects of an element along with info. This is where you drag scripts in the element.\n\nOther panels include a console, which will output when the game is run. The **Animator** and **Animation** go hand in hand and creates animation for sprites. \n\n\n\n\u003ca name=\"2D\"\u003e\u003c/a\u003e\n\n## 4. 2D\n\n\u003ca name=\"2dg\"\u003e\u003c/a\u003e\n\n### \t4a General\n\nSo you've decided to make a 2D game. Great! Who needs modelling and lighting anyways? \n\n2D games are secretly 3D, what does that mean? Think of Unity 2D as a bunch of layers like in Photoshop, Gimp, After Effects, or Illustrator. The closest to the camera is picked up first and blocks the ones behind it. As a 2D world, lighting is global (unless you want to enable an experimental local lighting feature). To start a new 2D game, click **New** and select 2D on the pop-up screen and use the desired directory (or follow my cloning [guide](#guide) so to not start from starch). This may take some time, but after Unity finishes installing itself, we can get started. Now let's make a player and make it move!\n\n*Note, part of the tutorial (2D) follows this repo: [Unity-Tutorial-2D](https://github.com/Zeyu-Li/Unity-Tutorial-2D)\n\n\n\n\u003ca name=\"spr\"\u003e\u003c/a\u003e\n\n### \t4b Sprites\n\nSprites are what make up the visuals of the game. These could be png or jpeg (recommended because of small size) file. You can make your own and drag them into an **Artworks folder**.\n\nIf you have multiple sprites on a picture file, you have what is called a **sprite sheet**. These could be useful because it saves space. Unity comes with a sprite editor that can cut the sprite sheet into multiple sprites. \n\nHowever, before we get to that, let us take a look at the Sprite setting\n\n![sprites](images/sprites.png)\n\nFrom the top header, we can see some info on the item\n\nFrom the header we also see:\n\n* Texture Type - Usually will only use sprite (2D image) or normal map (for 3D depth)\n* Sprite mode - as single texture or sprite sheet\n  * Adjust the pixels per unit (Pixels per unit should be 1-1) (In my case, it is 358 px per tile)\n  * Pivot - where the center of object is\n* Wrap Mode - how the image is displayed (ie repeated or clamped(/cut) at the board)\n* Filter Mode - Point (equivalent to pixel perfect or nearest neighbour in Photoshop) or Bilinear (natural scaling with edge softening)\n* Format - Format of image (8bit, 16 bit, 32 bit colour with or without alpha)\n\n\\* Note, if a setting was not mentioned, it is not that important at the beginner level.\n\n**Multiple Sprites**\n\n1. Select Multiple in **Sprite Mode**\n2. Click **Spirit Editor** button\n   ![spriteEditor](images/spriteEditor.png)\n3. In sprite editor, click Slice -\u003e Slice (This is an automatic slicer and is usually good enough, if not, manually move the transform bound boxes to fit or define split at distance apart (must change to **Grid by Size Count**, not **Automatic**) with the size of tile in **Pixel Size**.\n4. Click apply\n5. Close window or drag to some widget\n6. You can inspect every tile by expanding the original image and a bunch of tiles with name pictureName_0 to # of tiles with be a child of it\n\nNow, with a sprite, you can drag it into the scene\n\nTo create a tile map, follow the steps below:\n\n1. GameObject -\u003e 2D Object -\u003e Tile Map\n2. Open Tile Palette, by going to Window -\u003e 2D -\u003e Tile Palette\n3. Create New Palette and save it\n4. Drag all individual tiles into widget or drag parent spritesheet (and save)\n\nNow with the tile palette, you can draw on the scene, reorganize everything and many other things\n\n![tilePalette](images/tilePalette.png)\n\nFrom the top, there are many icons, we will go through each of them,\n\n* Curser - selects tiles from scene\n* Move - Moves tiles in palette (Only if you click **Edit**)\n* Brush - paints on scene\n* Square/Rect - Selects multiple tiles or one to paint from\n* Eye dropper - Selects tile from scene\n* Eraser - Erases\n* Paint Bucket - Floods with active brush (Like Photoshop)\n\nTo layer tiles:\n\n* Right click on the tile map -\u003e 2D -\u003e Tilemap for however many more layers you need\n\nTo set a layer as a solid with collision:\n\n1. go to the layer you want to make solid\n2. Add Component -\u003e search add Tilemap Collider 2D\n\nResources: [Brackeys](https://www.youtube.com/watch?v=ryISV_nH8qw)\n\n\n\n\u003ca name=\"move\"\u003e\u003c/a\u003e\n\n### 4c Movement\n\nMovement is critical in all games, whether the movement is limited to left or right, or games that are in 3D. On the internet there are many sources that claim the perfect jump, but only you can decide that based on what type of gameplay you want. \n\nTo start off with, set your player to be a rigid body with colliders:\n\n1. Select the player and add a Rigidbody 2D\n\n   ![rigid](../_games/Unity-Template-2D-2019_3/images/rigid.png)\n\n2. Open up the Rigidbody 2D and go to constraints. If you want the player to not rotate in 2D, then select **Freeze Rotation Z**\n\n3. Otherwise, add a **Collider 2D** to fit the player. Depending on how your player's form, different shapes may be better. Try the different collider options to see which ones fit best. Most of the time, a **Box Collider 2D** will work just fine. Also note that you can use multiple colliders, but remember, this is computationally more expensive.\n\n4. Also note that if you are not satisfied with Unity's default collider size, you can change the size by changing the **size** attribute\n\nNow for the movement:\n\n1. make a new folder called **scripts**\n2. right click -\u003e Create -\u003e C# Script -\u003e call it **movement** (although you can pick any name you want, this is standard)\n\nNext, you want to open the script by double clicking on it\n\nThis will either open the script in MonoDevelop or Visual Studio (to find out more about scripting, go to the [scripting section](#script))\n\nIn the movement class, put\n\n```c#\n// inits\n// horizontal speed\npublic float speed = 10f;\n\n// vertical jump\npublic float jumpForce = 10f;\n\n// different jump heights for how long jump button is pressed\n// change it as you change gravity\npublic float jumpCheck = .2f;\n// is ground check\npublic float checkRadius = 0.3f;\n\n// ground jump check\npublic bool isGrounded;\npublic Transform feetPos;\npublic LayerMask whatIsGround;\n\n// so that infin jumps are not a thing\nprivate float jumpCheckCounter;\nprivate bool jumping;\nprivate float moveInput;\n\n// inits rigid body\nprivate Rigidbody2D rb;\n\nvoid Start() {\n    rb = GetComponent\u003cRigidbody2D\u003e();\n}\n\nvoid Update() {\n\n    // bool to see if overlap of floor layer and feet object\n    isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);\n\n    // if is touching ground and jump button pressed, add jump force\n    if (Input.GetButtonDown(\"Jump\") \u0026\u0026 isGrounded == true) {\n        jumping = true;\n        jumpCheckCounter = jumpCheck;\n        rb.velocity = Vector2.up * jumpForce;\n    }\n\n    if (Input.GetButton(\"Jump\") \u0026\u0026 jumping == true) {\n        // can jump only once\n        if (jumpCheckCounter \u003e 0) {\n            Debug.Log(jumpCheckCounter);\n            rb.velocity = Vector2.up * jumpForce;\n            jumpCheckCounter -= Time.deltaTime;\n        }\n\n    }\n    else {\n        // once jumping is not true, set jump to false\n        jumping = false;\n    }\n\n    if (Input.GetButtonUp(\"Jump\")) {\n        jumping = false;\n    }\n\n    // flips player\n    if (moveInput \u003e 0) {\n        transform.eulerAngles = new Vector3(0, 0, 0);\n    }\n    else if (moveInput \u003c 0) {\n        transform.eulerAngles = new Vector3(0, 180, 0);\n    }\n}\nvoid FixedUpdate() {\n    // gets horizontal input from Unity (1 = right, -1 = left)\n    moveInput = Input.GetAxisRaw(\"Horizontal\");\n    rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);\n}\n```\n\nSave and exit. Now, when you click on the player, movement script, there will be options for you to tinker with. \n\nFinally for jumping you need to:\n\n1. Set ground layer to ground objects that can be jumped on\n2. Make a isGrounded empty object to be placed at the feet of the player to check if there is **ground layer **beneath the player to jump off of\n\n\\* Note that this script has a jump that can be a multitude of heights depending on how long the jump button is held down for.\n\nAlso, for the player to not stick to the walls while jumping, you must:\n\n1. Add a new physics material 2D\n2. Change friction to 0 and bounciness to whatever you want it to be \n3. Apply to player in the collider\n\nResource: https://www.youtube.com/watch?v=j111eKN8sJw\n\n\n\n\u003ca name=\"camera\"\u003e\u003c/a\u003e\n\n### \t4d Camera\n\n1. The camera will capture things from the scene to project onto the play window. \n\n   The most important setting for a camera object is the size. Changing the size will change the view for the user. \n\n   \u003ca name=\"background\"\u003e\u003c/a\u003e\n\n   #### Background\n\n   A background can be achieved by placed in the camera and setting the **Order in Layer** to some negative number, such that it is behind the foreground objects\n\n   \u003ca name=\"camera_follow\"\u003e\u003c/a\u003e\n\n   #### Camera Follow\n\n   When implementing a camera, there are two options, however, we will through the harder option first to get use to how cameras work\n\n   1. We will create a camera follow script with the following:\n\n   ```c#\n   // selects target to be fixed on\n   public Transform target;\n   public float smoothing = 0.12f;\n   \n   // because it is fixed to player, we want to move in from by 10 layers be default\n   public Vector3 offset = new Vector3(0f,0f,-10f);\n   \n   void FixedUpdate() {\n       Vector3 desiredP = target.position + offset;\n   \n       // interpolate movement\n       Vector3 smoothP = Vector3.Lerp(transform.position, desiredP, smoothing);\n       transform.position = smoothP;\n   \n       // will move in direction of target\n       // comment out if you don't like the jitters\n       transform.LookAt(target);\n   }\n   ```\n\n   You will have to drag the player to target and change the smoothing value if you like more or less smoothing\n\n   \n\n   **OR**\n\n   \n\n2. Use the [Cinemachine Extension](https://assetstore.unity.com/packages/essentials/cinemachine-79898) \n\nTo use Cinemachine, one must first install the extension as it does not come in with Unity natively. To do this, \n\n1. window -\u003e Package Manager -\u003e **Search: **Cinemachine -\u003e click install\n\nNow to use it:\n\n1. Cinemachine -\u003e Create 2D Camera\n2. Embed CM vcam into main camera (optional)\n3. Go to CM vcam and put the player in the **Follow** \n4. Try it out\n5. If you want the character directly in the center of the camera, turn down all **damping** and **dead zone** to 0 (these settings are in **Body**)\n6. **Screen** x and y, offsets from center\n7. **Soft zone** changes the max distance from center before snapping the player to edge\n8. **Dead zone** is how far you can move the character before the camera moves along-side the player\n9. **Damping** is the smoothness of the camera movements\n10. **Look ahead** is the direction the player is moving towards\n11. Play around with these setting\n\nResource: https://www.youtube.com/watch?v=MFQhpwc6cKE or https://www.youtube.com/watch?v=2jTY11Am0Ig\n\n\n\n\u003ca name=\"pref\"\u003e\u003c/a\u003e\n\n### \t4e Prefab\n\nA prefab is simply a clone that can be dragged to the scene\n\nThis means that things from other scenes can be reused\n\nTo make a prefab, just drag the desired prefab object from scene to the prefabs folder\n\n\n\n\u003ca name=\"partsys\"\u003e\u003c/a\u003e\n\n### \t4f Particle System\n\nA particle system adds an extra layer of immersion that is quite simple in Unity. \n\nTo add a particle system:\n\n1. Right click hierarchy -\u003e Effects -\u003e Particle System\n2. Remember, default is some circled with soft edges\n3. To make custom particles,\n   1. Go to photo editor of chose (Adobe Photoshop, illustrator, or GIMP work great)\n   2. Make your single particle or collection of particles\n   3. Save\n4. To use the custom particles, go to renderer -\u003e material -\u003e sprite default\n5. Now enable **Texture Sheet Animation**\n6. Mode -\u003e ~~Grid~~ -\u003e sprites\n7. Select objects\n\nThere are near infinite options in the inspector for particle systems. Most options are self explanatory. Some of the most common options to change are:\n\n* Loop - for ambient particles that need to on screen all the time\n\n* Start Color Options\n  * Random Color -\u003e randomly selects a color\n  * Gradient -\u003e flows from one color to the next\n  * Random between two colors/gradients -\u003e randomly picks a color in gradient or one of the two colors\n* Prewarm - already has some particles and does not start with no particles\n* Start Speed - Speed of particles\n* Start Lifetime - how long the particle lives in the scene\n* Start Size - size of particle\n* Emission -\u003e Rate over Time - how many particles spawn over time\n* Rotation over Lifetime -\u003e rotates over time\n* Collision -\u003e collides with solid objects\n* Trail -\u003e creates trails of particle as it moves\n* Color over Lifetime -\u003e you can fade the particles in and out\n* Shape -\u003e Randomize Direction - changes starting velocity vector\n* Shape -\u003e Spherize Direction - Moves out from center\n\n\\* Note for some options like start speed, lifetime, size, etc, you can pick from an interval\n\nIf there is some setting I haven't mentioned but look interesting, refer to the Unity docs. To test particles, use the Particle Effects window. This will control preview\n\n![partE](images/partE.png)\n\n\n\n\u003ca name=\"coll\"\u003e\u003c/a\u003e\n\n### 4g Collectibles\n\nThere are two parts to a collectible: \n\n1. The collection of the item\n2. The storage of the item in inventory\n\nWe will start with 1. the collection of an item\n\n1. Find a sprite or animation to use as collectable. For simplicity, I will use a sprite like this:\n\n   \u003cimg src=\"images/gem.png\" alt=\"gem\" style=\"zoom:33%;\" /\u003e\n2. Drag gem into level\n3. Add collider (I think box collider works best here) and check **Is Trigger**\n4. Add a new tag and select it of the gem\n\n   ![tag](images/tag.png)\n5. Within the player movement, we need to detect the collision overlaps and if an element of the tag overlaps the player, destroy object\n   This is done by putting the following code somewhere in the player movement class (not in an update or start method)\n\n   ```c#\n   private void OnTriggerEnter2D(Collider2D collision) {\n       if (collision.gameObject.CompareTag(\"gems\")) {\n           Destroy(collision.gameObject);\n       }\n   }\n   ```\n6. (Optional) If you want to reuse the gem, drag in Prefab folder\nNow we must consider the storage of the item in inventory. Note this can be as easy as a counter or a full fledged inventory\n\nI will do a counter for simplicity:\n\n\\* Note while we are adding a counter, it is also a convenient time to add a sound of collecting the item. \n\n1. Resources for audio clip: [here](https://docs.unity3d.com/ScriptReference/AudioSource.Play.html) \u0026 [here](https://docs.unity3d.com/ScriptReference/AudioSource-clip.html) but I used [PlayOneShot](https://docs.unity3d.com/ScriptReference/AudioSource.PlayOneShot.html) \n2. Optionally, a collecting animation or particles could also be implemented\n3. However, we will jump directly to a collectables counter\n   1. Create a text layer by clicking UI -\u003e Text - TextMeshPro\n   2. Click on canvas -\u003e Render Mode -\u003e Screen Space - Camera\n   3. Assign Render Camera to current Main camera\n   4. Change layering order on canvas so it is in front\n   5. Position it right. You may also chose to have a image accompanying the counter\n   6. Create a collectablesManager script with the following:\n      ```c#\n      using System.Collections;\n      using System.Collections.Generic;\n      using UnityEngine;\n      using TMPro;\n      \n      public class collectablesManager : MonoBehaviour\n      {\n          public static collectablesManager instance;\n          public TextMeshProUGUI text;\n          public int score = 0;\n          // Start is called before the first frame update\n          void Start()\n          {\n              if (instance==null) {\n                  instance = this;\n              }\n          }\n      \n          // Update is called once per frame\n          public void changeScore(int gemValue) {\n              score += gemValue;\n              text.text = \"x\" + score.ToString();\n          }\n      }\n      ```\n   7. Create empty to house the collectablesManager script and drag the script in\n   8. Drag the text score into the Text field\n   9. Now gems script and populate with the following: \n      ```c#\n      using System.Collections;\n      using System.Collections.Generic;\n      using UnityEngine;\n      \n      public class gems : MonoBehaviour\n      {\n          // Start is called before the first frame update\n          public int value = 1;\n          private void OnTriggerEnter2D(Collider2D collision) {\n              if (collision.gameObject.CompareTag(\"Player\")) {\n                  collectablesManager.instance.changeScore(value);\n              }\n          }\n      }\n      ```\n\n      *Note by using this, you must have one collider with the player tag or the collectable might count twice. Optionally, you can make a new empty game object with the player tag than triggers the collection\n\n\nResource: https://www.youtube.com/watch?v=DZ-3g31jk90\n\n\n\n\u003ca name=\"anim\"\u003e\u003c/a\u003e\n\n### 4h Animation\n\nAnimation is critical in creating any game that does not look static. In Unity, animation is handled by Animator and Animation windows. The **Animator** is a node based system while the **Animations** is a timeline based.\n\nTo make an animation, simply:\n\n1. Drag more than 1 picture into the scene\n2. Save your animations in the animations folder\n\nYou have made your first animation\n\nTo adjust your animation, go to the animator window and clip on the orange node.\n\nYou can change the speed here\n\nTo add different actions connected to the original animation:\n\n    1. Go to the Animations window when the original animation is selected\n    2. Click on animation dropdown -\u003e Create New Clip...\n    \n     ![animation](images/animation.png)\n  3. Save the new animation\n  4. It is recommended that you change the sample frame to the original animation's sample frame\n  5. Drag all the new set of pictures to the timeline in the **Animations** window\n  6. To change the pictures per second, drag the blue bar (all frames must be selected ie in blue)\n  7. Now to move from any one animation (or state as it is called), go to the **Animator** window\n  8. Right click on the **Any State** node -\u003e Make Transition\n\n     ![states](images/states.png)\n  9. We will link the idle animation to the other transitions, therefore, after selecting make transition, click on idle and this will connect any state to idle\n  10. Also make transition to walk (or any other animation) from any state\n  11. To link these states up, go to **Parameters** tab in the Animator window and click **+** -\u003e int\n  12. Name it\n  13. Select transition Any State to idle\n  14. in the inspector, expand Settings and\n      1. Uncheck **Fixed Duration** if you want no transition duration\n      2. **Change Transition** Duration to 0\n      3. Uncheck can transition to self\n      4. In Conditions, click **+**\n      5. Set it equal to 0\n      6. Do the same thing for **Any State** to any other animation to the same parameter except change step 5 to equal to some other number\n  15. Now to connect the animations with the code so it changes with the actions performed by the player\n  16. Go to the player movement script\n  17. Add the following:\n      ```c#\n      private Animator animator; //attribute in class\n      \n      // add the following in Start\n      void Start() {\n          animator = GetComponent\u003cAnimator\u003e();\n      }\n      \n      // add the following in FixedUpdate\n      void FixedUpdate() {\n          // if moving, then idle, else set to moving animation\n          if (moveInput != 0) {\n              animator.SetInteger(\"AnimValue\", 1);\n          } else {\n              animator.SetInteger(\"AnimValue\", 0);\n          }\n      }\n      ```\n      \\* Note if you don't want the animation to loop, go to the animation in where you saved your animation and uncheck **Loop Time**\n\n\u003ca name=\"events\"\u003e\u003c/a\u003e\n\n### 4i Events\n\nEvents add much needed interactions into a game, but keep in mind that every event requires a lot of work. With this in mind, let's implement a button that triggers a platform. \n\n  1. Have a button and platform object ready. If not, feel free to use the ones below\n\n     \u003cimg src=\"images/button.png\" alt=\"button\" style=\"zoom:50%;\" /\u003e\u003cimg src=\"images/pressedButton.png\" alt=\"pressedButton\" style=\"zoom:50%;\" /\u003e\u003cimg src=\"images/platform.png\" alt=\"platform\" style=\"zoom:70%;\" /\u003e\n  2. If you want, drag the two buttons as an animation so you can change the sprites when touched, but I will not go through the animations\n  3. Add a button tag onto the button\n  4. Create a button script and paste the following into the script\n     ```c#\n     using System.Collections;\n     using System.Collections.Generic;\n     using UnityEngine;\n     \n     public class button : MonoBehaviour\n     {\n         // renderer and timer\n         public GameObject somePlatform;\n     \n         // change button state\n         private Animator animator;\n     \n         // audio    \n         public AudioSource audioSource;\n         public AudioClip clip;\n         public float volume = 0.2f;\n     \n         // timer for how long the platform stays\n         private bool timerOn = false;\n         public float timeLeft = 8.0f;\n     \n         private void Start() {\n             animator = GetComponent\u003cAnimator\u003e();\n         }\n     \n         private void FixedUpdate() {\n             // when pressed, wait for timer to go down, then revert\n             if (timerOn) {\n                 timeLeft -= Time.deltaTime;\n                 if (timeLeft \u003c 0) {\n                     animator.SetInteger(\"button\", 0);\n                     somePlatform.SetActive(false);\n                     timerOn = false;\n                     timeLeft = 8.0f;\n                 }\n             }\n         }\n     \n         // Start is called before the first frame update\n         private void OnTriggerEnter2D(Collider2D collision) {\n             // when collision with obj with player tag, set button to pressed down,\n             // play tone, set platform active and activate timer to turn the things back to normal\n             if (collision.gameObject.CompareTag(\"Player\")) {\n                 animator.SetInteger(\"button\", 1);\n                 audioSource.PlayOneShot(clip, volume);\n                 somePlatform.SetActive(true);\n                 timerOn = true;\n                 timeLeft = 8.0f;\n             }\n         }\n     }\n     ```\n  5. Click on script, drag audio stuff or remove all audio parts from script and set the object to **Some Platform**, also set the timer for when it reverts back to normal (auto is 8 seconds)\n\nAs you can see, using what we already know, we can get a lot of events to work! I know this may be challenging and you may run into bugs (hell, even I ran in many bugs), but persistent and challenge yourself and good luck!\n\n\n\n\u003ca name=\"pix\"\u003e\u003c/a\u003e\n\n### 4j Pixelated\n\nPerhaps you want your game to have a pixelated feel, thankfully, it is not too much work to do that with Unity. \n\n**General rules and tips**\n\nSome extensions (especially with cameras) have options to enable **pixel perfect**. Whenever presented with that option, select it.\n\nOtherwise when importing your pixel artwork or spritesheet; \n\n\\* If you need pixel art to practice this section, take this:\n\n\u003cimg src=\"images/heartPerson.png\" alt=\"heartPerson\" style=\"zoom:100%;\" /\u003e\n\nClick on Filter Mode -\u003e Point (no filter)\n\n![pixel](images/pixel.png)\n\nThe point mode is like a nearest neighbour in Photoshop. This way, if you scale it, you will get the pixels to snap sharply. \n\nYou may also change the pixels per unit to your desired size. \n\n\n\n\u003ca name=\"music\"\u003e\u003c/a\u003e\n\n### 4k Music \u0026 Sounds\n\nMusic is curial to a game's level of emersion. While I will not go into music theory and music in general, I will help you get familiar with how Unity handles sounds. This is something Unity does really well, so not much can be said in the chapter. \n\nIf you need music to practice with, use main.wav in the **test_music** directory. Also note that this music is made by me and I give you permission to use it under creative commons license \n\n\u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\"\u003e\u003cimg alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by/4.0/88x31.png\" /\u003e\u003c/a\u003e\n\nThis work is licensed under a \u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\"\u003eCreative Commons Attribution 4.0 International License\u003c/a\u003e.\n\nFirst, when dealing with sound, not much should be changed and when playing a sound, in the script that triggers the sound, just put the following in\n\n  ```c#\n  // audio    \n  public AudioSource audioSource;\n  public AudioClip clip;\n  public float volume = 0.2f; // volume\n  \n  // to play sound\n  audioSource.PlayOneShot(clip, volume);\n  ```\n\nThe 3 options are\n\n  1. AudioSource - where the sound is omitted from\n  2. AudioClip - the audio file\n  3. volume - the volume of the clip\n\nFor music, it is recommended that a **Audio Source** object is created and a script added to control the music and when to stop it\n\nOtherwise, if starting and stopping the music is not a concern, just drag the music clip into the Audio Clip box and you are done\n\n![music](images/music.png)\n\n![music2](images/music2.png)\n\nBelow are some more options. Some important ones are the \n\n  1. Play on Awake - plays when scene is loaded \n  2. loop - loops track\n  3. Volume - volume of track\n  4. Pitch - shifts pitch (not recommended)\n\n\n\n\u003ca name=\"par\"\u003e\u003c/a\u003e\n\n### 4l Parallax\n\nParallax is a popular way of displaying movement, especially if the game is a bit static.\n\nWhat parallax does is like a old film reel, but instead of new frames, it is a repeat of the old frame(s).\n\n  1. Within the main camera, drag in your parallax object (I will be using clouds) \n  2. Clone/ copy and paste another version of the parallax object and set it just right and left of the original object if you want it to go right to left. Note the theses should be a child of the original object\n  3. Create new parallax script and put this in it:\n     ```c#\n     using System.Collections;\n     using System.Collections.Generic;\n     using UnityEngine;\n     \n     public class parallax : MonoBehaviour\n     {\n         private float length;\n         private float startpos;\n     \n         public GameObject cam;\n         public float parallex;\n     \n         // Start is called before the first frame update\n         void Start()\n         {\n             // if you want to do it by the y, just change x to y\n             startpos = transform.position.x;\n     \n             length = GetComponent\u003cSpriteRenderer\u003e().bounds.size.x;\n         }\n     \n         // Update is called once per frame\n         void Update()\n         {\n             float dis = cam.transform.position.x * parallex;\n             float tmp = cam.transform.position.x * (1-parallex);\n     \n             transform.position = new Vector3(startpos + dis, transform.position.y, transform.position.z);\n     \n             if (tmp \u003e startpos+length) {\n                 startpos += length;\n             } else if (tmp \u003c startpos - length) {\n                 startpos -= length;\n             }\n         }\n     }\n     ```\n  4. Drag the script on the original parallax object\n  5. Drag the main camera in the camera slot and play with the parallax number (between 1 to 0) to see how much parallax you want\n\nResource: https://www.youtube.com/watch?v=zit45k6CUMk\n\n\n\n\u003ca name=\"odds\"\u003e\u003c/a\u003e\n\n### 4m Odds and Ends\n\nFor changing controls, go to Project Settings -\u003e Input Manager and you can change your input from there\n\n\u003ca name=\"linked_scenes\"\u003e\u003c/a\u003e\n\n#### Linking Scenes\n\nLinking scenes is quite easy and just requires knowledge of the following:\n\n  1. When moving to another scene (this will usually involve a detection collider), simply put\n  ```c#\n  using UnityEngine.SceneManagement;\n  \n  // and this to load a new or the same scene\n  \n  SceneManager.LoadScene('#scene name here');\n  \n  ```\n\n  \n\n\u003ca name=\"death_zone\"\u003e\u003c/a\u003e\n\n#### Death Zones\n\nFor this exercise, I will create a death zone if the player is out of bounds, however, this could easily be modified such that they are spikes. \n\n  1. Create an empty object to house the colliders for out of bounds\n  2. Make the colliders are a series of sprites or a tile map. As long as a collider can be set to it such that Unity can detect when the Player's colliders collide with the out of bounds colliders, it is fine\n  3. Create a new tag. I will call it **death**\n  4. Create script **death** and paste in the following\n     ```c#\n     using System.Collections;\n     using System.Collections.Generic;\n     using UnityEngine;\n     using UnityEngine.SceneManagement;\n     \n     public class death : MonoBehaviour\n     {\n         // collides with object tagged death\n         private void OnTriggerEnter2D(Collider2D collision) {\n             if (collision.gameObject.tag == \"death\") {\n                 Die();\n             }\n         }\n     \n         // kills player and resets\n         void Die() {\n             Destroy(transform.parent.gameObject);\n             SceneManager.LoadScene(SceneManager.GetActiveScene().name);\n         }\n     }\n     ```\n     \\* Optionally, you can just add this to the movement player script\n  5. Drag to player collider\n\n\n\n\u003ca name=\"enemies\"\u003e\u003c/a\u003e\n\n#### Enemies\n\nEnemies are an important yet complicated thing. They can be static, or mobile. Have easy or tough AI, or creates projectiles. For this example I will do medium-easy example of a creature in a box moving back and forth\n\n  1. Drag Sprite or Animation in the scene\n  2. New creatureMove script and paste in the following\n     ```c#\n     using System.Collections;\n     using System.Collections.Generic;\n     using UnityEngine;\n     \n     public class creatureMove : MonoBehaviour\n     {\n         // speed of creature\n         public float speed = 5f;\n         public bool smartTurn = true;\n     \n         // wall detection\n         public Transform start, end;\n     \n         public bool collision;\n     \n         private Rigidbody2D body;\n     \n         // Start is called before the first frame update\n         void Start()\n         {\n             body = GetComponent \u003cRigidbody2D\u003e();\n         }\n     \n         // Update is called once per frame\n         void Update()\n         {\n             collision = Physics2D.Linecast(start.position, end.position, 1 \u003c\u003c LayerMask.NameToLayer(\"Ground\"));\n     \n             if (collision == smartTurn) {\n                 transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, 1);\n             }\n     \n             body.velocity = new Vector2(transform.localScale.x, 0) * speed;\n     \n         }\n     }\n     ```\n  3. Drag script to creature\n  4. Create an empty object as a child of the creature\n  5. To see the empty object that will act as a wall detector, press the cube icon and click on a large tag\n\n     ![detector](images/detector.png)\n  6. Place empty object in front of the creature such that if that empty interacts a wall, the creature will turn\n  7. Drag the creature itself into the creature box and the empty in the wall box\n  8. Change speed to desired amount and check **Smart Turn** to make the creature turn instead of falling off a ledge\n  9. If you want the creature to not walk off the edge, also clone the empty object and put it below the feet of the player so it is always touching the ground. Once it is not touching the ground, it should turn around\n\n\n\n\u003ca name=\"pausing\"\u003e\u003c/a\u003e\n\n#### Pausing\n\nPausing with Unity can be made simple with one command. \n\n  1. Create script pause and drag it on your player (optionally, you can just do this in the movement folder, but this will be more organized)\n  2. Create a pause UI element (I will be doing a simple Pause text)\n  3. Paste in the following:\n\n     ```c#\n     using System.Collections;\n     using System.Collections.Generic;\n     using UnityEngine;\n     \n     public class pause : MonoBehaviour\n     {\n         public static bool paused = false;\n     \n         public GameObject pauseMenu;\n     \n         // Update is called once per frame\n         void Update()\n         {\n             if (Input.GetKeyDown(KeyCode.P)) {\n                 Pause();\n             }\n         }\n     \n         void Pause() {\n             if (!paused) {\n                 pauseMenu.SetActive(true);\n                 Time.timeScale = 0f;\n             } else {\n                 pauseMenu.SetActive(false);\n                 Time.timeScale = 1f;\n             }\n             paused = !paused;\n         }\n     }\n     ```\n  4. Place the UI element in the Pause menu box\n\nResource: https://www.youtube.com/watch?v=JivuXdrIHK0\n\n\n\n\u003ca name=\"quit\"\u003e\u003c/a\u003e\n\n#### Quit\n\nTo quit game simply add the following onto the player:\n\n  ```c#\n  if (Input.GetKey(\"escape\")) // change escape to any other character if you like \n  {\n      Application.Quit();\n  }\n  ```\n\nin the update method\n\n\\* Note, of course more logic could be added to make this more complicated\n\n\n\n\u003ca name=\"end2d\"\u003e\u003c/a\u003e\n\n### 4n End Note\n\nI hope you had a good taste of Unity 2D. Of course, this was just a very brief introduction and there are many more aspects of Unity not covered; ie UI buttons. You can go to my Unity 3D course below if you want to learn more, or start creating your 2D game. There are many more resources online for you to check out if you need help, or want inspiration. These resources can be found in [section 11](#Help) and thank you for joining me with this course. If you have any feedback, feel free to go to the [GitHub](https://github.com/Zeyu-Li/Unity-Tutorial-2D/discussions) and open a discussion. Again, thanks for viewing and good luck to your future Unity endeavors. \n\n\n\n\u003ca name=\"finished\"\u003e\u003c/a\u003e\n\n#### End Product\n\n![game](demos/game.gif)\n\nIf you want to play it yourself (On windows, sorry Unix users 😜 need to build from source yourself):\n\n1. Go to the releases on the GitHub or https://github.com/Zeyu-Li/Unity-Tutorial-2D/releases/tag/1.0 \n2. Download the template_build.zip\n3. Unzip\n4. Run the executable!\n\n[🔝 Back to Top](#top)\n\n\n\n\u003ca name=\"3D\"\u003e\u003c/a\u003e\n\n## 5. 3D\n\n\u003ca name=\"5a\"\u003e\u003c/a\u003e\n\n### \t5a General\n\nGood for you for deciding to go 3D. Before we go any further, it is not recommended that you start off with a 3D project if you are just starting out doing game design. Furthermore, it is recommended that you start with the previous 2D tutorial because some of the concepts and components will be similar or exact. \n\nTo start a 3D project, press **New** and select 3D on the pop-up screen and use the desired directory (or follow my cloning [guide](#guide) so to not start from starch). This may take some time, but after Unity finishes installing itself, we can get started. Now let's make a 3D game!\n\nWhen you start off, you will be brought up to a scene consisting of a directional light (which is like a ray/sun light) and a Camera\n\n\\* Note this tutorial (3D) follows this repo: https://github.com/Zeyu-Li/Unity-Tutorial-3D\n\n\n\n\u003ca name=\"5b\"\u003e\u003c/a\u003e\n\n### \t5b 3D Models \u0026 Bodies\n\n#### Resources\n\nBefore we get to 3D bodies in Unity, it is necessary to get 3D models. Unity is not built to be a 3D modeling software, so 3D objects should be created in 3D programs or imported from 3D libraries. Therefore, I will recommend some free software and libraries\n\n\u003ca name=\"software\"\u003e\u003c/a\u003e\n\n#### Software\n\n**Free**\n\n* [Blender](https://www.blender.org/) - a very powerful open source 3D modeling, texturing, animations, and general 3D software. All my models in the exercises where made in Blender. A good place to start is with [Andrew's Donut](https://www.youtube.com/watch?v=TPrnSACiTJ4\u0026list=PLxLGgWrla12dEW5mjO09kR2_TzPqDTXdw). New 2.8 version is very similar to all other 3D software. I **very strongly** advice you use Blender because it is free and is often much better than paid software\n* [TreeIt](https://www.evolved-software.com/treeit/treeit) - a tree generator with presets that range from cacti to palm trees\n\n**Paid**\n\n* [Cinema 4D](https://www.maxon.net/en-us/products/cinema-4d/overview/) - 59.99USD/month (overpriced and not as good as Blender)\n\n* [Autodesk Maya](https://www.autodesk.com/products/maya/overview) - 1 620 USD/year (supposedly the industry standard) \n  \\* Note I don't know if they have a 3 year free for students like other Autodesk CAD software\n\n* [Houdini](https://www.sidefx.com/products/houdini/) - 199 USD / year\n\n* [Substance Designer](https://www.substance3d.com/products/substance-designer) - $19.90/month (for **revenue** under \\$100k) a node based texture designer\n\n  \\* Note this is a really powerful piece of software, but from my experience, it is not easy to learn and textures can be found online or created with other programs like Adobe Illustrator and converted into normal maps in Blender.\n\n\\* Note don't use CAD software like Fusion 360, Revit, Solidworks etc, because those are for CAD (computer assisted design) and are aimed towards engineers. Also, Blender has Architectural Plugin with many of the functionality of Autodesk Revit. \n\n\u003ca name=\"libraries\"\u003e\u003c/a\u003e\n\n#### Libraries\n\n* [Unity Asset Store](https://assetstore.unity.com/3d) - free and paid assets\n* [Free 3D](https://free3d.com/3d-models/unity) - be careful, some items are not for commercial applications\n\n**Textures**\n\n* [3D Textures](https://3dtextures.me/)\n* [TTextureHaven](https://texturehaven.com/)\n* [CC0 Textures](https://cc0textures.com/)\n\n\u003ca name=\"m_unity\"\u003e\u003c/a\u003e\n\n#### Unity\n\nIf you have experience with 3D software like Cinema 4D, Blender, or the Autodesk suit, Unity 3D will be very familiar to you. If you have not worked in a 3D environment, there is some adjusting. Note I will **not** go through the tools (ie rotate, scale, transform) for manipulating 3D bodies because they are the universal shortcuts and effects (ie. `w` for move, `e` for rotate, and `r` for scale). \n\nFirst off note that you do not need to make all 3D asset body. There are many asset stores with free and paid models. Usually I will use tons of free assets from the asset package (or go to [asset store](https://assetstore.unity.com/3d)) and if I need something custom, I model it with Blender. I recommend learning a 3D software before going into Unity 3D because it can be translated almost directly to Unity with light sources, objects, texture maps, etc. (my recommendation is to follow [Blender Guru](https://www.youtube.com/user/AndrewPPrice) on YouTube). \n\nTo import 3D models/bodies, you will have to import it as a fbx file (make sure you export only the things you have selected (the model) and not everything including the camera, lights, etc. or you can choose to not import the camera or lights in Unity) \n\nFrom there I have a model that can be dragged into the scene. Now you have the model with the materials and other properties included.\n\n![material](images/material.png)\n\nOf course, you can move it, rotate it, or scale it, but I will assume you know what to do that. However, if you want Unity to automatically general colliders for the model (generally good enough), \n\n1. Click on the model and under **Meshes** select **Generate Colliders**\n\n![generate](images/generate.png)\n\\* Note for some things like platforms, **Generate Colliders** can be bad as the optimized mesh collides with the player, therefore switch to box colliders\n\n2. Click **apply**\n3. Now Unity is generating colliders and this may take a while\n\nIf you want an object to be solid and non-movable (this will use bake lighting, which I will go into more detail later), check **Static**. Remember, this will generate a bake map, which is CPU intensive and may take a lot of time depending on the size of the model. Unfortunately, if the object is really big, checking Static may actually slow things down, so keep that in mind\n\n**Clean Snapping**\n\nIn many 3D programs, you will gUnity is not buildet options to snap to another object or vertex. This can be done in Unity. To achieve this,\n\n1. Select **Shaded Wireframe** as the view\n\n   ![view](images/view.png)\n2. Click on the **Move Tool** (the one with the arrows in 4 directions), hold down the **v key** and it will snap to a vertex \n3. With the v-key still help, drag and it will snap to another vertex \n\\* Note if you want to organize the 'layers', use **Quads** as they are 3D equivalents of empties\n\nResource: https://youtu.be/NjflKgMepQs\n\n\n\n\u003ca name=\"5c\"\u003e\u003c/a\u003e\n\n### \t5c Movement\n\n**Legacy Way:**\n\n~~For movement, generally, Unity's Standard Package can be used so no bones, animations, or controls need to be wired. I recommend importing Unity's character package. This is done by,~~\n\n1. ~~installing the [Unity Standard Assets Package](https://assetstore.unity.com/packages/essentials/asset-packs/standard-assets-for-unity-2017-3-32351) in the **Asset Store**~~\n2. ~~In a new player folder, go to Assets -\u003e Import Package -\u003e Characters and click **Import** (this may or may not work and thus, you may need to import all of the standard package and purge unused)~~\n3. ~~In the imported Standard Assets, go to Characters -\u003e FirstPersonCharacter-\u003ePrefabs-\u003eFPSController and drag it into the scene~~\n\n**New way:**\n\nNow that no Standard Packages exist, the easiest way to make a player is to create it from scratch\n\n1. New empty object named player\n2. add a **character controller** as a component to the empty\n   1. You can change the slope limit (limit angle at which you traverse a slope)\n   2. Skin width\n   3. Center at which the character is based on \n   4. Radius and Height of the capsule containing the player\n3. Add a camera to the empty, otherwise, move the empty exactly to the existing camera and move it such that it does not overlap meshes\n4. At this point, you can add the mesh that is your player and have it hold up to some animations or preloaded with animations, but for this tutorial, I will use a yellow capsule\n5. Next we want to control the camera with the mouse so create a cameraControl script in the scripts folder\n6. Paste the following in\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   \n   public class cameraControl : MonoBehaviour\n   {\n       // sensitivity of mouse\n       public float mouseSpeed = 100f;\n   \n       // place camera here\n       public Transform player;\n   \n       float xRotation = 0f;\n   \n       // Start is called before the first frame update\n       void Start() {\n           Cursor.lockState = CursorLockMode.Locked;\n       }\n   \n       // Update is called once per frame\n       void Update()\n       {\n           float mouseX = Input.GetAxis(\"Mouse X\") * mouseSpeed * Time.deltaTime;\n           float mouseY = Input.GetAxis(\"Mouse Y\") * mouseSpeed * Time.deltaTime;\n   \n           // for every frame, move camera up or down\n           xRotation -= mouseY;\n           // clamp the up down rotation\n           xRotation = Mathf.Clamp(xRotation, -85f, 85f);\n   \n           transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);\n           player.Rotate(Vector3.up * mouseX);\n       }\n   }\n   ```\n7. Optionally, you can smooth out the camera using the Lerp method\n8. Drag the player empty object into the Transform\n9. Next is movement\n10. Add a new player movement script to the empty player object\n11. Paste the following\n    ```c#\n    using System.Collections;\n    using System.Collections.Generic;\n    using UnityEngine;\n    \n    public class movement : MonoBehaviour\n    {\n        public CharacterController controller;\n    \n        public float movementSpeed = 14f;\n    \n        // gravity\n        public float gravity = -10f;\n        Vector3 velocity;\n    \n        // ground check\n        public Transform groundCheck;\n        public float checkRadius = 0.1f;\n        public LayerMask ground;\n    \n        public bool isGrounded = false;\n    \n        // jump\n        public float jump = 1f;\n    \n        // slope\n        public bool isSliding = false;\n        public float slopeLimit = 35f;\n        private Vector3 slopeParallel;\n    \n        // Update is called once per frame\n        void Update()\n        {\n            // is grounded calculations\n            isGrounded = Physics.CheckSphere(groundCheck.position, checkRadius, ground);\n    \n            if (isGrounded) {\n                velocity.y = -2f;\n            }\n    \n            float x = Input.GetAxis(\"Horizontal\");\n            float z = Input.GetAxis(\"Vertical\");\n    \n            Vector3 move = transform.right * x + transform.forward * z;\n    \n            controller.Move(move*movementSpeed*Time.deltaTime);\n    \n            // slopes, modified from https://answers.unity.com/questions/1502223/sliding-down-a-slope-with-a-character-controller.html\n            if (isGrounded) {\n                RaycastHit hit;\n                Physics.Raycast(transform.position, Vector3.down, out hit);\n                // Saving the normal\n                Vector3 n = hit.normal;\n    \n                // Crossing my normal with the player's up vector (if your player rotates I guess you can just use Vector3.up to create a vector parallel to the ground\n                Vector3 groundParallel = Vector3.Cross(transform.up, n);\n    \n                // Crossing the vector we made before with the initial normal gives us a vector that is parallel to the slope and always pointing down\n                slopeParallel = Vector3.Cross(groundParallel, n);\n                Debug.DrawRay(hit.point, slopeParallel * 10, Color.green);\n    \n                // Just the current angle we're standing on\n                float currentSlope = Mathf.Round(Vector3.Angle(hit.normal, transform.up));\n    \n                // If the slope is on a slope too steep and the player is Grounded the player is pushed down the slope.\n                if (currentSlope \u003e= slopeLimit) {\n                    isSliding = true;\n                }\n                // If the player is standing on a slope that isn't too steep, is grounded, as is not sliding anymore we start a function to count time\n                else if (currentSlope \u003c slopeLimit \u0026\u0026 isSliding) {\n                    isSliding = false;\n                }\n            }\n    \n            if (isSliding) {\n                controller.Move(slopeParallel.normalized / 2 * Time.deltaTime);\n            }\n    \n            // jump\n            if (Input.GetButtonDown(\"Jump\") \u0026\u0026 isGrounded) {\n                velocity.y = Mathf.Sqrt(jump * -2f * gravity);\n                if (isSliding) {\n                    // cut jump in halve\n                    velocity.y /= 2;\n                }\n            }\n    \n            velocity.y += gravity*Time.deltaTime;\n    \n            controller.Move(velocity * Time.deltaTime);\n        }\n    }\n    ```\n    This accounts for gravity and movement\n    \\* Note you can change the speed of movement, gravity constant, jump check radius, under the script. Also, sliding down slopes is a given\n12. For the gravity to work properly, a ground check must be performed to reset the velocity. To do this, create empty object in player and place at the feet of the player\n13. Add new layer of ground to perform jumps and gravity checks on and apply it to the models\n\nResource: [Brackeys](https://www.youtube.com/watch?v=_QajrabyTJc)\n\n\n\n\u003ca name=\"5d\"\u003e\u003c/a\u003e\n\n### \t5d Camera\n\nThere are a few options for cameras. For a fixed camera following the player:\n\n1. Nest the camera into the Player\n2. Move to the right position and angle\n\n\nThere are special camera options (such as a more flexible or switching to several fixed cameras) that use Cinemachine. Tutorials for Cinemachine can be found below:\n\n[Brackeys](https://www.youtube.com/watch?v=Gx9gZ9cfrys)\n\n[FilmStorm](https://www.youtube.com/watch?v=J1GgvDfmIo0)\n\n\n\n\u003ca name=\"light\"\u003e\u003c/a\u003e\n\n### \t5e Lighting\n\nJust like other 3D applications, Unity has an array of lighting options\n\nThe most important of these are the following:\n\n1. Point light - light is emitted from a point\n2. Directional light - a moon or sun light. Position does not matter, but the rotation determines the angle of attack\n3. Spot light - like that of a lamp\n4. Light Area - light emitted from an area\n\nFrom there, we can change some properties of the lights:\n\n* range - range of light source\n* color - color of light\n* shadow type\n  * soft shadows - blurred shadow\n  * hard shadows - very rough edged shadows\n\nSome other light options include an ambient light that lunates everything. This can be changed in the Window -\u003e Rendering -\u003e Lighting Settings. From there, there are many options you can play with. Also in the options is to add atmospheric fog.\n\nAnother important thing about lighting is bake lighting. Baking is a way to save space by \"baking\" or pre-mapping the lighting in the texture map so lighting does not need to be calculated again in real time. This may be something you would want to look into if you have problems with framerate, or just want to speed/smooth out the game. \n\n\n\n\u003ca name=\"5f\"\u003e\u003c/a\u003e\n\n### \t5f Prefab\n\nA prefab is simply a clone that can be dragged to the scene\n\nThis means that things in other scenes can be reused\n\nTo make a prefab, just drag the desired prefab object from scene to the prefabs folder\n\n\n\n\u003ca name=\"5g\"\u003e\u003c/a\u003e\n\n### \t5g Particle Systems\n\n3D particle systems are very similar to 2D particle systems, therefore so particle options, go to the 2D [particle section](https://github.com/Zeyu-Li/unity-user-guide#4f-particle-system) for help with the options\n\nFor this tutorial, I will just be adding a smoke particle effect from a pipe\n\n1. Import the pipe. I have one provided in the models folder if you want to follow along. (Again, this model was made by myself and you can use it in your projects) \n2. In the new model, add a new **particle system** be right clicking -\u003e Effects -\u003e Particle System\n3. Move, rotate and scale it to the right size (note the scale should be equal in all directions (x,y,z) for it to remain uniform)\n4. Changing the shape will determine the emission's direction\n5. Changing other attributes with the link above to the desired particle\n6. To change the texture of the particles, just drag and drop the image onto the particles\n\n\n\n\u003ca name=\"3anim\"\u003e\u003c/a\u003e\n\n### \t5h Animation\n\nUnity animations are very similar to other 3D animating software. This means there is a timeline with keyframes. For this tutorial, I will be doing a spinning and blobbing key. \n\n1. Place the object in the scene\n2. Go to the animation window and click **Add Animation**\n3. Save to the animation folder and set the time to whatever\n4. From there, you can click **Add Property **add something you would like to change over time\n5. For my example, I chose to key frame the rotation and position\n6. Set the start value and click the **Add Keyframe** (which looks like a diamond).\n7. Go to the end position and change the keyframe value (once changed the text area should be red) and click **Add Keyframe**\n8. Note the curves are set to non-linear (ie ease in and ease out). Therefore, to make them linear, I found the easiest way to do that would be to go the Curves **tab, click on the keyframe and a handle will appear. Drag the handle to the first keyframe or vice versa.\n\n\\* If you want to move this in global space, encapsulate it in a empty object and move the empty\n\nAnother way to the animation is to do it in the 3D program of choice (for me Blender) and export the animation within the fbx file format\n\n1. Have the export fbx with animation made\n2. Click on the fbx in Unity and change it to **Animation**\n\n   ![3animation](images/3animation.png)\n3. If you have several animations, you have to separate the different animations apart by clicking the add icon (below) and adjusting the start and end frames\n\n   ![clips](images/clips.png)\n4. Create an animations controller and rename it. Also double click it\n5. It will open up the Animator window so right click and click Create State -\u003e Empty\n6. Open the new empty state and rename it. Afterwards, change the motion to the imported motion (ie, it would be Torus|TorusAcion for my animation (seen above))\n7. Add an **Animator **to the animated object in the scene and add the controller. If you enable the animator the animation plays. With this in mind, I will use an event to enable the animation [later](#3events)\n\n   \n\n\u003ca name=\"3coll\"\u003e\u003c/a\u003e\n\n### \t5i Collectables\n\n1. The collectable should have the desired tag before starting\n\n2. Within the player controller (movement.cs) check for collision with the tag. If overlap, destroy the object\n\n   ```c#\n   private void OnTriggerEnter(Collider collision) {\n       if (collision.gameObject.CompareTag(\"key\")) {\n           Destroy(collision.gameObject);\n       }\n   }\n   ```\n\n3. Now once the player collides with the key, the key is destroyed\n\nNext thing we might want to do is add the key to our inventory. \n\n1. Create a UI -\u003e Canvas count object to be displayed once the object is collected\n   For my project, it is simply a sprite of a key appearing as I collect it\n\n2. The player should have the player tag\n\n3. Create a new script for the key once it is collected by the player\n\n4. I named my script key and had this in my script:\n\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   \n   public class key : MonoBehaviour\n   {\n    public GameObject menu;\n       private bool isShowing = false;\n   \n   \n       // Start is called before the first frame update\n       private void OnTriggerEnter(Collider collision) {\n           if (collision.gameObject.CompareTag(\"Player\")) {\n               isShowing = true;\n               menu.SetActive(isShowing);\n           }\n       }\n   }\n   \n   ```\n\nNow if the key is collected, the key will show up on screen\n\n\n\n\u003ca name=\"3events\"\u003e\u003c/a\u003e\n\n### \t5j Events\n\nFor this tutorial, I will make an event that activates once the key is collected. After which, a door opens. \n\n\\* Note this is working from the last collectables and animation section\n\n1. Within the key script, replace with the following:\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   \n   public class key : MonoBehaviour\n   {\n       public GameObject menu;\n       private bool isShowing = false;\n   \n       // gate animation\n       public GameObject gate;\n       Animator gateAnim;\n       public GameObject goal;\n   \n       private void Start() {\n   \n           gateAnim = gate.GetComponent\u003cAnimator\u003e();\n   \n       }\n   \n       // Start is called before the first frame update\n       private void OnTriggerEnter(Collider collision) {\n           if (collision.gameObject.CompareTag(\"Player\")) {\n               isShowing = true;\n               menu.SetActive(isShowing);\n               gateAnim.enabled = isShowing;\n               goal.enabled = isShowing;\n           }\n       }\n   }\n   ```\n2. Drag the gate containing the animator into the gate box and a goal with a collider to send you to the end screen to the goal box\n3. Now when the player collects the key, the gate will open and a goal with appear to the player to get to\n\nNow the final set is to send the player into the end screen after colliding with the goal box\n\n1. Set up the goal box\n2. Set up a new scene with the endscreen (this will simply be a black screen saying to be continued)\n3. Make a new script in the goal object\n4. In the script simply type out the following\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   using UnityEngine.SceneManagement;\n   \n   public class endScene : MonoBehaviour {\n       static public bool end = true;\n       private void OnTriggerEnter(Collider collision) {\n           if (collision.gameObject.CompareTag(\"Player\")) {\n               Done();\n           }\n       }\n   \n       // Update is called once per frame\n       void Done() {\n           SceneManager.LoadScene(\"title\");\n       }\n   }\n   ```\n\n\n\n\u003ca name=\"3music\"\u003e\u003c/a\u003e\n\n### 5k Music \u0026 Sounds\n\nMusic and sounds are important in the gameplay as it immerses the player into the game. This section will be split into two parts, music and sounds. \n\n**Music**\n\nAdding a track to the game is as easy as counting to 3. \n\n1. Have a music track (you can use mine called happy if you so choice)\n2. Simply drag the music into the player object\n3. In the settings you can change if it plays on startup and if it loops\n\n\\* Note when you are playing the game, don't forget to hit unmute\n\n**Sounds**\n\nAmbient sounds can be a great way to add that something extra to the game. This can be rustling leaves or  footsteps. For this tutorial, I will do footstep sounds when the player walks.\n\n1. Have a sound to play (an excellent resource is https://freesound.org/)\n\n2. In the movement script add the following:\n\n   ```c#\n   public class movement : MonoBehaviour\n   {\n   \n       // sound\n       public AudioClip[] footsteps;\n       public float volume = .5f;\n       public AudioSource listener;\n       private int index;\n       private float counter = 0;\n   \n       private void Start() {\n           listener = GetComponent\u003cAudioSource\u003e();\n       }\n   \n       // Update is called once per frame\n       void Update()\n       {\n           // is grounded calculations\n           isGrounded = Physics.CheckSphere(groundCheck.position, checkRadius, ground);\n   \n           float x = Input.GetAxis(\"Horizontal\");\n           float z = Input.GetAxis(\"Vertical\");\n   \n           if (isGrounded) {\n               velocity.y = -2f;\n               // plays walk sound\n               if (counter \u003c= 0 \u0026\u0026 (x != 0f || z != 0f)) {\n                   index = Random.Range(0, footsteps.Length);\n                   counter = footsteps[index].length;\n                   listener.PlayOneShot(footsteps[index], volume);\n               }\n               counter -= Time.deltaTime;\n           }\n   \n           Vector3 move = transform.right * x + transform.forward * z;\n   \t}\n   }\n   ```\n\n3. Grab the footsteps and place it in the footsteps audioclips after putting the number of audio clips to randomly choose from\n\n4. Add the audio listener and change volume\n\n\n\n\u003ca name=\"3odds\"\u003e\u003c/a\u003e\n\n### 5l Odds and Ends\n\n\u003ca name=\"3_pausing\"\u003e\u003c/a\u003e\n\n#### Pausing\n\nPausing with Unity can be made simple with one command. \n\n1. Create script pause and drag it on your player (optionally, you can just do this in the movement folder, but this will be more organized)\n2. Create a pause UI element (I will be doing a simple Pause text)\n3. Paste in the following:\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   \n   public class pause : MonoBehaviour\n   {\n       public static bool paused = false;\n   \n       public GameObject pauseMenu;\n   \n       // Update is called once per frame\n       void Update()\n       {\n           if (Input.GetKeyDown(KeyCode.P)) {\n               Pause();\n           }\n       }\n   \n       void Pause() {\n           if (!paused) {\n               pauseMenu.SetActive(true);\n               Time.timeScale = 0f;\n           } else {\n               pauseMenu.SetActive(false);\n               Time.timeScale = 1f;\n           }\n           paused = !paused;\n       }\n   }\n   ```\n4. Place the UI element in the Pause menu box\n\nResource: https://www.youtube.com/watch?v=JivuXdrIHK0\n\n\n\n\u003ca name=\"3_exit\"\u003e\u003c/a\u003e\n\n#### Exit Game\n\nTo quit game simply add the following onto the player:\n\n```c#\nif (Input.GetKey(\"escape\")) // change escape to any other character if you like \n{\n    Application.Quit();\n}\n```\n\nin the update method\n\n\\* Note, of course more logic could be added to make this more complicated\n\n\n\n\u003ca name=\"3demo\"\u003e\u003c/a\u003e\n\n### 5m Demo\n\nI hope you enjoyed this tutorial and the finished version is here.\n\nUnfortunately, I cannot insert a demo here as it would be too long (if you want to download the game see instructions below), but I can share some screenshots here:\n\n![title](images/title.png)\n\n![screen2](images/screen2.png)\n\n![screen1](images/screen1.png)\n\nFeel free to [play the game](https://github.com/Zeyu-Li/Unity-Template-3D-2019_3/releases/tag/1.0) or use any of the resources for the game. I hope you've enjoyed this experience and I wish you luck in making your games!\n\nIf you want to play it yourself (On windows, sorry Unix users 😜 need to build from source yourself):\n\n1. Go to the the releases on the GitHub or https://github.com/Zeyu-Li/Unity-Tutorial-3D/releases/tag/1.0 \n2. Download the 3D_template_game.zip\n3. Unzip\n4. Run the executable!\n\n[🔝 Back to Top](#top)\n\n\n\n\u003ca name=\"3_title\"\u003e\u003c/a\u003e\n\n### 6. Title Screen\n\nOne of the last things to do is to create a title screen. I will be basing my title screen on the 3D game.\n\n1. For my scene, it is the camera spinning through the 3D scene\n\n2. Overlaid is a canvas with a black panel within it\n\n3. Now you can populate with text, sprites, buttons and so forth, adjusting them to your liking\n\n4. To add functionality to the button, attach a script to the collection of menu object\n\n5. Populate with functions of the button in their own separate methods. For example, my script looks like the following:\n\n   ```c#\n   using System.Collections;\n   using System.Collections.Generic;\n   using UnityEngine;\n   using UnityEngine.SceneManagement;\n   \n   public class menu : MonoBehaviour\n   {\n       // Start is called before the first frame update\n       public void play() {\n           SceneManager.LoadScene(\"main\");\n       }\n   \n       public void quit() {\n           Application.Quit();\n       }\n   \n   }\n   ```\n\n6. With the button selected, click on the **+** icon in the On Click part (below)\n\n   ![buttonAction](images/buttonAction.png)\n\n7. Drag the menu in the None (Object) box\n\n8. In the drop down (no function), change into the function you want to activate (it will be in the name of the script)\n\n\n\n\u003ca name=\"script\"\u003e\u003c/a\u003e\n\n### 7. Scripting\n\nUnity is based on C# and is very much a c-styled programming language. That means it resembles programs that are written in C, C++, F#, or Java. \n\nThe main thing to know though is Unity's implementation of C#\n\nIf you create a script, automatically, it will be drawn from a template that looks similar to the following:\n\n```c#\nusing System.Collections;\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class movement : MonoBehaviour\n{\n    // Start is called before the first frame update\n    void Start()\n    {\n        \n    }\n\n    // Update is called once per frame\n    void Update()\n    {\n        \n    }\n}\n```\n\nYou will notice that at the top there are imports from Unity's other libraries using the **using** keyword. Afterwards, Unity defines the script as a class*. The class is defined as public so other scripts and Unity can assess and utilize this class. The name you gave the script will follow the **class** keyword. Afterwards, **MonoBehaviour** is defined as what movement inherits from. Think of this as your script **extending** from class MonoBehaviour. \n\n\\* Note a class is a data structure that holds a collection of information on the class (ie. its attributes and methods). \n\nBelow that and indented, we see void Start() and void Update(). As the comments suggest, void Start() occurs before the first frame update and void Update() is called once per frame. Note **void** means there will not be a return value (ie. no return statement).\n\nAlso, there are different methods of MonoBehaviour such as **FixedUpdate()** that may update more or less than once per frame. This will be important for any physics related functions\n\nA list of other functions and methods that can be used can be found on the [Unity Documentation](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html) site, however, the most important thing about learning and debugging Unity is to use\n\n```c#\nDebug.Log() // logs to Unity console\n```\n\nWhen using this, after running the game, it will output to Unity's debug console\n\n\n\n\u003ca name=\"build\"\u003e\u003c/a\u003e\n\n### 8. Build\n\nSo you are finished your game. You need to disturbed the game. This is done through building the game. \n\n1. Go to **File**, **Build Settings...**\n\n2. Select the scenes that you want to build\n\n   ![build](images/build.png)\n\n3. Select the desired **Platform**\n\n4. You can customize the company name, product name, icon, and cursor\n\n5. **Build** (**And Run** if you want to run it)\n\n6. Select the folder and wait for it to build\n\n\\* Note if you did not add an exit game button, the only way to exit is to close the program externally or Alt-f4\n\n\n\n\u003ca name=\"guide\"\u003e\u003c/a\u003e\n\n### 9. Cloning Guide\n\nTo download the finished projects:\n\n1. Find the right Unity Repo to clone from my account (https://github.com/Zeyu-Li/Unity-Tutorial-2D or https://github.com/Zeyu-Li/Unity-Tutorial-3D) \n\n2. Download ZIP after clicking Clone or download\n\n   ![download](images/download.png)\n\n3. Unzip and move to desired directory\n\n4. Go on Unity Hub and click **Add** and located to directory\n\n5. The project should appear in Projects and it is done\n\n6. Click on the project to open it\n\n  \\* Note if you want the project at different steps for 2D click on commits or https://github.com/Zeyu-Li/Unity-Tutorial-2D/commits/master and between Feb 26, 2020 `added logo` commit to April 12, 2020 `finished Unity template game` is when various steps were completed. To download the project file at these times, click on the bracket thing (see below) and repeat above from step 2\n\n![history](images/history.jpg)\n\nelse for 3D, go to https://github.com/Zeyu-Li/Unity-Tutorial-3D/commits/master and between April 13, 2020 `added imaged` commit to May 6, 2020 `finished game` is when various steps where completed. \n\n\n\n\u003ca name=\"team\"\u003e\u003c/a\u003e\n\n### 10. Collaboration\n\n\u003ca name=\"unity\"\u003e\u003c/a\u003e\n\n#### Unity's Collab\n\nCollaborating with friends can be tough with Unity, especially with git/GitHub, but if you are careful, things could turn out fine.\n\nIf you need to collaborate, the best way is to use Unity's Collab feature\n\n![collab](images/collab.png)\n\nHowever, note that this only supports 4 people (which is usually enough because only people that will contribute to the codebase should need it)\n\n\n\n\u003ca name='git'\u003e\u003c/a\u003e\n\n#### GitHub\n\nOtherwise if you are a masochistic and decide to GitHub, here are some general practices:\n\n1. Everyone should work on their own branches and work on their own scenes working towards **Prefabs** (ie one person on movement, one on moving platforms, etc.)\n2. Optionally, have one person on the master (final) level to peace it together\n3. Use [this](https://github.com/github/gitignore/blob/master/Unity.gitignore) gitignore or clone from my projects on GitHub\n4. Have the core gameplay done first (especially at a Game Jam)\n5. Get to know Git/GitHub and how version control works\n6. Remember you can go back to a previous working version\n7. Have fun and don't fight with your team members\n\n[🔝 Back to Top](#top)\n\n\n\n\u003ca name=\"Help\"\u003e\u003c/a\u003e\n\n### 11. Resources\n\n* The [Unity User Manual](https://docs.unity3d.com/Manual/index.html) provides some great documentation with code that can for the most part be copied and pasted\n* Brackeys [YouTube channel](https://www.youtube.com/user/Brackeys)\n* [Lynda.com](https://www.lynda.com/) - If you have a library card, there is a high probability that you have access to Lynda with their organization deal\n* Google is your best friend\n* Ask on Reddit or Stack Exchange, don't worry they won't bite\n\n","funding_links":["https://github.com/sponsors/Zeyu-Li"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeyu-li%2Funity-user-guide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeyu-li%2Funity-user-guide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeyu-li%2Funity-user-guide/lists"}