passing string from IEnumerator to void - c#

I'm trying to pass a string from an IEnumerator to a void. but the string keeps coming out null :( here is my code: I'm new to this so please help Thanks all.
my Void
public void ResisterButton ()
{
//checked Username
if (Username != "") {
StartCoroutine (CheackDBUN (Username));
Debug.LogWarning("User Data String in ResisterButton " + userDataString); // not work is empty :(
// do stuff with text eg turn bool UN = true
more code not to do with this
and the IEnumerator
IEnumerator CheackDBUN(string UsernamePost ){
WWWForm form = new WWWForm ();
form.AddField ("usernamePost", UsernamePost);
WWW userData = new WWW(checkUsernameURL, form);
yield return userData;
string userDataString = userData.text;
Debug.LogWarning("User Data String in CheackDBUN " + userDataString); //Working has text
yield return (userDataString);
}
the Mysql and php code is all working fine
Thanks hope that works if need to know more please ask

You have to wait for the coroutine to finish before using the userDataString result. Even though you are not changing userDataString in CheackDBUN (which i assume was your intention) you can still probably see that User Data String in ResisterButton is logged before User Data String in CheackDBUN.
You can use a callback delegate to tell the coroutine what to do with userDataString once it's finished.
public void ResisterButton ()
{
if (Username != "")
{
StartCoroutine(CheackDBUN(Username,
(userDataString) =>
{
Debug.LogWarning("User Data String in ResisterButton " + userDataString);
// do stuff with text eg turn bool UN = true
}
));
}
}
IEnumerator CheackDBUN(string UsernamePost, Action<string> callback){
WWWForm form = new WWWForm ();
form.AddField ("usernamePost", UsernamePost);
WWW userData = new WWW(checkUsernameURL, form);
yield return userData;
string userDataString = userData.text;
Debug.LogWarning("User Data String in CheackDBUN " + userDataString); //Working has text
callback(userDataString);
}

You need to make the void function accept a string like so:
public void ResisterButton (string str){
And then pass the user data string to it like this:
Debug.LogWarning("User Data String in CheackDBUN " + userDataString); //Working has text
ResisterButton(userDataString);
yield return (userDataString);

Related

Get the value from my Database (MySQL) and manipulate GameObjects automatically

Inside Unity I had prefabs, it calls "PropertyContainer" it filled with 2 text game object(Room_Type and Room_Qty) that I want to change it dynamically from my database. I had try to learn and watch any youtube tutorial and on the internet. After several weeks try searching and watching I still can't figure it out how to implementing into my code.
Below is my code that I got from several tutorial and some cases on the internet.
First code, is my php code that I used:
<?php
require 'Connection.php';
//Check Connection
if ($conn->connect_error){
die("Connection Failed: " . $conn->connect_error);
}
//Create Variable Submitted
$ID_Type = 2;
$sql = "SELECT Room_Type, Room_Qty FROM House WHERE ID_Type = '" . $ID_Type . "'";
$result = $conn->query($sql);
if ($result->num_rows > 0){
//Output data of each row.
$rows = array();
while ($row = $result->fetch_assoc()) {
$rows[] = $row;
}
//After the whole array is created.
echo json_encode($rows);
}else {
echo "Zero Result";
}
$conn->close();?>
It calls GetStockHouse_RoseType.php, After it is successfully to show my value to be a Json file then the next step I need to call it into my Unity. There are several code that I'm used in unity.
Second code, using C# it called Web.cs:
public IEnumerator GetPropertyStock(string ID_Type, Action<string> callback)
{
WWWForm form = new WWWForm();<br>
form.AddField("ID_Type", ID_Type);
using (UnityWebRequest www = UnityWebRequest.Get("http://localhost/xxxDB/GetStockHouse_RoseType.php"))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
//Show results as a text.
Debug.Log(www.downloadHandler.text);
string jsonArray = www.downloadHandler.text;
callback(jsonArray);
}
}
}
Third code, called Items.cs:
Action<string> _createItemsCallback;
// Use this for initialization
void Start () {
_createItemsCallback = (jsonArrayString) => {
StartCoroutine(CreateItemsRoutine(jsonArrayString));
};
CreateItems();
}
// Update is called once per frame
public void CreateItems() {
StartCoroutine(Main.Instance.Web.GetPropertyStock(_createItemsCallback));
}
IEnumerator CreateItemsRoutine(string jsonArrayString)
{
//Parsing json array string as an array
JSONArray jsonArray = JSON.Parse(jsonArrayString) as JSONArray;
for (int i = 0; i < jsonArray.Count; i++)
{
//Create local variables
bool isDone = false; //Are we done downloading?
string ID_Type = jsonArray[i].AsObject["ID_Type"];
JSONObject itemInfoJson = new JSONObject();
//Create a callback to get the information from Web.cs
Action<string> getItemInfoCallback = (itemInfo) =>
{
isDone = true;
JSONArray tempArray = JSON.Parse(itemInfo) as JSONArray;
itemInfoJson = tempArray[0].AsObject;
};
StartCoroutine(Main.Instance.Web.GetPropertyStock(ID_Type, getItemInfoCallback));
//Wait until the callback is called from the Web (info finished downloading).
yield return new WaitUntil(() => isDone == true);
//Instantiate GameObject (item prefab).
GameObject item = Instantiate(Resources.Load("Prefabs/PropertiContainer") as GameObject);
item.transform.SetParent(this.transform);
item.transform.localScale = Vector3.one;
item.transform.localPosition = Vector3.zero;
//Fill Information.
item.transform.Find("Room_Type").GetComponent<Text>().text = itemInfoJson["Room_Type"];
item.transform.Find("Room_Qty").GetComponent<Text>().text = itemInfoJson["Room_Qty"];
}
yield return null;
}
Fourth code, called Main.cs:
public static Main Instance;
public Web Web;
// Use this for initialization
void Start () {
Instance = this;
Web = GetComponent<Web>();
}
NOTES:The second and the fourth code is set in into one(1) Empty Object on Unity while the third code is set in the parents that called PropertyContainer.
Bellow is the picture from my Unity:
Picture No. 1) Main.cs & Web.cs set it into one Empty Object and also look oh my Game object for Room_Type and Room_Qty.
Main.cs & Web.cs
Item.cs
Unity File
What I expected is two (2) text Game Objects (Room_Type and Room_Qty) on PropertyContainer can change into my .php code. I hope all that information can fully understand.

