{"id":13664587,"url":"https://github.com/ozankasikci/unity-cheat-sheet","last_synced_at":"2026-02-25T08:07:07.032Z","repository":{"id":48124602,"uuid":"287488929","full_name":"ozankasikci/unity-cheat-sheet","owner":"ozankasikci","description":"C# Cheat sheet for Unity","archived":false,"fork":false,"pushed_at":"2025-01-26T21:47:17.000Z","size":588,"stargazers_count":246,"open_issues_count":1,"forks_count":32,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-02-28T09:44:51.672Z","etag":null,"topics":["cheatsheet","csharp","unity","unity-scripts","unity-tutorial","unity3d"],"latest_commit_sha":null,"homepage":"http://unitycheatsheet.com/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ozankasikci.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2020-08-14T08:55:37.000Z","updated_at":"2025-02-26T18:39:58.000Z","dependencies_parsed_at":"2024-03-21T19:30:02.553Z","dependency_job_id":"a916fe4e-9acf-44ce-8a9a-8b48b16761cd","html_url":"https://github.com/ozankasikci/unity-cheat-sheet","commit_stats":{"total_commits":58,"total_committers":2,"mean_commits":29.0,"dds":0.4655172413793104,"last_synced_commit":"9e46234f50524056057ff3c964c882798b2ff7f3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ozankasikci/unity-cheat-sheet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ozankasikci%2Funity-cheat-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ozankasikci%2Funity-cheat-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ozankasikci%2Funity-cheat-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ozankasikci%2Funity-cheat-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ozankasikci","download_url":"https://codeload.github.com/ozankasikci/unity-cheat-sheet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ozankasikci%2Funity-cheat-sheet/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265623231,"owners_count":23800126,"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":["cheatsheet","csharp","unity","unity-scripts","unity-tutorial","unity3d"],"created_at":"2024-08-02T05:03:00.540Z","updated_at":"2026-02-25T08:07:07.025Z","avatar_url":"https://github.com/ozankasikci.png","language":"C#","funding_links":[],"categories":["miscellaneous"],"sub_categories":[],"readme":"# Unity Cheat Sheet\n\n## Table of Contents\n\n- [Basics](#basics)\n  - [MonoBehaviour](#monobehaviour)\n  - [Transform](#transform)\n  - [Vector3](#vector3)\n  - [Quaternion](#quaternion)\n  - [Euler Angles](#euler-angles)\n- [Movement \u0026 Rotation](#movement--rotation)\n  - [Move Object](#move-object)\n    - [Transform.Translate()](#transformtranslate)\n    - [Vector3.MoveTowards()](#vector3movetowards)\n    - [Vector3.Lerp()](#vector3lerp)\n    - [Vector3.SmoothDamp()](#vector3smoothdamp)\n  - [Rotate Object](#rotate-object)\n    - [Transform.rotation](#transformrotation)\n    - [Transform.eulerAngles](#transformeulerangles)\n    - [Transform.Rotate()](#transformrotate)\n    - [Transform.RotateAround()](#transformrotatearound)\n    - [Transform.LookAt()](#transformlookat)\n    - [Quaternion.LookRotation()](#quaternionlookrotation)\n    - [Quaternion.FromToRotation()](#quaternionfromtorotation)\n    - [Quaternion.ToAngleAxis()](#quaterniontoangleaxis)\n- [Physics](#physics)\n  - [Raycast](#raycast)\n  - [Collisions \u0026 Triggers](#collisions--triggers)\n  - [Ignore Collision](#ignorecollision)\n- [Input](#input)\n  - [Keyboard](#keyboard)\n  - [Mouse](#mouse)\n  - [Touch](#touch)\n  - [New Input System](#new-input-system)\n- [UI](#ui)\n  - [Button](#button)\n  - [Slider](#slider)\n- [Audio](#audio)\n  - [Basic Audio Play](#basic-audio-play)\n- [Scripting](#scripting)\n  - [Coroutines](#coroutines)\n  - [Async/Await](#asyncawait)\n    - [Basic Structure](#basic-structure)\n    - [Loading Resources](#loading-resources)\n    - [Web Requests](#web-requests)\n    - [Scene Loading](#scene-loading)\n    - [Parallel Operations](#parallel-operations)\n    - [Timeout Handling](#timeout-handling)\n    - [Best Practices](#best-practices)\n  - [Event Systems](#event-systems)\n  - [Scriptable Objects](#scriptable-objects)\n  - [Custom Editor Scripts](#custom-editor-scripts)\n- [Design Patterns](#design-patterns)\n  - [Singleton](#singleton)\n  - [Factory Pattern](#factory-pattern)\n  - [Observer Pattern](#observer-pattern)\n  - [Command Pattern](#command-pattern)\n  - [State Pattern](#state-pattern)\n    - [Basic Example](#basic-example)\n    - [Detailed Example - Game Onboarding System](#detailed-example---game-onboarding-system)\n  - [Strategy Pattern](#strategy-pattern)\n    - [Basic Example](#basic-example-1)\n    - [Detailed Example - Combat System](#detailed-example---combat-system)\n  - [Object Pooling Pattern](#object-pooling-pattern)\n  - [Chain of Responsibility Pattern](#chain-of-responsibility-pattern)\n    - [Basic Example](#basic-example-2)\n    - [Detailed Example - Input Handling System](#detailed-example---input-handling-system)\n- [Shortcuts](#shortcuts)\n  - [Scene View Editing](#scene-view-editing)\n  - [Scene View Navigation](#scene-view-navigation)\n  - [Hierarchy Management](#hierarchy-management)\n  - [Layout](#layout)\n- [Practical Use Cases](#practical-use-cases)\n  - [Check if object is on the ground](#check-if-object-is-on-the-ground)\n  - [Get the transform of a Body Bone](#get-the-transform-of-a-body-bone)\n  - [Make object look at the camera](#make-object-look-at-the-camera)\n  - [Camera follow \u0026 orbit](#camera-follow--orbit)\n  - [Fade UI element](#fade-ui-element)\n  - [Load next scene](#load-next-scene)\n- [TBD (To Be Documented)](#tbd-to-be-documented)\n  - [Scripting](#scripting-1)\n\n## Basics\n\n### [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html)\n[MonoBehaviour Life Cycle Flow Chart](https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg)\n```csharp\n// MonoBehaviour is the base class from which every Unity script derives.\n// Offers some life cycle functions that are easier for you to develop your game.\n\n// Some of the most frequently used ones are as follows;\nAwake()\nStart()\nUpdate()\nFixedUpdate()\nLateUpdate()\nOnGUI()\nOnEnable()\nOnDisable()\n```\n\n### [Transform](https://docs.unity3d.com/ScriptReference/Transform.html)\n```csharp\n// Transform is a fundamental component in Unity that every GameObject has.\n// It defines the object's Position, Rotation, and Scale in the game world.\n\n// Access the transform component\nTransform transform = gameObject.transform;\n\n// Position: Vector3 representing world space coordinates (x, y, z)\ntransform.position = new Vector3(0, 2, 0);      // Set absolute position\ntransform.localPosition = Vector3.zero;         // Position relative to parent\n\n// Rotation: Can be set using Euler angles (degrees) or Quaternions\ntransform.rotation = Quaternion.identity;       // No rotation\ntransform.eulerAngles = new Vector3(0, 90, 0);  // Rotate 90 degrees around Y axis\ntransform.localRotation = Quaternion.identity;  // Rotation relative to parent\n\n// Scale: Vector3 representing scale on each axis\ntransform.localScale = Vector3.one;             // Normal scale (1, 1, 1)\ntransform.localScale = new Vector3(2, 2, 2);    // Double size on all axes\n\n// Parent-Child Relationships\ntransform.parent = anotherObject.transform;     // Set parent\ntransform.SetParent(null);                      // Remove parent (make root)\n```\n\n### [Vector3](https://docs.unity3d.com/ScriptReference/Vector3.html)\n```csharp\n// Vector3 is representation of 3D vectors and points\n// It's used to represent 3D positions,considering x,y \u0026 z axis.\n\nVector3 v = new Vector3(0f, 0f, 0f);\n```\n\n### [Quaternion](https://docs.unity3d.com/ScriptReference/Quaternion.html)\n```csharp\n// A Quaternion stores the rotation of the Transform in world space.\n// Quaternions are based on complex numbers and don't suffer from gimbal lock.\n// Unity internally uses Quaternions to represent all rotations.\n// You almost never access or modify individual Quaternion components (x,y,z,w); \n\n// A rotation 30 degrees around the y-axis\nQuaternion rotation = Quaternion.Euler(0, 30, 0);\n```\n\n### Euler Angles\n```csharp\n// Euler angles are \"degree angles\" like 90, 180, 45, 30 degrees.\n// Quaternions differ from Euler angles in that they represent a point on a Unit Sphere (the radius is 1 unit).\n\n// Create a quaternion that represents 30 degrees about X, 10 degrees about Y\nQuaternion rotation = Quaternion.Euler(30, 10, 0);\n\n// Using a Vector\nVector3 EulerRotation = new Vector3(30, 10, 0);\nQuaternion rotation = Quaternion.Euler(EulerRotation);\n\n// Convert a transform's Quaternion angles to Euler angles\nQuaternion quaternionAngles = transform.rotation;\nVector3 eulerAngles = quaternionAngles.eulerAngles;\n```\n\n## Movement \u0026 Rotation\n\n### Move Object\n#### Transform.Translate()\n```csharp\n// Moves the transform in the direction and distance of translation.\npublic void Translate(Vector3 translation);\npublic void Translate(Vector3 translation, Space relativeTo = Space.Self);\n\ntransform.Translate(Vector3.right * movementSpeed);\n```\n\n#### Vector3.MoveTowards()\n```csharp\n// Calculate a position between the points specified by current and target\n// Moving no farther than the distance specified by maxDistanceDelta\npublic static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta);\n\nVector3 targetPosition;\ntransform.position = Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime);\n```\n\n#### Vector3.Lerp()\n```csharp\n// Linearly interpolates between two points. Results in a smooth transition.\npublic static Vector3 Lerp(Vector3 startValue, Vector3 endValue, float interpolationRatio);\n\nVector3 targetPosition;\nfloat t = 0;\nt += Time.deltaTime * speed;\ntransform.position = Vector3.Lerp(transform.position, targetPosition, t);\n```\n\n#### Vector3.SmoothDamp()\n```csharp\n// Gradually changes a vector towards a desired goal over time.\n// The vector is smoothed by some spring-damper like function, which will never overshoot.\n// The most common use is for smoothing a follow camera.\npublic static Vector3 SmoothDamp(Vector3 current, Vector3 target, ref Vector3 currentVelocity, float smoothTime, float maxSpeed = Mathf.Infinity, float deltaTime = Time.deltaTime);\n\nfloat smoothTime = 1f;\nVector3 velocity;\nVector3 targetPosition = target.TransformPoint(new Vector3(0, 5, -10));\n// Smoothly move the camera towards that target position\ntransform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);\n```\n\n### Rotate Object\n#### Transform.rotation\n```csharp\n// A Quaternion stores the rotation of the Transform in world space.\n// Quaternions are based on complex numbers and don't suffer from gimbal lock.\n// Unity internally uses Quaternions to represent all rotations.\n\ntransform.rotation = new Quaternion(rotx, roty, rotz, rotw);\n```\n\n#### Transform.eulerAngles\n```csharp\n// Transform.eulerAngles represents rotation in world space. \n// It is important to understand that although you are providing X, Y, and Z rotation values to describe your rotation\n// those values are not stored in the rotation. Instead, the X, Y \u0026 Z values are converted to the Quaternion's internal format.\n\ntransform.eulerAngles = Vector3(rotx, roty, rotz);\n```\n\n#### Transform.Rotate()\n```csharp\n// Applies rotation around all the given axes.\npublic void Rotate(Vector3 eulers, Space relativeTo = Space.Self);\npublic void Rotate(float xAngle, float yAngle, float zAngle, Space relativeTo = Space.Self);\n\ntransform.Rotate(rotx, roty, rotz);\n```\n\n#### Transform.RotateAround()\n```csharp\n// Rotates the transform about axis passing through point in world coordinates by angle degrees.\npublic void RotateAround(Vector3 point, Vector3 axis, float angle);\n\n// Spin the object around the target at 20 degrees/second.\nTransform target;\ntransform.RotateAround(target.position, Vector3.up, 20 * Time.deltaTime);\n```\n\n#### Transform.LookAt()\n```csharp\n// Points the positive 'Z' (forward) side of an object at a position in world space.\npublic void LookAt(Transform target);\npublic void LookAt(Transform target, Vector3 worldUp = Vector3.up);\n\n// Rotate the object's forward vector to point at the target Transform.\nTransform target;\ntransform.LookAt(target);\n\n// Same as above, but setting the worldUp parameter to Vector3.left in this example turns the object on its side.\ntransform.LookAt(target, Vector3.left);\n```\n\n#### Quaternion.LookRotation()\n```csharp\n// Creates a rotation with the specified forward and upwards directions.\npublic static Quaternion LookRotation(Vector3 forward, Vector3 upwards = Vector3.up);\n\n// The following code rotates the object towards a target object.\nVector3 direction = target.position - transform.position;\nQuaternion rotation = Quaternion.LookRotation(direction);\ntransform.rotation = rotation;\n```\n\n#### Quaternion.FromToRotation()\n```csharp\n// Creates a rotation (a Quaternion) which rotates from fromDirection to toDirection.\npublic static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection);\n\n// Sets the rotation so that the transform's y-axis goes along the z-axis.\ntransform.rotation = Quaternion.FromToRotation(Vector3.up, transform.forward);\n```\n\n#### Quaternion.ToAngleAxis()\n```csharp\n// Converts a rotation to angle-axis representation (angles in degrees).\n// In other words, extracts the angle as well as the axis that this quaternion represents.\npublic void ToAngleAxis(out float angle, out Vector3 axis);\n\n// Extracts the angle - axis rotation from the transform rotation\nfloat angle = 0.0f;\nVector3 axis = Vector3.zero;\ntransform.rotation.ToAngleAxis(out angle, out axis);\n```\n\n## Physics\n### Raycast\n\n```csharp\nvoid FixedUpdate() {\n    // Bit shift the index of the layer (8) to get a bit mask\n    int layerMask = 1 \u003c\u003c 8;\n\n    // This would cast rays only against colliders in layer 8.\n    // But instead we want to collide against everything except layer 8. The ~ operator does this, it inverts a bitmask.\n    layerMask = ~layerMask;\n\n    RaycastHit hit;\n    // Does the ray intersect any objects excluding the player layer\n    if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, Mathf.Infinity, layerMask)) {\n        Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.forward) * hit.distance, Color.yellow);\n        Debug.Log(\"Did Hit\");\n    }\n}\n```\n\n### Collisions \u0026 Triggers\n\n\u003e For the complete guide with collision matrix, 2D events, and common patterns, see [Collisions \u0026 Triggers](docs/physics/collisions.md)\n\n#### Collision Events (Physics Response)\n\n```csharp\n// Called when collision begins\nvoid OnCollisionEnter(Collision collision)\n{\n    Debug.Log(\"Hit: \" + collision.gameObject.name);\n    \n    // Access collision details\n    Vector3 impactVelocity = collision.relativeVelocity;\n    ContactPoint contact = collision.GetContact(0);\n    Vector3 hitPoint = contact.point;\n}\n\n// Called every frame during collision\nvoid OnCollisionStay(Collision collision) { }\n\n// Called when collision ends\nvoid OnCollisionExit(Collision collision) { }\n```\n\n#### Trigger Events (No Physics Response)\n\n```csharp\n// Called when entering trigger (requires \"Is Trigger\" checked on collider)\nvoid OnTriggerEnter(Collider other)\n{\n    if (other.CompareTag(\"Player\"))\n    {\n        // Pickup item, enter zone, etc.\n        Destroy(gameObject);\n    }\n}\n\n// Called every frame while inside trigger\nvoid OnTriggerStay(Collider other) { }\n\n// Called when exiting trigger\nvoid OnTriggerExit(Collider other) { }\n```\n\n#### 2D Equivalents\n```csharp\nvoid OnCollisionEnter2D(Collision2D collision) { }\nvoid OnTriggerEnter2D(Collider2D other) { }\n// Also: OnCollisionStay2D, OnCollisionExit2D, OnTriggerStay2D, OnTriggerExit2D\n```\n\n#### Requirements\n- Both objects need a **Collider** (or Collider2D)\n- At least one object needs a **Rigidbody** (or Rigidbody2D)\n- For triggers: Check **\"Is Trigger\"** on at least one collider\n\n### Ignore Collision\n```csharp\n// Makes the collision detection system ignore all collisions between collider1 and collider2.\npublic static void IgnoreCollision(Collider collider1, Collider collider2, bool ignore = true);\n\n// Here we're disabling the collision detection between the colliders of ally and bullet objects.\nTransform bullet;\nTransform ally;\nPhysics.IgnoreCollision(bullet.GetComponent\u003cCollider\u003e(), ally.GetComponent\u003cCollider\u003e());\n```\n\n## Input\n\n### Keyboard\n\n```csharp\n// Returns true during the frame the user starts pressing down the key\nif (Input.GetKeyDown(KeyCode.Space)) {\n    Debug.Log(\"Space key was pressed\");\n}\n\n// Jump is also set to space in Input Manager\nif (Input.GetButtonDown(\"Jump\")) {\n    Debug.Log(\"Do something\");\n}\n```\n\n### Mouse\n\n```csharp\nif (Input.GetAxis(\"Mouse X\") \u003c 0) {\n    Debug.Log(\"Mouse moved left\");\n}\n\nif (Input.GetAxis(\"Mouse Y\") \u003e 0) {\n    Debug.Log(\"Mouse moved up\");\n}\n\nif (Input.GetMouseButtonDown(0)) {\n    Debug.Log(\"Pressed primary button.\");\n}\n\nif (Input.GetMouseButtonDown(1)) {\n    Debug.Log(\"Pressed secondary button.\");\n}\n\nif (Input.GetMouseButtonDown(2)) {\n    Debug.Log(\"Pressed middle click.\");\n}\n```\n\n### Touch\n```csharp\nif (Input.touchCount \u003e 0) {\n    touch = Input.GetTouch(0);\n\n    if (touch.phase == TouchPhase.Began) {\n        Debug.Log(\"Touch began\");\n    }\n\n    if (touch.phase == TouchPhase.Moved) {\n        Debug.Log(\"Touch moves\");\n    }\n\n    if (touch.phase == TouchPhase.Ended) {\n        Debug.Log(\"Touch ended\");\n    }\n}\n```\n\n### New Input System\n\nThe Input System package is the **standard for Unity 6** and recommended for all new projects. It provides flexible, multi-device input handling with runtime rebinding support.\n\n\u003e For the complete guide with all examples, see [New Input System](docs/input/new-input-system.md)\n\n#### Quick Setup\n```\nWindow \u003e Package Manager \u003e Unity Registry \u003e Input System \u003e Install\nEdit \u003e Project Settings \u003e Player \u003e Active Input Handling \u003e Input System Package (New)\n```\n\n#### Direct Device Access\n```csharp\nusing UnityEngine.InputSystem;\n\n// Keyboard\nif (Keyboard.current.spaceKey.wasPressedThisFrame) {\n    Debug.Log(\"Space pressed\");\n}\n\n// Mouse\nVector2 mousePos = Mouse.current.position.ReadValue();\nif (Mouse.current.leftButton.wasPressedThisFrame) {\n    Debug.Log(\"Left click at \" + mousePos);\n}\n\n// Gamepad (always check for null!)\nif (Gamepad.current != null) {\n    Vector2 leftStick = Gamepad.current.leftStick.ReadValue();\n    if (Gamepad.current.buttonSouth.wasPressedThisFrame) {\n        Debug.Log(\"A/Cross button pressed\");\n    }\n}\n```\n\n#### Using Input Actions (Recommended)\n```csharp\nusing UnityEngine;\nusing UnityEngine.InputSystem;\n\npublic class PlayerController : MonoBehaviour\n{\n    [SerializeField] private InputActionReference moveAction;\n    [SerializeField] private InputActionReference jumpAction;\n\n    void OnEnable()\n    {\n        moveAction.action.Enable();\n        jumpAction.action.Enable();\n        jumpAction.action.performed += OnJump;\n    }\n\n    void OnDisable()\n    {\n        jumpAction.action.performed -= OnJump;\n        moveAction.action.Disable();\n        jumpAction.action.Disable();\n    }\n\n    void Update()\n    {\n        Vector2 move = moveAction.action.ReadValue\u003cVector2\u003e();\n        transform.Translate(move.x * Time.deltaTime, 0, move.y * Time.deltaTime);\n    }\n\n    void OnJump(InputAction.CallbackContext context)\n    {\n        Debug.Log(\"Jump!\");\n    }\n}\n```\n\n## UI\n\n### Button\n\n```csharp\n// Button is used to handle user clicks and interactions.\n// Attach this script to a Button component to respond to button clicks.\n\nusing UnityEngine.UI;\n\nButton myButton = GetComponent\u003cButton\u003e();\nmyButton.onClick.AddListener(MyButtonClickHandler);\n\nvoid MyButtonClickHandler() {\n    Debug.Log(\"Button Clicked!\");\n}\n```\n\n### Slider\n```csharp\n// Slider is used for selecting a value within a range.\n// Attach this script to a Slider component to respond to value changes.\n\nusing UnityEngine.UI;\n\nSlider mySlider = GetComponent\u003cSlider\u003e();\nmySlider.onValueChanged.AddListener(MySliderValueChangedHandler);\n\nvoid MySliderValueChangedHandler(float value) {\n    Debug.Log(\"Slider Value: \" + value);\n}\n```\n\n## Audio\n\n### Basic Audio Play\n\n```csharp\npublic class PlayAudio : MonoBehaviour {\n    public AudioSource audioSource;\n\n    void Start() {\n        // Calling Play on an Audio Source that is already playing will make it start from the beginning\n        audioSource.Play();\n    }\n}\n```\n\n## Scripting\n\n### Coroutines\nCoroutines in Unity are a powerful feature that allows you to pause the execution of a function and resume it later. This is particularly useful for tasks that need to be spread over several frames, such as animations, waiting for a condition to be met, or handling asynchronous operations.\n\n#### Basic Coroutine Example\n```csharp\nusing UnityEngine;\nusing System.Collections;\n\npublic class CoroutineExample : MonoBehaviour {\n    void Start() {\n        // Start the coroutine\n        StartCoroutine(ExampleCoroutine());\n    }\n\n    IEnumerator ExampleCoroutine() {\n        Debug.Log(\"Coroutine started\");\n\n        // Wait for 2 seconds\n        yield return new WaitForSeconds(2);\n\n        Debug.Log(\"Coroutine resumed after 2 seconds\");\n    }\n}\n```\n\n#### Using Coroutines for Repeated Actions\nCoroutines can be used to perform repeated actions with a delay between each iteration.\n\n```csharp\nIEnumerator RepeatActionCoroutine() {\n    while (true) {\n        Debug.Log(\"Action performed\");\n        \n        // Wait for 1 second before repeating\n        yield return new WaitForSeconds(1);\n    }\n}\n\n// Start the coroutine\nStartCoroutine(RepeatActionCoroutine());\n```\n\n#### Waiting for a Condition\nCoroutines can also wait for a condition to be true before continuing execution.\n\n```csharp\nIEnumerator WaitForConditionCoroutine() {\n    Debug.Log(\"Waiting for condition...\");\n\n    // Wait until the condition is met\n    yield return new WaitUntil(() =\u003e SomeConditionIsTrue());\n\n    Debug.Log(\"Condition met, resuming coroutine\");\n}\n\nbool SomeConditionIsTrue() {\n    // Replace with your actual condition\n    return Time.time \u003e 5;\n}\n\n// Start the coroutine\nStartCoroutine(WaitForConditionCoroutine());\n```\n\n#### Using Coroutines with Unity Events\nCoroutines can be used to handle events over time, such as fading out a UI element.\n\n```csharp\nIEnumerator FadeOutCoroutine(CanvasGroup canvasGroup, float duration) {\n    float startAlpha = canvasGroup.alpha;\n    float rate = 1.0f / duration;\n    float progress = 0.0f;\n\n    while (progress \u003c 1.0f) {\n        canvasGroup.alpha = Mathf.Lerp(startAlpha, 0, progress);\n        progress += rate * Time.deltaTime;\n\n        yield return null; // Wait for the next frame\n    }\n\n    canvasGroup.alpha = 0;\n}\n\n// Usage\nCanvasGroup myCanvasGroup = GetComponent\u003cCanvasGroup\u003e();\nStartCoroutine(FadeOutCoroutine(myCanvasGroup, 2.0f));\n```\n\n#### Stopping Coroutines\nYou can stop a coroutine using `StopCoroutine()` or `StopAllCoroutines()`.\n\n```csharp\nCoroutine myCoroutine;\n\nvoid Start() {\n    myCoroutine = StartCoroutine(ExampleCoroutine());\n}\n\nvoid StopMyCoroutine() {\n    if (myCoroutine != null) {\n        StopCoroutine(myCoroutine);\n    }\n}\n\nvoid StopAllMyCoroutines() {\n    StopAllCoroutines();\n}\n```\n\n#### Important Notes\n- Coroutines are not threads. They run on the main thread and are subject to the same performance constraints.\n- Use `yield return null;` to wait for the next frame.\n- Use `yield return new WaitForSeconds(seconds);` to wait for a specific amount of time.\n- Use `yield return new WaitUntil(() =\u003e condition);` to wait until a condition is true.\n- Coroutines can be nested, and you can yield return other coroutines.\n\n### Event Systems\nUnity provides several ways to handle events in your games. Here are the main approaches:\n\n#### UnityEvents\nUnityEvents are serializable events that can be configured in the Inspector and used in scripts.\n\n```csharp\nusing UnityEngine;\nusing UnityEngine.Events;\n\n// Basic UnityEvent\npublic class BasicEventExample : MonoBehaviour {\n    // This will show up in the inspector\n    public UnityEvent onGameStart;\n    \n    void Start() {\n        // Invoke the event\n        onGameStart?.Invoke();\n    }\n}\n\n// UnityEvent with parameters\n[System.Serializable]\npublic class ScoreEvent : UnityEvent\u003cint\u003e { }\n\npublic class ParameterizedEventExample : MonoBehaviour {\n    public ScoreEvent onScoreChanged;\n    private int score = 0;\n\n    public void AddScore(int points) {\n        score += points;\n        onScoreChanged?.Invoke(score);\n    }\n}\n```\n\n#### C# Events and Delegates\nTraditional C# events provide a more code-based approach to event handling.\n\n\nDelegates are type-safe function pointers, and events are a way to broadcast messages to multiple listeners.\n\n```csharp\npublic class GameEvents : MonoBehaviour {\n    // Delegate definition\n    public delegate void GameStateHandler();\n    public delegate void ScoreHandler(int newScore);\n\n    // Event declaration\n    public static event GameStateHandler OnGameStart;\n    public static event GameStateHandler OnGameOver;\n    public static event ScoreHandler OnScoreChanged;\n\n    // Methods to trigger events\n    public static void TriggerGameStart() {\n        OnGameStart?.Invoke();\n    }\n\n    public static void TriggerGameOver() {\n        OnGameOver?.Invoke();\n    }\n\n    public static void TriggerScoreChanged(int newScore) {\n        OnScoreChanged?.Invoke(newScore);\n    }\n}\n\n// Example usage in another class\npublic class Player : MonoBehaviour {\n    void OnEnable() {\n        // Subscribe to events\n        GameEvents.OnGameStart += HandleGameStart;\n        GameEvents.OnGameOver += HandleGameOver;\n    }\n\n    void OnDisable() {\n        // Unsubscribe from events\n        GameEvents.OnGameStart -= HandleGameStart;\n        GameEvents.OnGameOver -= HandleGameOver;\n    }\n\n    private void HandleGameStart() {\n        Debug.Log(\"Game Started!\");\n    }\n\n    private void HandleGameOver() {\n        Debug.Log(\"Game Over!\");\n    }\n}\n```\n\n### Scriptable Objects\n```csharp\n// ScriptableObjects are data containers that you can use to save large amounts of data, independent of class instances.\n[CreateAssetMenu(fileName = \"NewData\", menuName = \"ScriptableObjects/Data\")]\npublic class Data : ScriptableObject {\n    public string dataName;\n    public int dataValue;\n}\n\n// Usage\nData myData = ScriptableObject.CreateInstance\u003cData\u003e();\n```\n\n### Custom Editor Scripts\n```csharp\n// Custom Editor scripts allow you to create custom inspectors and windows in the Unity Editor.\nusing UnityEditor;\nusing UnityEngine;\n\n[CustomEditor(typeof(MyComponent))]\npublic class MyComponentEditor : Editor {\n    public override void OnInspectorGUI() {\n        DrawDefaultInspector();\n\n        MyComponent myComponent = (MyComponent)target;\n        if (GUILayout.Button(\"Do Something\")) {\n            myComponent.DoSomething();\n        }\n    }\n}\n```\n\n### Async/Await\nAsync/await is a programming pattern that simplifies asynchronous programming. It allows you to write asynchronous code that looks and behaves like synchronous code. This is particularly useful for operations that might take time, such as:\n- Loading resources\n- Network requests\n- File operations\n- Scene loading\n\n#### Basic Structure\n```csharp\nusing UnityEngine;\nusing System.Threading.Tasks;\nusing System;\n\npublic class AsyncAwaitExample : MonoBehaviour\n{\n    // Basic async/await structure in Unity\n    private async void Start()\n    {\n        Debug.Log(\"Starting async operation\");\n        await Task.Delay(1000); // Wait for 1 second\n        Debug.Log(\"Async operation completed\");\n    }\n\n    // IMPORTANT: Unity's Update loop and MonoBehaviour methods must be void\n    // They cannot be async Task\n    private void Update() { }      // Correct\n    // private async Task Update() {} // Wrong!\n}\n```\n\n#### Loading Resources\n```csharp\n// Loading resources asynchronously with progress tracking\nprivate async Task\u003cTexture2D\u003e LoadTextureAsync()\n{\n    var resourcePath = \"Textures/MyTexture\";\n    var request = Resources.LoadAsync\u003cTexture2D\u003e(resourcePath);\n    \n    while (!request.isDone)\n    {\n        // Report progress\n        Debug.Log($\"Loading: {request.progress * 100}%\");\n        await Task.Yield(); // Let other operations continue\n    }\n\n    return request.asset as Texture2D;\n}\n```\n\n#### Web Requests\n```csharp\n// Making web requests with progress tracking\nprivate async Task\u003cstring\u003e FetchDataAsync(string url)\n{\n    using var request = UnityWebRequest.Get(url);\n    var operation = request.SendWebRequest();\n\n    while (!operation.isDone)\n    {\n        Debug.Log($\"Downloading: {request.downloadProgress * 100}%\");\n        await Task.Yield();\n    }\n\n    if (request.result != UnityWebRequest.Result.Success)\n        throw new Exception($\"Failed to fetch data: {request.error}\");\n\n    return request.downloadHandler.text;\n}\n```\n\n#### Scene Loading\n```csharp\n// Loading scenes asynchronously with progress tracking\nprivate async Task LoadSceneAsync(string sceneName)\n{\n    var operation = SceneManager.LoadSceneAsync(sceneName);\n    operation.allowSceneActivation = false; // Don't activate immediately\n\n    while (operation.progress \u003c 0.9f) // 0.9 is the progress before activation\n    {\n        Debug.Log($\"Loading scene: {operation.progress * 100}%\");\n        await Task.Yield();\n    }\n\n    Debug.Log(\"Scene ready to activate\");\n    operation.allowSceneActivation = true;\n}\n```\n\n#### Parallel Operations\n```csharp\n// Running multiple async operations in parallel\nprivate async Task LoadGameAssetsAsync()\n{\n    try\n    {\n        // Start multiple operations simultaneously\n        var textureTask = LoadTextureAsync();\n        var dataTask = FetchDataAsync(\"https://api.example.com/gamedata\");\n        var sceneTask = LoadSceneAsync(\"Level1\");\n\n        // Wait for all tasks to complete\n        await Task.WhenAll(textureTask, dataTask, sceneTask);\n        \n        // All assets are now loaded\n        Debug.Log(\"All assets loaded successfully\");\n    }\n    catch (Exception e)\n    {\n        Debug.LogError($\"Failed to load assets: {e.Message}\");\n    }\n}\n```\n\n#### Timeout Handling\n```csharp\n// Implementing timeout for async operations\nprivate async Task\u003cT\u003e WithTimeout\u003cT\u003e(Task\u003cT\u003e task, TimeSpan timeout)\n{\n    var timeoutTask = Task.Delay(timeout);\n    var completedTask = await Task.WhenAny(task, timeoutTask);\n    \n    if (completedTask == timeoutTask)\n        throw new TimeoutException(\"Operation timed out\");\n            \n    return await task; // Unwrap the result or propagate the exception\n}\n\n// Complete example using timeout handling\nprivate async Task InitializeGameAsync()\n{\n    try\n    {\n        // Show loading screen\n        ShowLoadingUI();\n\n        // Start multiple loading operations with timeout\n        var loadingTask = Task.WhenAll(\n            LoadTextureAsync(),\n            FetchDataAsync(\"https://api.example.com/gamedata\"),\n            LoadSceneAsync(\"MainLevel\")\n        );\n\n        // Wait for all operations with a 30-second timeout\n        await WithTimeout(loadingTask, TimeSpan.FromSeconds(30));\n\n        // Hide loading screen\n        HideLoadingUI();\n        Debug.Log(\"Game initialized successfully\");\n    }\n    catch (TimeoutException)\n    {\n        Debug.LogError(\"Game initialization timed out\");\n        ShowRetryButton();\n    }\n    catch (Exception e)\n    {\n        Debug.LogError($\"Failed to initialize game: {e.Message}\");\n        ShowErrorUI();\n    }\n}\n```\n\n#### Best Practices\nWhen using async/await in Unity, follow these best practices:\n\n1. Always handle exceptions in async methods\n2. Use Task.Yield() instead of Task.Delay() for frame-by-frame operations\n3. Remember that async void should only be used for event handlers and MonoBehaviour methods\n4. Use CancellationToken when possible to support cancellation\n5. Implement timeout handling for network operations\n6. Don't block the main thread with .Result or .Wait()\n7. Use Task.WhenAll for parallel operations\n\n## Design Patterns\n### Singleton\n\n```csharp\n// Define singleton class\npublic class SingletonClass: MonoBehaviour {\n    private static SingletonClass instance;\n\n    public static SingletonClass Instance { get { return instance; } }\n\n    private void Awake() {\n        if (instance != null \u0026\u0026 instance != this) {\n            Destroy(this.gameObject);\n        } else {\n            instance = this;\n        }\n    }\n\n    public void SomeFunction() {\n    }\n}\n\n// Use it in another class\npublic class AnotherClass: MonoBehaviour {\n\n    private void Awake() {\n       SingletonClass.Instance.SomeFunction();\n    }\n}\n```\n\n### Factory Pattern\n```csharp\n// Interface for the enemy\npublic interface IEnemy {\n    void Attack();\n    void TakeDamage(int damage);\n}\n\n// Concrete implementation of the enemy: Goblin\npublic class Goblin : IEnemy {\n    public void Attack() =\u003e Debug.Log(\"Goblin attacking!\");\n    public void TakeDamage(int damage) =\u003e Debug.Log($\"Goblin taking {damage} damage.\");\n}\n\n// Concrete implementation of the enemy: Orc\npublic class Orc : IEnemy {\n    public void Attack() =\u003e Debug.Log(\"Orc attacking!\");\n    public void TakeDamage(int damage) =\u003e Debug.Log($\"Orc taking {damage} damage.\");\n}\n\n// Factory interface for creating enemies\npublic interface IEnemyFactory {\n    IEnemy CreateEnemy();\n}\n\n// Concrete implementation of the factory: GoblinFactory\npublic class GoblinFactory : IEnemyFactory {\n    public IEnemy CreateEnemy() =\u003e new Goblin();\n}\n\n// Concrete implementation of the factory: OrcFactory\npublic class OrcFactory : IEnemyFactory {\n    public IEnemy CreateEnemy() =\u003e new Orc();\n}\n\n// Client class using the factory to create and interact with enemies\npublic class GameManager : MonoBehaviour {\n    private void Start() {\n        InteractWithEnemy(new GoblinFactory());\n        InteractWithEnemy(new OrcFactory());\n\n        // You can introduce new concrete implementations of IEnemy\n        // without modifying existing client code\n        // adhering to the open/closed principle of SOLID design \n    }\n\n    private void InteractWithEnemy(IEnemyFactory factory) {\n        IEnemy enemy = factory.CreateEnemy();\n\n        // Consistent interaction regardless of the enemy type\n        enemy.Attack();\n        enemy.TakeDamage(20);\n    }\n}\n```\n\n### Observer Pattern\n```csharp\n// Observer interface\npublic interface IObserver {\n    void UpdateObserver(string message);\n}\n\n// Concrete implementation of the observer\npublic class ConcreteObserver : IObserver {\n    private string name;\n\n    public ConcreteObserver(string name) {\n        this.name = name;\n    }\n\n    public void UpdateObserver(string message) {\n        Debug.Log($\"{name} received message: {message}\");\n    }\n}\n\n// Subject class\npublic class Subject {\n    private List\u003cIObserver\u003e observers = new List\u003cIObserver\u003e();\n\n    public void AddObserver(IObserver observer) {\n        observers.Add(observer);\n    }\n\n    public void RemoveObserver(IObserver observer) {\n        observers.Remove(observer);\n    }\n\n    public void NotifyObservers(string message) {\n        foreach (var observer in observers) {\n            observer.UpdateObserver(message);\n        }\n    }\n}\n\n// Example of usage\npublic class ObserverExample : MonoBehaviour {\n    private void Start() {\n        Subject subject = new Subject();\n\n        ConcreteObserver observer1 = new ConcreteObserver(\"Observer 1\");\n        ConcreteObserver observer2 = new ConcreteObserver(\"Observer 2\");\n\n        subject.AddObserver(observer1);\n        subject.AddObserver(observer2);\n\n        // Notify all observers\n        subject.NotifyObservers(\"Hello Observers!\");\n    }\n}\n\n```\n\n### Command Pattern\n```csharp\n// Command interface\npublic interface ICommand {\n    void Execute();\n}\n\n// Concrete command classes\npublic class MoveCommand : ICommand {\n    private Transform transform;\n    private Vector3 direction;\n    private float distance;\n\n    public MoveCommand(Transform transform, Vector3 direction, float distance) {\n        this.transform = transform;\n        this.direction = direction;\n        this.distance = distance;\n    }\n\n    public void Execute() {\n        transform.Translate(direction * distance);\n    }\n}\n\n// Invoker class\npublic class CommandInvoker {\n    private Stack\u003cICommand\u003e commandStack = new Stack\u003cICommand\u003e();\n\n    public void ExecuteCommand(ICommand command) {\n        commandStack.Push(command);\n        command.Execute();\n    }\n\n    public void Undo() {\n        if (commandStack.Count \u003e 0) {\n            var command = commandStack.Pop();\n            // Implement an undo method if necessary\n        }\n    }\n}\n\n// Usage\npublic class CommandUser : MonoBehaviour {\n    private CommandInvoker invoker = new CommandInvoker();\n\n    void Update() {\n        if (Input.GetKeyDown(KeyCode.UpArrow)) {\n            ICommand moveUp = new MoveCommand(transform, Vector3.up, 1.0f);\n            invoker.ExecuteCommand(moveUp);\n        }\n\n        // Add other directions and invoker.Undo() for undos\n    }\n}\n```\n\n### State Pattern\nThe State Pattern allows an object to alter its behavior when its internal state changes. It encapsulates state-specific behavior and makes state transitions explicit.\n\n#### Basic Example\n```csharp\n// State interface\npublic interface IState {\n    void Enter();\n    void Update();\n    void Exit();\n}\n\n// Example state implementation\npublic class IdleState : IState {\n    public void Enter() =\u003e Debug.Log(\"Entered Idle State\");\n    public void Update() =\u003e Debug.Log(\"Updating Idle State\");\n    public void Exit() =\u003e Debug.Log(\"Exited Idle State\");\n}\n\n// State machine that manages state transitions\npublic class StateMachine : MonoBehaviour {\n    private IState currentState;\n\n    public void ChangeState(IState newState) {\n        currentState?.Exit();\n        currentState = newState;\n        currentState?.Enter();\n    }\n\n    private void Update() {\n        currentState?.Update();\n    }\n}\n```\n\n#### Detailed Example - Game Onboarding System\nA complete example showing how to implement a game onboarding/tutorial system using the State Pattern. This implementation demonstrates how to:\n- Manage different tutorial states (movement, combat, inventory)\n- Handle state transitions\n- Track player progress through the tutorial\n\n👉 [View Full Implementation](Patterns/StatePattern/README.md)\n\n### Strategy Pattern\nThe Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. This pattern lets the algorithm vary independently from clients that use it.\n\n#### Basic Example\n```csharp\n// Strategy interface\npublic interface IStrategy {\n    void Execute();\n}\n\n// Example strategy implementation\npublic class AttackStrategy : IStrategy {\n    public void Execute() =\u003e Debug.Log(\"Performing attack!\");\n}\n\n// Context class that uses the strategy\npublic class Character : MonoBehaviour {\n    private IStrategy strategy;\n\n    public void SetStrategy(IStrategy newStrategy) {\n        strategy = newStrategy;\n    }\n\n    public void ExecuteStrategy() {\n        strategy?.Execute();\n    }\n}\n```\n\n#### Detailed Example - Combat System\nA complete example showing how to implement a flexible combat system using the Strategy Pattern. This implementation demonstrates how to:\n- Define different attack strategies (melee, ranged, area)\n- Switch between strategies at runtime\n- Encapsulate combat algorithms\n\n👉 [View Full Implementation](Patterns/StrategyPattern/README.md)\n\n### Object Pooling Pattern\n```csharp\nusing System.Collections.Generic;\nusing UnityEngine;\n\npublic class ObjectPool : MonoBehaviour\n{\n    [System.Serializable]\n    public class Pool\n    {\n        public string tag;\n        public GameObject prefab;\n        public int size;\n    }\n\n    public List\u003cPool\u003e pools;\n    public Dictionary\u003cstring, Queue\u003cGameObject\u003e\u003e poolDictionary;\n\n    private void Start()\n    {\n        poolDictionary = new Dictionary\u003cstring, Queue\u003cGameObject\u003e\u003e();\n\n        foreach (Pool pool in pools)\n        {\n            Queue\u003cGameObject\u003e objectPool = new Queue\u003cGameObject\u003e();\n\n            for (int i = 0; i \u003c pool.size; i++)\n            {\n                GameObject obj = Instantiate(pool.prefab);\n                obj.SetActive(false);\n                objectPool.Enqueue(obj);\n            }\n\n            poolDictionary.Add(pool.tag, objectPool);\n        }\n    }\n\n    public GameObject SpawnFromPool(string tag, Vector3 position, Quaternion rotation)\n    {\n        if (!poolDictionary.ContainsKey(tag))\n        {\n            Debug.LogWarning(\"Pool with tag \" + tag + \" doesn't exist.\");\n            return null;\n        }\n\n        GameObject objectToSpawn = poolDictionary[tag].Dequeue();\n\n        objectToSpawn.SetActive(true);\n        objectToSpawn.transform.position = position;\n        objectToSpawn.transform.rotation = rotation;\n\n        poolDictionary[tag].Enqueue(objectToSpawn);\n\n        return objectToSpawn;\n    }\n}\n\n// Usage example\npublic class GameManager : MonoBehaviour\n{\n    public ObjectPool objectPool;\n\n    private void Update()\n    {\n        if (Input.GetKeyDown(KeyCode.Space))\n        {\n            objectPool.SpawnFromPool(\"Bullet\", transform.position, Quaternion.identity);\n        }\n    }\n}\n```\n\n### Chain of Responsibility Pattern\nThe Chain of Responsibility pattern creates a chain of handler objects for a request. Each handler contains a reference to the next handler in the chain and decides either to handle the request or pass it to the next handler.\n\n#### Basic Example\n```csharp\n// Handler interface\npublic interface IHandler {\n    void SetNext(IHandler handler);\n    void HandleRequest(string request);\n}\n\n// Base handler class\npublic abstract class BaseHandler : IHandler {\n    protected IHandler nextHandler;\n\n    public void SetNext(IHandler handler) {\n        nextHandler = handler;\n    }\n\n    public virtual void HandleRequest(string request) {\n        if (nextHandler != null) {\n            nextHandler.HandleRequest(request);\n        }\n    }\n}\n\n// Concrete handlers\npublic class UIHandler : BaseHandler {\n    public override void HandleRequest(string request) {\n        if (request == \"UI_CLICK\") {\n            Debug.Log(\"UI Handler: Handling UI click\");\n        } else {\n            base.HandleRequest(request);\n        }\n    }\n}\n\npublic class GameplayHandler : BaseHandler {\n    public override void HandleRequest(string request) {\n        if (request == \"PLAYER_MOVE\") {\n            Debug.Log(\"Gameplay Handler: Handling player movement\");\n        } else {\n            base.HandleRequest(request);\n        }\n    }\n}\n\n// Usage\npublic class InputManager : MonoBehaviour {\n    private IHandler handlerChain;\n\n    private void Start() {\n        // Set up the chain\n        var uiHandler = new UIHandler();\n        var gameplayHandler = new GameplayHandler();\n        \n        uiHandler.SetNext(gameplayHandler);\n        handlerChain = uiHandler;\n    }\n\n    private void Update() {\n        // Example: Process different types of input\n        if (Input.GetMouseButtonDown(0)) {\n            handlerChain.HandleRequest(\"UI_CLICK\");\n        }\n        if (Input.GetKeyDown(KeyCode.W)) {\n            handlerChain.HandleRequest(\"PLAYER_MOVE\");\n        }\n    }\n}\n```\n\n#### Detailed Example - Input Handling System\nA complete example showing how to implement a robust input handling system using the Chain of Responsibility Pattern. This implementation demonstrates how to:\n- Handle different types of input (UI, gameplay, cutscenes)\n- Process input based on game state\n- Chain multiple handlers together\n\n👉 [View Full Implementation](Patterns/ChainOfResponsibility/README.md)\n\n## Shortcuts\n\n### Scene View Editing\n```\nQ - Pan tool\nW - Move tool\nE - Rotate tool\nR - Scale tool\nT - Rect tool\nY - Transform tool\n\nCTRL/CMD + Z - Undo\nCTRL/CMD + Y - Redo\nCTRL/CMD + S - Save\nCTRL/CMD + P - Play/Stop\nCTRL/CMD + SHIFT + P - Pause\n```\n\n### Scene View Navigation\n```\nAlt + Left Click - Orbit around scene view pivot\nAlt + Right Click - Zoom in/out\nMiddle Mouse - Orbit\nMiddle Mouse + Alt - Zoom\nF - Focus on selected object\nCTRL/CMD + ALT + F - Frame selected\nHold Right Click - Free look (FPS style)\n```\n\n### Hierarchy Management\n```\nCTRL/CMD + SHIFT + N - Create empty GameObject\nALT + SHIFT + N - Create empty child GameObject\nCTRL/CMD + D - Duplicate selected\nCTRL/CMD + ALT + F - Frame selected object\nF2 - Rename selected\nDelete - Delete selected\n```\n\n### Layout\n```\nCTRL/CMD + 1-5 - Switch between layouts\nSHIFT + Space - Toggle maximize current window\n```\n\n## Practical Use Cases\n\n### Check if object is on the ground\n\n```csharp\nRaycastHit hit;\n\n// Unlike this example, most of the time you should pass a layerMask as the last option to hit only to the ground\nif (Physics.Raycast(transform.position, Vector3.down, out hit, 0.5f)) {\n   Debug.log(\"Hit something below!\");\n}\n```\n\n### Get the transform of a Body Bone\n\n```csharp\nAnimator animator;\n\nTransform transform = animator.GetBoneTransform(HumanBodyBones.Head);\n```\n\n### Make object look at the camera\n\n```csharp\nvar camPosition = Camera.main.transform.position;\n\ntransform.rotation = Quaternion.LookRotation(transform.position - camPosition);\n```\n\n### Camera follow \u0026 orbit\n\n[Full example](docs/practical-use-cases/camera-follow-orbit.md) – smooth follow using `Vector3.SmoothDamp` while orbiting via yaw/pitch input.\n\n```csharp\n// Accumulate yaw/pitch input\nyaw += lookInput.x * orbitSpeed * Time.deltaTime;\npitch = Mathf.Clamp(pitch - lookInput.y * orbitSpeed * Time.deltaTime, pitchLimits.x, pitchLimits.y);\n\n// Build rotation and place camera\nQuaternion rotation = Quaternion.AngleAxis(yaw, Vector3.up) * Quaternion.AngleAxis(pitch, Vector3.right);\nVector3 desiredPosition = target.position + rotation * followOffset;\ntransform.position = Vector3.SmoothDamp(transform.position, desiredPosition, ref velocity, followSmoothTime);\ntransform.rotation = Quaternion.LookRotation(target.position - transform.position, Vector3.up);\n```\n\n### Fade UI element\n\n[Full example](docs/practical-use-cases/fade-ui-element.md) – coroutine-driven `CanvasGroup` fade for prompts and HUD panels.\n\n```csharp\nIEnumerator Fade(CanvasGroup group, float targetAlpha, float duration)\n{\n    float start = group.alpha;\n    float time = 0f;\n    while (time \u003c duration)\n    {\n        time += Time.unscaledDeltaTime;\n        group.alpha = Mathf.Lerp(start, targetAlpha, time / duration);\n        yield return null;\n    }\n    group.alpha = targetAlpha;\n}\n```\n\n### Load next scene\n\n```csharp\nvar nextSceneToLoad = SceneManager.GetActiveScene().buildIndex + 1;\nvar totalSceneCount = SceneManager.sceneCountInBuildSettings;\n\nif (nextSceneToLoad \u003c totalSceneCount) {\n  SceneManager.LoadScene(nextSceneToLoad);\n}\n```\n\n## TBD (To Be Documented)\n\nThe following topics are planned to be added to the documentation:\n\n### Scripting\n- [ ] More advanced scripting topics coming soon\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/images/longhorn-logo.png\" alt=\"\" width=\"120\"\u003e\n  \u003cp\u003e\u003cem\u003eBuilt with ❤️ by \u003ca href=\"https://longhorn.games/\"\u003eLonghorn Games\u003c/a\u003e\u003c/em\u003e\u003c/p\u003e\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fozankasikci%2Funity-cheat-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fozankasikci%2Funity-cheat-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fozankasikci%2Funity-cheat-sheet/lists"}