Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 15,00€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales
kingtrase

Crear Extensiones Mods Plugins para tus Juegos

Recommended Posts

Crear Plugins/Mods/Extensiones para tus juego de Unity

  • Hola a todos, Quería compartir con todos la forma de crear plugins para sus juegos una vez ya acabados. No me liare mucho ya que es algo complejo y necesitas tiempo.

    Lo primero tienen que saber que esto no es añadir el sistema y ale! magia! ya pueden crear cualquier plugin..., Ustedes tienen que crear despues una Api con acceso a vuestro juego para que se pueda expandir. (Este sistema solo lo he probado en windows, esta claro que un *.dll no funcionara en otro sistema), También decir que no explicare que son los delegados ni ninguna clase que utilize, para aprender a programar ya hay otros tutoriales.

Introducción:

Haré una pequeña introducción de cómo funciona para comprender lo que hay que hacer.

  1. Crearemos un .dll que se incluirá dentro de unity antes de compilar el juego. (Sera el que cargue los demás .dll, Este será nuestra API también)

  2. Añadiremos un script para que llamen a ese dll anterior en el juego.

  3. Haremos una pequeña compilación de una escena para que veamos como funciona.

  4. Por último crearemos un plugin para añadir al juego.

Creando la API y el cargador de plugins:

Usaremos Visual Studio (La versión no importa yo uso 2015), con el lenguaje de programación C#.

  • Creamos un nuevo proyecto con esta configuracion, ¡Recordar que los nombres son como vosotros querais, los mios seran orientativos, el nombre de los namespaces y los class y etc...!

Tambien decir que todas las explicaciones estaran por comentarios en codigo (asi no tengo que estar cambiando ventana entre esto y los programas)

1.png

  • Añadimos la referencia a la libreria de UnityEngine

Para añadir una referencia Menu Visual Studio->Project->Add reference...

La ruta de UnityEngine.dll: %Unity_Install_Path%\Editor\Data\Managed\UnityEngine.dll

2.png

Vale Ahora crearemos Otra clase: Llamada Loader dentro de un nombre de espacios llamado APILoader

using System;
using System.Reflection;

namespace APILoader
{
    public static class Loader
    {
    }
}

Esta clase sera para cargar los scripts, luego haremos la clase API, con funciones publicas para llamarlas desde los plugins creados.

using System;
using System.Reflection;
using System.IO;
using System.Collections.Generic;

namespace APILoader
{
    /*Dentro de cada plugin podra habra dos funciones obligatorias que seran llamadas al inicio del juego y en cada frame
     * igual que haces en unity en void Start y void Update, nosotros haremos lo mismo con nuestros plugins
     */
    public delegate void FunctionAtStart();//Creamos los delegados para añadir esas funciones y llamarlas cuando queramos.
    public delegate void FunctionAtUpdate();

    public static class Loader
    {
        public static FunctionAtStart callAtStart;//Instanciamos los delegados
        public static FunctionAtUpdate callAtUpdate;

        //Ruta de la carpeta donde guardaremos los plugins en este caso es: donde se ejecute el programa + \Plugins\
        public static string _PATH = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\Plugins\\";

        public static void LoadExternalAssembled()
        {
            foreach (var eAssemb in Directory.GetFiles(_PATH)) //Hacemos un bucle para cargar todos los plugins de la carpeta
                {
                    Assembly _current = Assembly.LoadFile(eAssemb);//Cargamos el plugin
                    Type _typeof = _current.GetType("Plugin.External"); //Donde Plugin es el nombre el namespace del plugin y 
                                                //external es la clase del plugin que cargaremos nosotros
                    
                    _typeof.GetMethod("load").Invoke(Activator.CreateInstance(_typeof), null);
           //Cargaremos la funcion load dentro del plugin, para que este se añada a los delegados y asi se ejecute segun corresponda
                }
        }

    }
}

Crearemos ahora otra clase llamada Functions dentro de un nombre de espacios llamado API

using System;
using UnityEngine;

namespace API
{
    class Functions
    {

    }
}

Aqui crearemos las funciones que el plugin podra usar.

Yo haré solo unas pocas para que veais el funcionamiento.

using System;
using System.Collections.Generic;
using UnityEngine;

