Saltar a contenido

Unity Cheatsheet

Unity - Game Development for Mobile

Unity es un potente motor de juegos multiplataforma utilizado para crear juegos y simulaciones en 2D, 3D, VR y AR. Esta hoja de referencia se enfoca en el desarrollo de juegos móviles con Unity.

Tabla de Contenidos

Would you like me to continue translating the rest of the document? I can proceed with the remaining sections if you confirm.```bash

Download Unity Hub from unity.com

Unity Hub manages Unity versions and projects

Install Unity version

Open Unity Hub -> Installs -> Add

Select desired Unity version (e.g., 2021.3 LTS)

Add modules: Android Build Support, iOS Build Support

Set environment variables (optional)

UNITY_HOME=/path/to/unity/version

PATH=\(PATH:\)UNITY_HOME/Editor

### Android Setup
```bash
# In Unity Hub, add Android Build Support module
# Unity will install required Android SDK & NDK

# Verify setup in Unity Editor
# Edit -> Preferences -> External Tools
# Check Android SDK, NDK, and JDK paths

# For custom SDK/NDK
# Download from developer.android.com
# Set paths in Unity Editor

iOS Setup (macOS only)

# In Unity Hub, add iOS Build Support module

# Install Xcode from Mac App Store
# Install Xcode Command Line Tools
xcode-select --install

# Install CocoaPods
sudo gem install cocoapods

# Verify setup in Unity Editor
# Edit -> Preferences -> External Tools
# Check Xcode path

Unity Editor

Main Windows

  • Scene View: Visual representation of the game world
  • Game View: Preview of the game as seen by the player
  • Hierarchy: List of all GameObjects in the current scene
  • Project: Browser for all assets in the project
  • Inspector: Properties of the selected GameObject or asset
  • Console: Displays logs, warnings, and errors

Keyboard Shortcuts

  • Q: Hand Tool (pan)
  • W: Move Tool
  • E: Rotate Tool
  • R: Scale Tool
  • T: Rect Tool (for UI)
  • Ctrl/Cmd + S: Save Scene
  • Ctrl/Cmd + P: Play/Pause Game
  • Ctrl/Cmd + Shift + P: Step Frame
  • F: Focus on selected object
  • Ctrl/Cmd + D: Duplicate selected object

Project Management

# Create new project
# Unity Hub -> Projects -> New
# Select template (2D, 3D, URP, HDRP)
# Enter project name and location

# Open existing project
# Unity Hub -> Projects -> Add
# Select project folder

# Upgrade project
# Open project in newer Unity version
# Unity will prompt for upgrade

Core Concepts

GameObject

  • The fundamental objects in Unity that represent characters, props, scenery, cameras, etc.
  • A container for Components.

Component

  • Functional pieces of a GameObject.
  • Examples: Transform, Mesh Renderer, Rigidbody, Collider, Scripts.

Transform Component

  • Every GameObject has a Transform component.
  • Defines the GameObject's position, rotation, and scale.

Scene

  • A container for a set of GameObjects.
  • Represents a level, a menu, or a part of the game.

Prefab

  • A reusable GameObject stored in the Project view.
  • Allows you to create, configure, and store a GameObject complete with all its components, property values, and child GameObjects as a reusable asset.

Asset

  • Any file used in a Unity project, such as models, textures, sounds, scripts, etc.

Scripting with C

Creating a Script

// In Project view, right-click -> Create -> C# Script
// Name the script (e.g., PlayerController)
// Attach script to a GameObject by dragging it to the Inspector

MonoBehaviour Lifecycle

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // Called when the script instance is being loaded
    void Awake()
    {
        Debug.Log("Awake called");
    }

    // Called on the frame when a script is enabled before any of the Update methods are called the first time
    void Start()
    {
        Debug.Log("Start called");
    }

    // Called every frame
    void Update()
    {
        // Game logic that needs to run every frame
    }

    // Called every fixed framerate frame
    void FixedUpdate()
    {
        // Physics calculations
    }

    // Called every frame, after all Update functions have been called
    void LateUpdate()
    {
        // Camera movement, etc.
    }

    // Called when the object becomes enabled and active
    void OnEnable()
    {
        Debug.Log("OnEnable called");
    }

    // Called when the object becomes disabled or inactive
    void OnDisable()
    {
        Debug.Log("OnDisable called");
    }

    // Called when the MonoBehaviour will be destroyed
    void OnDestroy()
    {
        Debug.Log("OnDestroy called");
    }
}