Unity WWW webrequest not executing

I have a unity program that changes it content based on the data requested from a webserver. I wrote the following code to do the web-request.
public static string[] GetDBValues(int type, string[] data){
string base_url = "http://localhost/artez/onderzoeks_opdracht/interface_test/get_elements.php";
string typePrefix = "?type=";
string dataPrefix = "data[]=";
string uriString = base_url + typePrefix + type;
foreach (string dataElement in data){
uriString += "&" + dataPrefix + dataElement;
}
Debug.Log("executing url request");
UrlData(uriString);
return new string[] {"a"};
}
public static IEnumerator UrlData(string url){
Debug.Log("searching the web");
using (WWW www = new WWW(url)){
Debug.Log(www.text);
yield return www.text;
}
}
this code compiles and executes but i never see the following Debug.Log("searching the web") being logged. So i believe my code never executes the last part why is this happening?
I am a complete newb to c#.
If something is unclear let me know so i can clarify.
There are many issues in your code:
1.The UrlData function is a coroutine function. You have to use StartCoroutine to call it instead of calling it irectly like a normal function. So, UrlData(uriString); should be StartCoroutine(UrlData(uriString));
2.You have to yield or wait for the WWW request to finish before accessing the WWW.text property. That should be yield return www not yield return www.text.
public static IEnumerator UrlData(string url)
{
Debug.Log("searching the web");
using (WWW www = new WWW(url))
{
yield return www;
Debug.Log(www.text);
}
}
3.It looks like you want GetDBValues to return the result from the UrlData function. If this is true then just add Action as argument to the UrlData function so that you can use that to return the result.
Something like this:
public static IEnumerator UrlData(string url, Action<string> result)
{
Debug.Log("searching the web");
using (WWW www = new WWW(url))
{
yield return www;
if (result != null)
result(www.text);
}
}
then start it like below. The result is in the result variable:
StartCoroutine(UrlData("url", (result) =>
{
Debug.Log(result);
}));

You are using download over http. Currently Unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition, but it will be removed soon [duplicate]