namespace API
{
    public static class Functions
    {
        public static List<GameObject> reference;       //Imaginaros que quereis hacer que el jugador tenga funciones en api
                                                        //Lo añadiriamos desde unity aqui, para que cualquier plugin pueda hacerle
                                                        //referencia. (Hare una funcion como ejemplo)

        public static GameObject getReference(string name) //retornara el gameobject segun un nombre si existe en la lista.
        {
            return reference.Find(g => g.name == name);
        }

        public static void changeColorOfMaterial(GameObject go, Color newColor)
        {
            go.GetComponent<Renderer>().material.color = newColor;
            //Esta funcion la usaremos para buscar un objeto en la lista "reference" y cambiarle el color.

        }

        public static void IntegerPlusPlus(ref int i)
        {
            i++;
            //Esta funcion incrementa 1 a la variable que le pasemos, la llamaremos dentro del update del plugin para
            //que veamos como se ejecuta.
        }

        public static string sayHelloWord()
        {
            return @"Hello World from APi"; //Esta es sencilla, solo retorna ese string.
        }

    }
}

Como veis es sencillo, Ya tenemos creado el Loader y la API. ¡Facíl!

Preparando Unity:

Ahora en Unity crearemos una carpeta llamada Plugins No nos confundamos ahora, esta carpeta sera para los plugins de Unity, como el ultimo que hemos creado, pero nosotros queremos hacer Plugins para nuestro juego y crearlos despues de compilar.

Desde Visual Stuido compilaremos el proyecto antes creado, y lo arrastraremos a la carpeta que acabamos de crear, os tiene que quedar asi.

3.png

Ese archivo es el .dll que generamos con Visual Studio.

Ahora crearemos el script que cargar y ejecutara nuestros plugins. yo lo llamare pluginsLoader

Aqui el codigo.

using UnityEngine;
using APILoader; //AQUI ESTOY LLAMANDO AL DLL QUE HEMOS CREADO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

public class pluginsLoader : MonoBehaviour {
	void Awake () 
	{
		Loader.LoadExternalAssembled(); //Llamamos a nuestra funcion creada dentro del dll para que cargue los plugins.
	}
	void Start () {
		Loader.callAtStart(); //Aqui estamos llamando a las funciones de los plugins start.
	}
	void Update () {
		Loader.callAtUpdate(); //Aqui llamamos a las funciones de los plugins update.
	}
}

Y no tiene mas misterio!, Esto lo añadimos a un object de la escena y listo.

4.png

Ahora creamos Un objeto, en mi caso sera un cubo, para añadirlo a los objetos de referencia que pueden ser llamados desde la API (tendremos que modificar este ultimo script)

using UnityEngine;
using System.Collections.Generic;
using APILoader; //AQUI ESTOY LLAMANDO AL DLL QUE HEMOS CREADO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
using API;
public class pluginsLoader : MonoBehaviour {

	public GameObject[] prefabsToReference;

	void Awake () 
	{
		Loader.LoadExternalAssembled(); //Llamamos a nuestra funcion creada dentro del dll para que cargue los plugins.
		Functions.reference = new List<GameObject>();
		Functions.reference.AddRange(prefabsToReference); 
	}
	void Start () {
		Loader.callAtStart(); //Aqui estamos llamando a las funciones de los plugins start.
	}
	void Update () {
		Loader.callAtUpdate(); //Aqui llamamos a las funciones de los plugins update.
	}
}

Asi quedaria el script!

Ahora creamos nuestro cubo y lo añadimos al Array de GameObjects que hemos creado.

5.png

como el cubo se llama cubito, desde los plugins habra que buscar "cubito"

vale, Por la parte de Unity ya esta!, Ahora crearemos nuestro plugin. Primero compilaremos este proyecto.

6.png

Por un momento pense que no compilaria... ;)

Creando un Plugin Para el juego:

Lo primero que hay que hacer es: crear una carpeta dentro de: executable_Data\Managed\ llamada Plugins (para incluir nuestros plugins), executable_Data por que yo lo llame asi, cambiar segun el nombre que pusieron.

Asi deberia quedar:

7.png

Ahora volveremos a Visual Studio para hacer nuestro plugin.

Crearemos un nuevo Proyecto, igual que el anterior pero con otro nombre

8.png

Ahora pasare el codigo comentado para que vean como es, y FIN! (Veo que en vez de First puse Firs, menudo programador...)