Accessing Components

// Get component on the same GameObject
Rigidbody rb = GetComponent<Rigidbody>();

// Get component on a child GameObject
Transform childTransform = GetComponentInChildren<Transform>();

// Get component on a parent GameObject
PlayerController parentController = GetComponentInParent<PlayerController>();

// Add component to GameObject
BoxCollider collider = gameObject.AddComponent<BoxCollider>();

// Find GameObject by name
GameObject player = GameObject.Find("Player");

// Find GameObject by tag
GameObject enemy = GameObject.FindWithTag("Enemy");

// Find all GameObjects with tag
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");

Input Handling

// Keyboard input
if (Input.GetKeyDown(KeyCode.Space))
{
    // Jump
}

if (Input.GetKey(KeyCode.A))
{
    // Move left
}

if (Input.GetKeyUp(KeyCode.LeftShift))
{
    // Stop sprinting
}

// Mouse input
if (Input.GetMouseButtonDown(0))
{
    // Left mouse button clicked
}

float mouseX = Input.GetAxis("Mouse X");
float mouseY = Input.GetAxis("Mouse Y");

// Touch input
if (Input.touchCount > 0)
{
    Touch touch = Input.GetTouch(0);

    if (touch.phase == TouchPhase.Began)
    {
        Debug.Log("Touch began");
    }

    if (touch.phase == TouchPhase.Moved)
    {
        Debug.Log("Touch moved");
    }

    if (touch.phase == TouchPhase.Ended)
    {
        Debug.Log("Touch ended");
    }
}

Coroutines

using System.Collections;
using UnityEngine;

public class CoroutineExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(Fade());
    }

    IEnumerator Fade()
    {
        Debug.Log("Coroutine started");

        // Wait for 2 seconds
        yield return new WaitForSeconds(2f);

        Debug.Log("After 2 seconds");

        // Wait for the end of the frame
        yield return new WaitForEndOfFrame();

        Debug.Log("End of frame");

        // Wait for another coroutine to finish
        yield return StartCoroutine(AnotherCoroutine());

        Debug.Log("Coroutine finished");
    }

    IEnumerator AnotherCoroutine()
    {
        Debug.Log("Another coroutine started");
        yield return new WaitForSeconds(1f);
        Debug.Log("Another coroutine finished");
    }

    // Stop a coroutine
    public void StopMyCoroutine()
    {
        StopCoroutine(Fade());
        StopAllCoroutines();
    }
}

Scene Management

using UnityEngine.SceneManagement;

// Load a scene by name
SceneManager.LoadScene("Level1");

// Load a scene by index
SceneManager.LoadScene(1);

// Load a scene asynchronously
StartCoroutine(LoadSceneAsync("Level2"));

IEnumerator LoadSceneAsync(string sceneName)
{
    AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);

    while (!asyncLoad.isDone)
    {
        float progress = Mathf.Clamp01(asyncLoad.progress / 0.9f);
        Debug.Log("Loading progress: " + (progress * 100) + "%");
        yield return null;
    }
}

// Get the current scene
Scene currentScene = SceneManager.GetActiveScene();
string sceneName = currentScene.name;

Physics

Rigidbody

  • Component that enables a GameObject to be affected by physics.
  • Rigidbody: For 3D physics.
  • Rigidbody2D: For 2D physics.
// Get Rigidbody component
Rigidbody rb = GetComponent<Rigidbody>();

// Add force
rb.AddForce(Vector3.forward * 10f, ForceMode.Impulse);

// Add torque (rotation)
rb.AddTorque(Vector3.up * 5f, ForceMode.Force);

// Set velocity
rb.velocity = new Vector3(0, 10, 0);

// Move position (for kinematic rigidbodies)
rb.MovePosition(transform.position + Vector3.forward * Time.deltaTime);

// Move rotation
rb.MoveRotation(transform.rotation * Quaternion.Euler(Vector3.up * 10f * Time.deltaTime));

Collider

  • Defines the shape of a GameObject for physical collisions.
  • BoxCollider, SphereCollider, CapsuleCollider, MeshCollider.
  • BoxCollider2D, CircleCollider2D, CapsuleCollider2D.

