2012-01-21 17 views
17

Esta es una pregunta de Unity3d in C#. El objetivo es crear un objeto tal que pueda pasar una URL y recibir datos a través del GET, un objeto que yo crearía sería un contenedor para la lógica WWW. También me gustaría un objeto 'POST' también, donde podría proporcionar una url y un 'Diccionario' de pares clave-valor como las argumentaciones posteriores. Taaan ... que en última instancia gustaría algo como esto:Unity GET/POST Wrapper

get_data = GET.request("http://www.someurl.com/somefile.php?somevariable=somevalue"); 

Y

post_data = POST.request("http://www.someurl.com/somefile.php", post) 
// Where post is a Dictionary of key-value pairs of my post arguments. 

para tratar de lograr esto, yo uso el objeto WWW. Ahora, para dar el tiempo de objeto WWW para descargar, necesitamos que esto suceda dentro de un objeto MonoBehaviour y yield los resultados. Así que me dio esto, que funciona:

public class main : MonoBehavior 
{ 
    IEnumerator Start() 
    { 
     WWW www = new WWW("http://www.someurl.com/blah.php?action=awesome_stuff"); 
     yield return www; 
     Debug.Log(www.text); 
    } 
} 

Lo que realmente quiero es éste:

public class main : MonoBehavior 
{ 
    IEnumerator Start() 
    { 
     GET request = new GET("http://www.someurl.com/blah.php?action=awesome_stuff"); 
     Debug.Log(request.get_data()); // Where get_data() returns the data (which will be text) from the request. 
    } 
} 

ahora tengo el script principal unido a la única GameObject en la jerarquía (denominado raíz). ¿Debo tener también el script GET adjunto a la raíz GameObject? ¿Puedo hacer eso dinámicamente desde main?

En última instancia, necesito una solución que me permita enviar fácilmente GET y POST solicitudes.

¡Salud!

Respuesta

17

Ah, lo tengo!

Mi problema era un malentendido de cómo funcionaban MonoBehaviour y Coroutines. La solución es muy simple.

En el editor, crea un GameObject vacío. Lo llamé DB.A continuación, adjunte la siguiente secuencia de comandos:

using System; 
using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 
class DB : MonoBehaviour 
{ 
    void Start() { } 

    public WWW GET(string url) 
    { 
     WWW www = new WWW(url); 
     StartCoroutine(WaitForRequest(www)); 
     return www; 
    } 

    public WWW POST(string url, Dictionary<string, string> post) 
    { 
     WWWForm form = new WWWForm(); 
     foreach (KeyValuePair<String, String> post_arg in post) 
     { 
      form.AddField(post_arg.Key, post_arg.Value); 
     } 
     WWW www = new WWW(url, form); 

     StartCoroutine(WaitForRequest(www)); 
     return www; 
    } 

    private IEnumerator WaitForRequest(WWW www) 
    { 
     yield return www; 

     // check for errors 
     if (www.error == null) 
     { 
      Debug.Log("WWW Ok!: " + www.text); 
     } 
     else 
     { 
      Debug.Log("WWW Error: " + www.error); 
     } 
    } 
} 

Luego, en la función de inicio de su script principal, ¡puede hacerlo!

private DB db; 
void Start() 
{ 
    db = GameObject.Find("DB").GetComponentInChildren<DB>(); 
    results = db.GET("http://www.somesite.com/someAPI.php?someaction=AWESOME"); 
    Debug.Log(results.text); 
} 

¡No he probado las solicitudes de POST, pero ahora toda la lógica está lista! Envíe solicitudes HTTP a su deseo de corazones, ¡aplausos!

+1

El gran problema al usar el método FIND es que tendrás un gran impacto en el rendimiento de tu juego .... tratando de encontrar un objeto del juego .... mira un buen enlace sobre cómo trabajar con los delegados http: // www .unifycommunity.com/wiki/index.php? title = CSharpMessenger_Extended –

+0