Recordar tambien añadir al proyecto de plugin la referencia de UnityEngine, y del DLL que habiamos creado llamado API!

9.png

Aqui el codigo de nuestro plugin, como vereis este llama a las funciones de la API que habiamos creado.

using API;
using APILoader;
using UnityEngine;

namespace Plugin //Si recuerdan en el primer DLL para unity, dijimos que el nombre de espacios seria Plugin, y la clase External
{//Si ustedes quieren cambiar estos datos, para que el nombre de espacios sea otro, tambien tienen que cambiarlo en la DLL de API
    public class External
    {
        static int i;
        public static void load()//Esta funcion es llamada desde el juego.
        {
            APILoader.Loader.callAtStart += start; //Y aqui añadimos las funciones a los delegados de nuestra api para que puedan ser 
            APILoader.Loader.callAtUpdate += update;// llamadas a su momento.

        }
        static void start()//PONEMOS EN STATIC!!
        {
            API.Functions.changeColorOfMaterial(API.Functions.getReference("cubito"), Color.red);
            //Al comienzo de la escena, cambiara el color de cubito a rojo, si recordais, añadimos cubito a la referencia de objetos de la api
        }
        static void update()
        {
            i++;
            if(i>100)//Pasados 100 frames el cubo sera azul!
            API.Functions.changeColorOfMaterial(API.Functions.getReference("cubito"), Color.blue);
        }
    }
}

Una vez creado el DLL (compliado el plugin) lo añadiremos a la carpeta Plugins que hemos creado anteriormente.

 

Subire el Proyecto ya compilado para que veais que funciona -> https://mega.nz/#!kBYEnBJb

-Creo que soy el unico que no utiliza una pagina de publicidad en un link ;)

Si os da algun error, antes de preguntarme aqui en el post, podeis mirar si es esto:

  • Seleccion de diferente Framework en los DLL.
  • Error en algun nombre.
  • Error de seleccion de plataforma, en un sitio poneis para x64 en otro para x32 etc...

Un Saludo a todos y espero que os sirva de ayuda!

 

 

Share this post


Link to post
Share on other sites

Muchas gracias, lindo aporte, bien completo, al parecer es bastante sencillo usar plugins en Unity, te pregunto: por que usas los gameobjects referenciados cuando pones el componente PluginsLoader en un gameObject? osea, podrias usar directamente gameObject si quisieras (algo como "this.gameObject"), pregunto porq nunca trabaje con plugins.

Me gusto el plugin del ++ xD.

En que caso pensas que seria util e indispensable utilizar plugins?  se que se puede implementar plugins en C++ lo cual tiene como objetivo obvio mejorar sectores en los que la performance es un problema y no alcanza con c# y su garbage collector.

Share this post


Link to post
Share on other sites
hace 25 minutos, lightbug said:

Muchas gracias, lindo aporte, bien completo, al parecer es bastante sencillo usar plugins en Unity, te pregunto: por que usas los gameobjects referenciados cuando pones el componente PluginsLoader en un gameObject? osea, podrias usar directamente gameObject si quisieras (algo como "this.gameObject"), pregunto porq nunca trabaje con plugins.

Me gusto el plugin del ++ xD.

En que caso pensas que seria util e indispensable utilizar plugins?  se que se puede implementar plugins en C++ lo cual tiene como objetivo obvio mejorar sectores en los que la performance es un problema y no alcanza con c# y su garbage collector.

En realidad lo pongo como una forma sencilla para acceder a ellos, pero se pueden buscar igualmente con GameObject.Find realmente estos plugins son para extender el codigo y crear mejoras, los recursos seguiran siendo los mismos que tenias en el juego, (Se pueden añadir mas claro esta)

Imagina que tu juego es un RTS, si quieres añadir otra funcionalidad mas, como por ejemplo la formacion de las tropas, solamente implementas el codigo desde un plugin de este tipo, asi no tienes que rearmar el juego. o muchas cosas de este estilo.

Me alegra que te guste @lightbug, y gracias!

@lightbug para hacer lo de this.gameObject tendrias que hacer un script hijo de MonoBehaviour vamos el tipico que crea unity, y añadirlo a un gameobject de la escena, eso se podria hacer, puedes hacer cualquier cosa que quieras.

Share this post


Link to post
Share on other sites

×
×
  • Create New...