web-dev-qa-db-fra.com

Unity GET/POST Wrapper

Ceci est une question Unity3d en C #. L'objectif est de créer un objet tel que je puisse passer une URL et recevoir des données via GET, un objet que je créerais serait un wrapper pour la logique WWW. Je voudrais aussi un objet 'POST', où je pourrais fournir une URL et un 'Dictionnaire' de paires clé-valeur comme arguments de post. Sooo ... nous aimerions finalement quelque chose comme ceci:

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

ET

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

Pour essayer d'accomplir cela, j'utilise l'objet WWW. Maintenant, afin de donner à l'objet WWW le temps de télécharger, il faut que cela se passe dans un objet MonoBehaviour et yield les résultats. Donc, j'ai ce qui fonctionne:

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);
    }
}

Ce que je veux vraiment, c'est ceci:

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.   
    }
}

Maintenant, le script principal est associé à l'unique GameObject dans la hiérarchie (appelée racine). Dois-je également avoir le script GET attaché à la racine GameObject? Puis-je le faire dynamiquement à partir de main?

En fin de compte, j'ai besoin d'une solution qui me permette d'envoyer facilement des demandes GET et POST.

À votre santé!

17

Ah, j'ai compris!

Mon problème était une incompréhension du fonctionnement de MonoBehaviour et Coroutines. La solution est très simple.

Dans l'éditeur, créez un GameObject vide. Je l'ai nommé DB. Puis attachez-lui le script suivant:

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);
        }
    }
}

Ensuite, dans la fonction de démarrage de votre script principal, vous pouvez le faire!

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);
}

Nous n'avons pas testé les demandes POST, mais maintenant toute la logique est bouclée! Envoyer des demandes HTTP à votre coeur désir, acclamations!

17

Quel est le script GET auquel vous faites référence? La classe WWW vous permet de récupérer des données GET sans problème, les informations dont vous avez besoin se trouvent dans la propriété text de l'objet WWW instancié. Voici la documentation:

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

Tout ce que vous avez à faire est de renvoyer l'objet WWW, comme vous venez de le faire, puis de lire les propriétés qui vous intéressent, qu'elles soient claires ou simples, sans avoir besoin de classes supplémentaires.

En ce qui concerne l'envoi d'un objet POST, c'est à cela que sert la classe WWWForm:

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

En bref, vous créez simplement un objet WWWForm, vous y ajoutez des champs via AddField (), puis vous créez simplement un nouvel objet WWW avec l’URL POST & l’ancien objet, le tour est joué. Rendez l'objet WWW et une fois qu'il sera retourné, les données auront été soumises. Les réponses sont, encore une fois, dans la propriété du texte et les erreurs dans le champ correspondant. Simple, propre et simple.

HTH!

2
jmpp

Voici le code de @ pandemoniumsyndicate modifié pour ajouter un rappel. Le code d'origine n'est pas complètement correct car les fonctions GET et POST se fermeront immédiatement après l'appel de la coroutine. À ce moment, il est probable que la demande WWW n’est pas encore terminée et qu’il est impossible d’accéder à un champ autre que (www.isDone).

Le code suivant définit un délégué, WWWRequestFinished, qui sera appelé lorsque la demande sera terminée avec le résultat de la demande et les données reçues, le cas échéant.

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);
    }

}
0
questionman