Interfaces en Unity

Interfaces en Unity

Interfaces en Unity

 

Las interfaces te permiten añadir funcionalidades en cualquier clase que se implemente. De esta manera, puede asegurarse de que todas las clases no relacionadas se comporten de manera similar.

En este artículo aprenderás a crear interfaces en Unity, regulares, genéricas, e implementar-las en una clase.

Una interface en Unity, define un contrato. Cualquier class o struct que implemente ese contrato debe proporcionar una implementación de los miembros definidos en la interfaz.

Puede ser, que al leer esto, os recuerde a una clase abstracta, ya que las usamos para las mismas cosas, aun así hay algunas diferencias importantes.

Diferencias entre clases abstractas e interfaces

  • C# no permite la multiherencia, por lo que una clase solo puede heredar de otra clase, mientras que puede implementar todas las interfaces que quiera.
  • Las clases abstractas pueden contener código, mientras que las interfaces no. Aunque los métodos extensionales te permiten «hacer trampas» en este tema.
  • Es posible versionar una clase abstracta sin romper a otras clases que las implementen, pero no es posible hacer lo mismo con una interfaz. Añadir un método más, dejará de compilar, ya que es obligatorio implementar el método a todas las clases.
  • En las clases abstractas podemos indicar el modificador de acceso, mientras que en las interfaces no.

Imaginemos que nuestro jugador puede interactuar con ciertos objetos. Los objetos con los que queremos interaccionar tienen sus propios scripts con sus métodos de interactuar.

Ejemplo de la primera claseEjemplo de la segunda clase

Para acceder a los métodos podríamos utilizar el GetComponent para buscar la función interactuar en el script del objeto.

Función del código mal hecha

La función GetNearestGameObject() devuelve el objeto más cercano al jugador.

Hay un problema para extender nuestro código con este sistema. En este caso no hay problema, ya que son solo dos objetos, pero si tuviésemos muchísimos más, donde interactuásemos con más de 30 objetos, nuestro código se extendería muchísimo y no sería nada óptimo.

Aquí es donde emplearemos las interfaces.

Crear e implementar interfaces en Unity.

Para generar una interface, generaremos un nuevo script.cs, por defecto, se nos añaden las librerías de Unity, y la estructura de clase.

Eliminaremos la clase, y crearemos la interface con la siguiente sintaxis:

Interface en Unity

La nomenclatura estándar para las interfaces es añadiendo una I delante del nombre de la interface.

Esta interface tiene únicamente el método “Use”, que habrá que implementar en cada clase que se aplique.

Código añadiendo las interfaces en unity

Ahora ya no tenemos que preocuparnos de añadir cada una de las clases con cada uno de los métodos, ya que todas las clases con la interfaz van a incluir el método Use. El resultado será un código más limpio y estructurado:

Igual que lo podemos utilizar con objetos interactuables, se puede usar en muchas otros escenarios:

  • IDamageble (Clases que pueden recibir daño),
  • ICatchable (Coger objetos)
  • IConsumable (Método para pociones/comida)
  • ISellable (Objetos que se pueden vender)

En conclusión, las interfaces en Unity son muy importantes para nuestro desarrollo, os animo a que las probéis para mejorar el código.

Código del ejemplo:

PlayerInteraction.cs

if (Input.GetButtonDown("Fire1"))
{
    var nearestGameObject = GetNearestGameObject();
    if (nearestGameObject != null){
        var itemInteractuable = nearestGameObject.GetComponent<IInteractable>();
        if (itemInteractuable != null)
        {
            itemInteractuable.Use();
        }
    }
}

private GameObject GetNearestGameObject()
{
    GameObject result = null;
    var ray = _camera.ScreenPointToRay(Input.mousePosition);
    if (Physics.Raycast(ray, out var hit, 3))
    {
        result = hit.transform.gameObject;
    }
    return result;
}

ObjetoInteractuable.cs

public class luzCambiar : MonoBehaviour, IInteractable
{
    [SerializeField] private List<Light> luces;
    private bool _isEnabled = true;
    public void cambiar()
    {
        _isEnabled = !_isEnabled;
        foreach (var aLight in luces)
        {
            aLight.enabled = _isEnabled;
        }
    }
    public void Use()
    {
        cambiar();
    }
}

Escribe un comentario