Absolutamente correcto. Idealmente, debería hacer un seguimiento del objeto a través de la variable de referencia y aferrarse a él para que solo necesite hacer eso una vez. O si un objeto de juego en la escena usa este envoltorio, podría tener una var pública a la que se le podría asignar el DB GO en el editor de Unity, ¡entonces no necesita encontrar nada! – PandemoniumSyndicate

+2

No creo que esto funcione realmente. Cuando lo esté haciendo: StartCoroutine (WaitForRequest (request)) Debug.Log (request.text) Si la solicitud aún no se ha realizado, la coroutine se detendrá, no la función real. Se llamará a Debug.Log (request.text) antes de que finalice la solicitud. –

2

¿Qué es ese script GET al que te refieres? La clase WWW le permite recuperar datos GET muy bien, la información que necesita se encuentra en la propiedad de texto del objeto WWW instanciado. Aquí está la documentación:

http://unity3d.com/support/documentation/ScriptReference/WWW-text.html http://unity3d.com/support/documentation/ScriptReference/WWW.html

Todo lo que tiene que hacer es dar el objeto WWW, como se está haciendo en este momento, y luego lea cualquiera de las propiedades que le interesan, simple y llanamente, sin necesidad de clases adicionales.

Como para el envío de un objeto POST, eso es lo que la clase WWWForm es para:

http://unity3d.com/support/documentation/ScriptReference/WWWForm.html

En resumen, que acaba de crear un objeto WWWForm, agregar campos a través AddField(), y luego simplemente construir un nuevo objeto WWW con la URL POST & el objeto anterior, eso es todo. Ceda el objeto WWW y una vez que regrese, sus datos han sido enviados. Las respuestas son, nuevamente, en los errores de propiedad de texto & en el campo correspondiente. Normal, limpio & simple.

HTH!

+0

Lo sentimos, el objeto GET es una clase que completa la lógica de WWW. La ventaja es que todo lo que necesito hacer es proporcionar una URL y recibir una salida. No estoy seguro si eso es posible dada la unidad, sin embargo. Voy a editar mi pregunta. – PandemoniumSyndicate

0

Aquí está el código de @ pandemoniumsyndicate modificado para agregar una devolución de llamada. El código original no es completamente correcto, ya que las funciones GET y POST se cerrarán inmediatamente después de llamar a coroutine. En ese momento, es probable que la solicitud WWW aún no se haya completado y acceder a cualquier campo excepto (www.isDone) no tiene sentido.

El siguiente código define un delegado, WWWRequestFinished, que se invocará cuando la solicitud finalice con el resultado de la solicitud y los datos recibidos, si los hay.

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

public class WWWRequestor : MonoBehaviour 
{ 

    Dictionary<WWW, object> mRequestData = new Dictionary<WWW, object>(); 
    public delegate void WWWRequestFinished(string pSuccess, string pData); 

    void Start() { } 

    public WWW GET(string url, WWWRequestFinished pDelegate) 
    { 
     WWW aWww = new WWW(url); 
     mRequestData[aWww] = pDelegate; 

     StartCoroutine(WaitForRequest(aWww)); 
     return aWww; 
    } 

    public WWW POST(string url, Dictionary<string, string> post, WWWRequestFinished pDelegate) 
    { 
     WWWForm aForm = new WWWForm(); 
     foreach (KeyValuePair<String, String> post_arg in post) 
     { 
      aForm.AddField(post_arg.Key, post_arg.Value); 
     } 
     WWW aWww = new WWW(url, aForm); 

     mRequestData[aWww] = pDelegate; 
     StartCoroutine(WaitForRequest(aWww)); 
     return aWww; 
    } 

    private IEnumerator WaitForRequest(WWW pWww) 
    { 
     yield return pWww; 

     // check for errors 
     string aSuccess = "success"; 
     if (pWww.error != null) 
     { 
      aSuccess = pWww.error; 
     } 

     WWWRequestFinished aDelegate = (WWWRequestFinished) mRequestData[pWww]; 
     aDelegate(aSuccess, pWww.text); 
     mRequestData.Remove(pWww); 
    } 

}