This question already has an answer here:
You are using download over http. Currently Unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition
(1 answer)
Closed 4 years ago.
I am uploading data to database using WWW.
I have two data classes for data object.
[Serializable]
public class pushdatawrapper{
public string email;
public pushdata[] shotsArray=new pushdata[1];
}
[Serializable]
public class pushdata{
public string timehappened;
public string clubtype;
public pushdata(string timestamp_,string clubtype_)
{
timehappened = timestamp_;
clubtype = clubtype_;
}
}
Loading Json array of data object to database, I tried two approaches.
The first one was ok, but the second one is always failed at calling StartCoroutine function.
First approach
public class BLEBridge : MonoBehaviour {
void Start () {
pushdata_ pdata = new pushdata_("123123123123.0","15","123.0","123.0", "123.0", "123.0","123.0", "123.0","123.0","123.0","123.0","123.0", "First");
pushdatawrapper_ pw = new pushdatawrapper_ ();
pw.email = "test#gmail.com";
pw.shotsArray[0] = pdata;
StartCoroutine (PushData_ (pw));
}
private IEnumerator PushData_(pushdatawrapper_ pdata){
WWW www;
Hashtable postHeader = new Hashtable();
postHeader.Add("Content-Type", "application/json");
string dataToJason = JsonUtility.ToJson(pdata);
Debug.Log ("dataToJason " + dataToJason);
// convert json string to byte
var formData = System.Text.Encoding.UTF8.GetBytes(dataToJason);
www = new WWW("http://rmotion.rapsodo.com/api/push/new", formData, postHeader);
StartCoroutine(WaitForRequest(www));
return www;
}
IEnumerator WaitForRequest(WWW data)
{
yield return data; // Wait until the download is done
if (data.error != null)
{
Debug.Log("There was an error sending request: " + data.text);
}
else
{
Debug.Log("WWW Request: " + data.text);
}
}
}
This first method is always ok.
But in actual implementation, I need to upload data from a static function. Those private IEnumerator PushData_(pushdatawrapper_ pdata) and IEnumerator WaitForRequest(WWW data) can't be static.
So what I did was
I made a separate class as
public class UploadData: MonoBehaviour{
public void uploadindividualshot(pushdatawrapper pw){
StartCoroutine (PushData (pw));
}
private IEnumerator PushData(pushdatawrapper pdata){
WWW www;
Hashtable postHeader = new Hashtable();
postHeader.Add("Content-Type", "application/json");
string dataToJason = JsonUtility.ToJson(pdata);
Debug.Log ("dataToJason " + dataToJason);
// convert json string to byte
var formData = System.Text.Encoding.UTF8.GetBytes(dataToJason);
Debug.Log ("before www ");
www = new WWW("http://rmotion.rapsodo.com/api/push/new", formData, postHeader);
Debug.Log ("after new ");
StartCoroutine(WaitForRequest(www));
Debug.Log ("after WaitForRequest ");
return www;
}
IEnumerator WaitForRequest(WWW data)
{
Debug.Log ("start pushing ");
yield return data; // Wait until the download is done
if (data.error != null)
{
Debug.Log("There was an error sending request: " + data.text);
}
else
{
Debug.Log("WWW Request: " + data.text);
}
}
}
Then call the instance of the class from static method as
public class BLEBridge : MonoBehaviour {
void Start(){}
public unsafe static void GetGolfREsult()
{
pushdata pdata = new pushdata("123123123123.0","15","123.0","123.0", "123.0", "123.0","123.0", "123.0","123.0","123.0","123.0","123.0", "First");
pushdatawrapper pw = new pushdatawrapper();
pw.email = Login.loginName;
pw.shotsArray[0] = pdata;
UploadData up = new UploadData ();
up.uploadindividualshot (pw);
}
}
I always have error as
after new
UploadData:PushData(pushdatawrapper)
BLEBridge:GetGolfREsult()
(Filename: /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/DebugBindings.gen.cpp Line: 51)
libc++abi.dylib: terminating with uncaught exception of type Il2CppExceptionWrapper
2018-04-29 17:25:25.565292+0800 RMotion[270:7241] You are using download over http. Currently Unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition, but it will be removed soon. Please consider updating to https.
The program has error at StartCoroutine(WaitForRequest(www));
What is wrong with second approach?
In unity calling this line of code automatically start http request
WWW www = new WWW("url");
yield is just the convenience way to tell the coroutine to wait for the process to finish. Don't separate your calls in 2 IEnumerator.
private IEnumerator PushData_(pushdatawrapper_ pdata){
WWW www;
Hashtable postHeader = new Hashtable();
postHeader.Add("Content-Type", "application/json");
string dataToJason = JsonUtility.ToJson(pdata);
Debug.Log ("dataToJason " + dataToJason);
// convert json string to byte
var formData = System.Text.Encoding.UTF8.GetBytes(dataToJason);
www = new WWW("http://rmotion.rapsodo.com/api/push/new", formData, postHeader)
Debug.Log ("start pushing ");
yield return www; // Wait until the download is done
if (www.error != null)
{
Debug.Log("There was an error sending request: " + www.text);
}
else
{
Debug.Log("WWW Request: " + www.text);
}
}
And I don't see any use of pointer in your static method so why did you use the unsafe keyword?

