Unity C#: Cómo usar ScriptableObjects para crear un sistema de armas modular
Cómo usar ScriptableObjects para crear un sistema de armas modular
Cuando nuestros proyectos en Unity comienzan a crecer, gestionar la información de los personajes, las armas o los ítems mediante variables públicas dentro de scripts de tipoMonoBehaviour se convierte en un dolor de cabeza. En este tutorial aprenderás a diseñar una arquitectura limpia, modular y fácil de mantener utilizando ScriptableObjects.- Qué es exactamente un ScriptableObject y por qué ahorra memoria RAM.
- Cómo crear datos de armas/personajes reusables directamente desde el menú de Unity.
- Cómo conectar datos y controladores para tener un código limpio y desacoplado.
1. Requisitos previos
- Unity 2021.3 LTS, 2022.3 LTS o superior (funciona en Unity 6 sin cambios).
- Conocimientos básicos de C# (variables, funciones y herencia).
2. ¿Qué es un ScriptableObject y por qué usarlo?
A diferencia de los scripts tradicionales que heredan de MonoBehaviour, los ScriptableObjects no necesitan estar adjuntos a un GameObject en la escena. Se guardan como archivos de activos (Assets) en la carpeta del proyecto.
Ventaja principal: Si tienes 100 enemigos del mismo tipo en pantalla, un MonoBehaviour duplicaría las estadísticas en memoria 100 veces. Con un ScriptableObject, los 100 enemigos leen los datos desde un único archivo centralizado.
3. Paso a Paso: Creación de la plantilla de datos
Primero, crearemos el script contenedor de los datos del arma. Crea un script en C# llamado WeaponData.cs y reemplaza su contenido por el siguiente:
using UnityEngine;
[CreateAssetMenu(fileName = "NewWeapon", menuName = "ScriptableObjects/WeaponData", order = 1)]
public class WeaponData : ScriptableObject
{
[Header("Información Básica")]
public string weaponName;
public Sprite icon;
[Header("Estadísticas de Combate")]
public float damage;
public float fireRate;
public int maxAmmo;
[Header("Efectos")]
public GameObject impactEffectPrefab;
public AudioClip shootSound;
}
¿Qué hace la etiqueta [CreateAssetMenu]? Permite crear instancias de estos datos haciendo clic derecho en la ventana Project de Unity: Right Click > Create > ScriptableObjects > WeaponData.
4. Leyendo los datos desde un GameObject
Ahora necesitamos que el jugador o un enemigo use estos datos. Crea un segundo script llamado WeaponHandler.cs y asígnalo al GameObject que disparará:
using UnityEngine;
public class WeaponHandler : MonoBehaviour
{
[SerializeField] private WeaponData currentWeapon;
private void Start()
{
EquipWeapon();
}
private void EquipWeapon()
{
if (currentWeapon != null)
{
Debug.Log($"Arma equipada: {currentWeapon.weaponName}");
Debug.Log($"Daño base: {currentWeapon.damage}");
}
else
{
Debug.LogWarning("¡No hay ningún ScriptableObject asignado al arma!");
}
}
public void Shoot()
{
// Lógica para disparar usando el sonido e impacto del ScriptableObject
if (currentWeapon.shootSound != null)
{
AudioSource.PlayClipAtPoint(currentWeapon.shootSound, transform.position);
}
}
}
5. Poniéndolo a prueba en Unity
- Guarda ambos scripts en tu proyecto de Unity.
- En la ventana Project, haz clic derecho en la carpeta de tu elección:
Create > ScriptableObjects > WeaponData. NómbraloEspada_MagicaoPistola_Laser. - Selecciona el archivo creado y configura sus valores en el **Inspector** (agrega un icono, ajusta el daño, asigna un sonido).
- Asigna este archivo en la ranura
Current Weapondel componenteWeaponHandleren tu jugador.
6. Conclusión
Al separar la información de las armas de la lógica de disparo, tu código queda completamente modular. Si deseas balancear el juego y modificar el daño del arma, no necesitas tocar scripts ni buscar GameObjects en la escena: simplemente editas el archivo ScriptableObject.
¿Tienes alguna duda sobre cómo implementar este patrón o integrarlo con un sistema de inventario? ¡Déjala en los comentarios abajo y con gusto te responderé!


Deja un comentario