Collision Detection

// Called when this collider/rigidbody has begun touching another rigidbody/collider
void OnCollisionEnter(Collision collision)
{
    Debug.Log("Collision entered with: " + collision.gameObject.name);

    if (collision.gameObject.CompareTag("Enemy"))
    {
        // Take damage
    }
}

// Called once per frame for every collider/rigidbody that is touching another rigidbody/collider
void OnCollisionStay(Collision collision)
{
    Debug.Log("Collision staying with: " + collision.gameObject.name);
}

// Called when this collider/rigidbody has stopped touching another rigidbody/collider
void OnCollisionExit(Collision collision)
{
    Debug.Log("Collision exited with: " + collision.gameObject.name);
}

Trigger Detection

  • Colliders can be marked as "Is Trigger" to detect when objects enter their volume without causing a collision.
// Called when the Collider other enters the trigger
void OnTriggerEnter(Collider other)
{
    Debug.Log("Trigger entered by: " + other.gameObject.name);

    if (other.CompareTag("Player"))
    {
        // Collect item
    }
}

// Called once per frame for every Collider other that is touching the trigger
void OnTriggerStay(Collider other)
{
    Debug.Log("Trigger staying with: " + other.gameObject.name);
}

// Called when the Collider other has stopped touching the trigger
void OnTriggerExit(Collider other)
{
    Debug.Log("Trigger exited by: " + other.gameObject.name);
}

Raycasting

// Cast a ray from the camera to the mouse position
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;

if (Physics.Raycast(ray, out hit, 100f))
{
    Debug.Log("Ray hit: " + hit.collider.gameObject.name);
    Debug.Log("Hit point: " + hit.point);
}

// Cast a ray from a transform
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f))
{
    Debug.Log("Forward ray hit: " + hit.collider.gameObject.name);
}

// Raycast with layer mask
int layerMask = 1 << 8; // Layer 8
if (Physics.Raycast(transform.position, Vector3.down, out hit, 2f, layerMask))
{
    Debug.Log("Ground detected");
}

UI System

Canvas

  • The root element for all UI in a scene.
  • Render Mode: Screen Space - Overlay, Screen Space - Camera, World Space.

UI Components

  • Text: Displays text.
  • Image: Displays an image.
  • RawImage: Displays a texture.
  • Button: A clickable button.
  • Toggle: A checkbox.
  • Slider: A draggable slider.
  • Scrollbar: A scrollbar.
  • InputField: A text input field.
  • Panel: A container for other UI elements.
  • ScrollView: A scrollable view.

Rect Transform

  • The Transform component for UI elements.
  • Defines position, size, anchors, and pivot.

Event System

  • Handles input events for UI elements.
  • Requires an EventSystem GameObject in the scene.

Button Click Event

using UnityEngine.UI;

public Button myButton;

void Start()
{
    myButton.onClick.AddListener(OnButtonClick);
}

void OnButtonClick()
{
    Debug.Log("Button clicked!");
}

Accessing UI Components

using UnityEngine.UI;

public Text scoreText;
public Image healthBar;
public InputField nameInput;

void UpdateScore(int score)
{
    scoreText.text = "Score: " + score;
}

void UpdateHealth(float health)
{
    healthBar.fillAmount = health / 100f;
}

string GetPlayerName()
{
    return nameInput.text;
}

Animation

Animator Component

  • Controls animations on a GameObject.
  • Uses an Animator Controller asset to manage animation states.

Animator Controller

  • A state machine for animations.
  • States: Represent individual animations (e.g., Idle, Walk, Run, Jump).
  • Transitions: Define how to move between states.
  • Parameters: Variables that control transitions (e.g., Speed, IsJumping).

Animation Clips

  • Assets that contain animation data (e.g., keyframes for position, rotation, scale).

Controlling Animations from Script

Animator animator = GetComponent<Animator>();

// Set float parameter
animator.SetFloat("Speed", moveSpeed);

// Set bool parameter
animator.SetBool("IsJumping", true);

// Set trigger parameter
animator.SetTrigger("Attack");

// Get current animation state
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName("Attack"))
{
    // In attack animation
}

Animation Events

  • Call a function at a specific point in an animation clip.
  • Add an event in the Animation window.