Unable to receive data from PHP in unity

I have this script to interact with my database which is on mySql
string dataSubmitURL = "http://localhost/HighScore/AddScore.php?";
string dataGetURL = "http://localhost/HighScore/GetScore.php?";
// Use this for initialization
void Start () {
StartCoroutine(GetScores());
}
// Update is called once per frame
void Update () {
}
IEnumerator PostScores(string playerName, int score) {
string submitURL = dataSubmitURL + "name="+ playerName + "&score=" + score;
print(submitURL);
WWW submitData = new WWW(submitURL);
yield return submitData;
if (submitData.error != null)
{
Debug.LogError("Error occur when Submitting data : " + submitData.error);
Debug.LogError("Error occur when Submitting data : " + submitData.text);
Debug.LogError("Error occur when Submitting data : " + submitData.responseHeaders);
//submitData.text
}
else {
print(" Submitted");
}
IEnumerator GetScores() {
WWW getData = new WWW(dataGetURL);
yield return getData;
if (getData.error != null)
{
Debug.LogError("There was an error getting the high score: " + getData.error);
}
else {
print(getData.text);
}
}
}
But the problem is i am getting
There was an error getting the high score: Empty reply from server
Although these both urls
string dataSubmitURL = "http://localhost/HighScore/AddScore.php?";
string dataGetURL = "http://localhost/HighScore/GetScore.php?";
working fine in browser when i directly put it. I also added this crossDomain.xml in my root folder so that it can accessible to all. What I am doing wrong.
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
I don't know what was the problem all the code is correct and it works by changing the IP Address only.
string dataSubmitURL = "http://YouripAddress/HighScore/AddScore.php?";
string dataGetURL = "http://YouripAddress/HighScore/GetScore.php?";

Why is my StreamReader string empty when referenced outside of the containing class?

I'm using a StreamReader to fill a string up with data from a web response. This works just fine, and can be accessed inside the class. (WebResponseEventArgs) When I try to access it elsewhere however, it returns an empty string. Not null, just an empty string.
WebResponseEventArgs class:
public class WebResponseEventArgs : EventArgs
{
public WebAsync WebAsyncObject;
public string ErrorMessage;
public JArray ValidationErrors;
public JArray Data;
public string ResponseString;
public string Test;
public StreamReader reader;
public WebResponseEventArgs(WebAsync webAsync)
{
Test = "Hello!";
WebAsyncObject = webAsync;
Stream responseStream = WebAsyncObject.requestState.webResponse.GetResponseStream ();
reader = new StreamReader (responseStream);
ResponseString = reader.ReadToEnd ();
if(ResponseString != "")
{
try {
Debug.Log (ResponseString);
Data = JArray.Parse (ResponseString);
}
catch(JsonReaderException e)
{
Data = JArray.Parse ("[" + ResponseString + "]");
}
if(Data.Contains ("errors"))
{
ValidationErrors = (JArray) Data["errors"];
}
Debug.Log (Data[1]);
}
}
public bool HasErrors()
{
if(ErrorMessage != null)
{
return true;
}
else return false;
}
}
As you can see I'm logging the string in the debugger, and it shows me the complete response string, verifying that it does work inside this class. When the variable is called from anywhere else however, it returns an empty string. I spent the past 2 hours Googling and hoping someone else had stumbled upon this issue before, but I couldn't find anything.
Here is the event handler that tries to access the string:
public void OnGetAllResource(WebResponseEventArgs e)
{
//Check for errors
if(e.HasErrors())
{
Debug.Log (e.ErrorMessage);
return;
}
//Debug.Log (r);
//Test our resource inherited class
else
{
//string string2 = Shift.Instance.getAll ();
//string string3 = Shift.Instance.getAll ();
//Start composing our list
Debug.Log (e.Test);
Debug.Log (e.ResponseString);
Debug.Log(e.Test) works fine, Debug.Log(e.ResponseString) returns an empty string.
I hope someone can help me with this, it's been causing me a major headache :)

Categories