2012-01-21 18 views
17

Đây là câu hỏi Unity3d trong C#. Mục đích là tạo một đối tượng để tôi có thể chuyển vào một URL và nhận dữ liệu qua GET, một đối tượng mà tôi sẽ tạo ra sẽ là một trình bao bọc cho logic WWW. Tôi cũng sẽ thích một đối tượng 'POST', nơi tôi có thể cung cấp một url và một 'Từ điển' của các cặp khóa-giá trị như các đối số sau. Sooo ... chúng ta cuối cùng muốn một cái gì đó như thế này:Unity GET/POST Wrapper

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

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

Để thử và thực hiện điều này, tôi sử dụng các đối tượng WWW. Bây giờ, để cung cấp thời gian đối tượng WWW để tải xuống, chúng tôi cần phải có điều này xảy ra bên trong một đối tượng MonoBehaviouryield kết quả. Vì vậy, tôi nhận được điều này, mà làm việc:

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

Những gì tôi thực sự muốn là thế này:

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

Bây giờ tôi có kịch bản chính kèm theo đơn GameObject trong hệ thống phân cấp (gọi là root). Tôi có cần phải có tập lệnh GET được đính kèm vào thư mục gốc GameObject không? Tôi có thể làm điều đó động từ main không?

Cuối cùng, tôi cần một giải pháp cho phép tôi dễ dàng gửi yêu cầu GETPOST.

Chúc mừng!

Trả lời

17

Ah, OK!

Vấn đề của tôi là sự hiểu lầm về cách MonoBehaviour và Coroutines hoạt động. Giải pháp này rất đơn giản.

Trong trình chỉnh sửa, tạo một GameObject trống. Tôi đặt tên nó là DB.Sau đó đính kèm tập lệnh sau vào nó:

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

Sau đó, trong chức năng bắt đầu của tập lệnh chính, bạn có thể thực hiện việc này!

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

Chưa thử nghiệm yêu cầu POST, nhưng bây giờ tất cả logic được gói gọn! Gửi yêu cầu HTTP đến trái tim của bạn mong muốn, cổ vũ!

+1

vấn đề lớn mặc dù trong sử dụng phương pháp FIND là bạn sẽ có một hit lớn về hiệu suất trò chơi của bạn .... cố gắng tìm một đối tượng trò chơi .... kiểm tra liên kết tốt đẹp về cách làm việc với các đại biểu http: // www .unifycommunity.com/wiki/index.php? title = CSharpMessenger_Extended –

+0

Hoàn toàn chính xác. Lý tưởng nhất là bạn sẽ theo dõi đối tượng thông qua biến tham chiếu và treo vào nó để bạn chỉ cần thực hiện điều đó một lần. Hoặc nếu một trò chơi trong cảnh đang sử dụng trình bao bọc này, bạn có thể có một var công khai có thể được chỉ định DB GO trong trình chỉnh sửa Thống nhất, sau đó bạn không cần tìm bất kỳ thứ gì! – PandemoniumSyndicate

+2

Tôi không nghĩ rằng điều này hoạt động thực sự. Khi bạn đang thực hiện: StartCoroutine (WaitForRequest (yêu cầu)) Debug.Log (request.text) Nếu yêu cầu chưa được thực hiện thì chỉ coroutine sẽ bị dừng, chứ không phải chức năng thực tế. Debug.Log (request.text) nào sẽ được gọi trước khi yêu cầu kết thúc. –

2

Kịch bản GET mà bạn đang đề cập là gì? Lớp WWW cho phép bạn truy xuất dữ liệu GET tốt, thông tin bạn cần nằm trong thuộc tính văn bản của đối tượng WWW được khởi tạo. Đây là tài liệu hướng dẫn:

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

Tất cả bạn cần làm là mang lại các đối tượng cá nhân, như bạn đang làm ngay bây giờ, và sau đó đọc bất kỳ thuộc tính nào bạn quan tâm, đơn giản và đơn giản, không cần thêm lớp học nào.

Đối với việc gửi một đối tượng POST, đó là những gì lớp WWWForm dành cho:

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

Nói tóm lại, bạn chỉ cần tạo một đối tượng WWWForm, thêm các trường để nó qua AddField(), và sau đó chỉ cần xây dựng một đối tượng WWW mới với POST URL & đối tượng cũ, đó là nó. Sử dụng đối tượng WWW và một khi nó trở lại, dữ liệu của bạn đã được gửi đi. Phản hồi, một lần nữa, trong thuộc tính văn bản & lỗi trong trường tương ứng. Đồng bằng, sạch & đơn giản.

HTH!

+0

Xin lỗi, đối tượng GET là lớp kết thúc logic của WWW. Lợi thế là tất cả những gì tôi cần làm là cung cấp một URL và nhận đầu ra. Tôi không chắc chắn nếu đó là có thể cho làm thế nào đoàn kết hoạt động tuy nhiên. Tôi sẽ chỉnh sửa câu hỏi của mình. – PandemoniumSyndicate

0

Đây là mã của @ pandemoniumsyndicate được sửa đổi để thêm một cuộc gọi lại. Mã gốc không hoàn toàn chính xác, vì các hàm GETPOST sẽ thoát ngay lập tức sau khi gọi coroutine. Vào thời điểm đó có khả năng yêu cầu WWW chưa hoàn tất và truy cập vào bất kỳ trường nào ngoại trừ (www.isDone) là vô nghĩa.

Mã sau xác định đại biểu, WWWRequestFinished, sẽ được gọi khi yêu cầu kết thúc với yêu cầu và dữ liệu nhận được, nếu có.

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

}