// Function to be called by animation event
public void OnAttackAnimationEnd()
{
    Debug.Log("Attack animation finished");
}
```## Desarrollo Móvil
```csharp
#if UNITY_ANDROID
    // Android-specific code
#elif UNITY_IOS
    // iOS-specific code
#else
    // Code for other platforms (e.g., Editor)
#endif
```### Compilación Específica de Plataforma
```csharp
// Set screen orientation
Screen.orientation = ScreenOrientation.LandscapeLeft;

// Allow auto-rotation
Screen.autorotateToPortrait = true;
Screen.autorotateToLandscapeLeft = true;
Screen.autorotateToLandscapeRight = true;
Screen.autorotateToPortraitUpsideDown = false;
```### Orientación de Pantalla
```csharp
void Update()
{
    if (Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);

        switch (touch.phase)
        {
            case TouchPhase.Began:
                // Handle touch began
                break;

            case TouchPhase.Moved:
                // Handle touch moved
                Vector2 touchDeltaPosition = touch.deltaPosition;
                break;

            case TouchPhase.Ended:
                // Handle touch ended
                break;
        }
    }
}
```### Controles Táctiles
```csharp
// Get accelerometer data
Vector3 acceleration = Input.acceleration;

// Use accelerometer for movement
float moveHorizontal = acceleration.x;
float moveVertical = acceleration.y;
```### Acelerómetro
```csharp
// Enable gyroscope
Input.gyro.enabled = true;

// Get gyroscope data
Quaternion rotation = Input.gyro.attitude;
Vector3 rotationRate = Input.gyro.rotationRate;
```### Giroscopio
```csharp
// Vibrate device
Handheld.Vibrate();
```### Vibración del Dispositivo
```csharp
// PlayerPrefs for simple data storage
PlayerPrefs.SetInt("HighScore", 100);
PlayerPrefs.SetString("PlayerName", "John");
PlayerPrefs.SetFloat("Volume", 0.8f);

int highScore = PlayerPrefs.GetInt("HighScore", 0);
string playerName = PlayerPrefs.GetString("PlayerName", "Guest");
float volume = PlayerPrefs.GetFloat("Volume", 1.0f);

PlayerPrefs.Save();

// For complex data, use file I/O
string path = Application.persistentDataPath + "/save.dat";
File.WriteAllText(path, "My save data");
string saveData = File.ReadAllText(path);
```### Datos Persistentes
```csharp
public class ObjectPool : MonoBehaviour
{
    public GameObject objectToPool;
    public int amountToPool;
    private List<GameObject> pooledObjects;

    void Start()
    {
        pooledObjects = new List<GameObject>();
        for (int i = 0; i < amountToPool; i++)
        {
            GameObject obj = Instantiate(objectToPool);
            obj.SetActive(false);
            pooledObjects.Add(obj);
        }
    }

    public GameObject GetPooledObject()
    {
        for (int i = 0; i < pooledObjects.Count; i++)
        {
            if (!pooledObjects[i].activeInHierarchy)
            {
                return pooledObjects[i];
            }
        }
        return null;
    }
}
```## Optimización de Rendimiento

### Profiler
- Una herramienta para analizar y optimizar el rendimiento del juego.
- **Ventana -> Análisis -> Profiler**.
- **Uso de CPU**: Identificar cuellos de botella de rendimiento en scripts.
- **Uso de GPU**: Analizar el rendimiento de renderizado.
- **Memoria**: Rastrear asignaciones de memoria e identificar fugas de memoria.

### Agrupación
- **Agrupación Estática**: Para objetos no móviles que comparten el mismo material.
- **Agrupación Dinámica**: Para objetos pequeños móviles que comparten el mismo material.

### Culling
- **Culling de Frustum**: Habilitado automáticamente. Los objetos fuera de la vista de la cámara no se renderizan.
- **Culling de Oclusión**: Previene el renderizado de objetos ocultos detrás de otros objetos.

### Nivel de Detalle (LOD)
- Renderiza modelos con diferentes niveles de detalle según su distancia de la cámara.

### Compresión de Texturas
- Usar formatos de compresión de texturas apropiados para cada plataforma (por ejemplo, ASTC para Android/iOS).

### Agrupación de Objetos
- Reutilizar objetos en lugar de instanciarlos y destruirlos con frecuencia.
```csharp
// Load asset from Resources folder
Texture2D texture = Resources.Load<Texture2D>("Textures/my_texture");
GameObject prefab = Resources.Load<GameObject>("Prefabs/my_prefab");
```## Gestión de Recursos

### AssetBundles
- Archivos de recursos que pueden cargarse bajo demanda.
- Utilizados para contenido descargable (DLC) y reducir el tamaño inicial de la aplicación.

### Recursos Direccionables
- Un sistema para gestionar y cargar recursos por dirección.
- Simplifica la gestión y carga de recursos.

### Carpeta de Recursos
- Una carpeta especial donde los recursos pueden cargarse por nombre en tiempo de ejecución.
- No recomendado para proyectos grandes debido a implicaciones de rendimiento.
```csharp
// Log messages to the console
Debug.Log("This is a log message");
Debug.LogWarning("This is a warning");
Debug.LogError("This is an error");

// Draw debug lines in the Scene view
Debug.DrawLine(transform.position, transform.position + transform.forward * 10f, Color.red);
Debug.DrawRay(transform.position, transform.forward * 10f, Color.green);

// Assertions
Debug.Assert(condition, "Assertion failed");
```## Pruebas y Depuración

### Depuración
```csharp
// Edit Mode Test
using NUnit.Framework;

public class CalculatorTests
{
    [Test]
    public void Add_TwoNumbers_ReturnsSum()
    {
        var calculator = new Calculator();
        var result = calculator.Add(2, 3);
        Assert.AreEqual(5, result);
    }
}

// Play Mode Test
using System.Collections;
using NUnit.Framework;
using UnityEngine.TestTools;

public class PlayerTests
{
    [UnityTest]
    public IEnumerator Player_Jumps_ChangesYPosition()
    {
        var player = new GameObject().AddComponent<Player>();
        float initialY = player.transform.position.y;

        player.Jump();

        yield return new WaitForSeconds(0.5f);

        Assert.Greater(player.transform.position.y, initialY);
    }
}
```### Marco de Pruebas de Unity
- Un marco para escribir y ejecutar pruebas automatizadas en Unity.
- **Ventana -> General -> Test Runner**.
- **Pruebas de Modo Edición**: Se ejecutan en el Editor de Unity.
- **Pruebas de Modo Juego**: Se ejecutan mientras el juego está en ejecución.
```bash
# In Build Settings, switch to Android platform
# Connect Android device with USB debugging enabled
# Click "Build and Run"

# To create an APK
# Click "Build"
# Save the APK file

# To create an AAB (Android App Bundle)
# Check "Build App Bundle (Google Play)"
# Click "Build"
```## Implementación

### Configuración de Compilación
- **Archivo -> Configuración de Compilación**.
- Seleccionar plataforma de destino (Android, iOS).
- Agregar escenas a la compilación.
- Configurar ajustes del reproductor.

### Ajustes del Reproductor
- **Editar -> Configuración del Proyecto -> Reproductor**.
- **Nombre de la Empresa**, **Nombre del Producto**, **Versión**.
- **Ícono**, **Pantalla de Inicio**.
- **Identificador de Paquete** (por ejemplo, com.company.product).
- **Backend de Scripting** (Mono, IL2CPP).
- **Nivel de Compatibilidad de API**.

### Compilación para Android
```bash
# In Build Settings, switch to iOS platform
# Click "Build"
# This will generate an Xcode project

# Open the Xcode project
# In Xcode, set up signing and capabilities
# Select target device and run the app

# To create an archive for App Store
# In Xcode, Product -> Archive
```### Compilación para iOS (solo macOS)
Assets/ ├── _Project/ │ ├── Scenes/ │ ├── Scripts/ │ │ ├── Core/ │ │ ├── Gameplay/ │ │ └── UI/ │ ├── Prefabs/ │ ├── Materials/ │ ├── Textures/ │ ├── Animations/ │ └── Audio/ ├── Plugins/ ├── ThirdParty/ └── Resources/ ```## Mejores Prácticas

Organización del Proyecto

Awake### Prácticas de Codificación - Usar espacios de nombres para organizar código. - Seguir una convención de nomenclatura consistente (por ejemplo, PascalCase para clases, camelCase para variables). - Almacenar referencias de componentes en Starto GameObject.Find. - Evitar usar Updateen