- Home /
WWW data acquisition from remote server failing
I've started using LitJSON for my processing needs, and (quickly) built a Net Access layer to acquire data from a remote source. My Net Access Layer looks like this:
NET Access Layer
using UnityEngine;
using System;
using System.Collections;
using LitJson;
[Serializable]
public class ServerConnector : IDisposable
{
#region Variables / Properties
public string Address { get; private set; }
public bool AssetAcquired { get; private set; }
private WWW _payload;
#endregion Variables / Properties
#region Constructor
public ServerConnector(string address)
{
if(string.IsNullOrEmpty(address))
throw new ArgumentNullException("address");
Address = address;
DownloadPayload();
}
#endregion Constructor
#region Static Methods
public static T UnpackJSONFromSource< T >(string address)
{
if(string.IsNullOrEmpty(address))
throw new ArgumentNullException("address");
T result = default(T);
using(ServerConnector connector = new ServerConnector(address))
{
if(connector.AssetAcquired)
{
result = connector.UnpackJSON< T >();
}
}
return result;
}
#endregion Static Methods
#region Methods
public void Dispose()
{
if(_payload != null)
_payload = null;
}
public string GetTextData()
{
return _payload.text;
}
public T UnpackJSON< T >()
{
Debug.Log("Payload: " + _payload);
T result = JsonMapper.ToObject< T >(_payload.text);
return result;
}
private IEnumerator DownloadPayload()
{
_payload = new WWW(Address);
yield return _payload;
if(_payload == null)
{
Debug.LogError("Failed to get the payload.");
AssetAcquired = false;
return true;
}
if(_payload.error != null)
{
Debug.LogError("Error occurred during download from " + Address + ": " + _payload.error);
AssetAcquired = false;
}
else
{
AssetAcquired = true;
}
}
#endregion Methods
}
Naturally, to test that this is working correctly, I created a single game object in a scene, with the following behavior:
Test Behavior
using UnityEngine;
using System.Collections;
public class NetLayerTest : MonoBehaviour
{
#region Variables / Properties
private ServerConnector _connector;
private string _secretMessage = "The secret message was not found or acquired.";
#endregion Variables / Properties
void Start () {
_connector = new ServerConnector("http://andrewrgray.webs.com/dataz/test-data.json");
Debug.Log("Address for download: " + _connector.Address);
if(_connector.AssetAcquired)
_secretMessage = _connector.UnpackJSON();
Debug.Log(_secretMessage);
}
}
However, I notice whenever I start up in my test scene that I always get the Debug messages, "Failed to get the payload.", and "The secret message was not found or acquired." Long story short, my usage of WWW isn't getting any results!
I've made sure that the URL pointing to this JSON resource is correct (in fact, here it is), and that my usage of the WWW class in the Net Access layer is correct. I'm running my project in the editor, so I doubt that any interference from building as a webplayer is occurring (though, to rule that I out, I changed to a PC Any CPU build to be sure.)
Obviously, I am doing something totally wrong. The question is: what?
A note: This is my first time using WWW, so I made sure to consult the documentation first, and it did not yield enough information for me to discover the cause of the problem.
Have you tried just making a basic function using WWW to grab the raw resource? Does that work? If so, start adding back the other functionality.
Commented out the existing body of Start()
, changed it to an IEnumerator, then created just a basic body where I'm doing pretty much what ServerConnection.DownloadPayload()
is doing; successful result. So, WWW is working. $$anonymous$$y usage in this utility class is off, though.
Answer by AndrewGrayGames · Feb 13, 2013 at 04:32 AM
iwaldrop set me on the correct path; my problem was that as the MonoBehaviour wasn't working with the coroutines, nothing was working as intended. As such, I altered my setup as below:
ServerConnector Class
[Serializable]
public class ServerConnector : IDisposable
{
#region Variables / Properties
public string Address { get; private set; }
public bool AssetAcquired { get; private set; }
private WWW _payload;
#endregion Variables / Properties
#region Constructor
public ServerConnector(string address)
{
if(string.IsNullOrEmpty(address))
throw new ArgumentNullException("address");
Address = address;
}
#endregion Constructor
#region Methods
public void Dispose()
{
if(_payload != null)
_payload = null;
}
public string GetTextData()
{
return _payload.text;
}
public T UnpackJSON()
{
Debug.Log("Payload: " + _payload);
T result = JsonMapper.ToObject(_payload.text);
return result;
}
public IEnumerator DownloadPayload()
{
_payload = new WWW(Address);
yield return _payload;
if(_payload == null)
{
Debug.LogError("Failed to get the payload.");
AssetAcquired = false;
return true;
}
if(_payload.error != null)
{
Debug.LogError("Error occurred during download from " + Address + ": " + _payload.error);
AssetAcquired = false;
}
else
{
AssetAcquired = true;
}
}
#endregion Methods
}
Test Behavior
public class NetLayerTest : MonoBehaviour
{
#region Variables / Properties
public string URL = "http://andrewrgray.webs.com/dataz/test-data.json";
private ServerConnector _connector;
private string _secretMessage = "The secret message was not found or acquired.";
#endregion Variables / Properties
#region Methods
IEnumerator Start ()
{
_connector = new ServerConnector(URL);
yield return StartCoroutine(_connector.DownloadPayload());
if(_connector.AssetAcquired)
_secretMessage = _connector.GetTextData();
Debug.Log(_secretMessage);
}
#endregion Methods
}
While telling the utility class in the constructor who the calling MonoBehaviour is was a great idea, the problem is that the actual data access took 0.02s...longer than it took for the behavior to determine that the data had not been retrieved. It was impossible for me to get around moving the coroutine call to the actual behavior.
Once that happened, though, the rest fell into place!
Nice solution. I wouldn't say passing the calling $$anonymous$$onoBehaviour was a good idea, it was just a hack while I was also trying to solve some of my own problems! ;)
Answer by iwaldrop · Feb 13, 2013 at 03:00 AM
Try checking if (_payload.text == null) in your Coroutine.
"This is a test of the Net Layer Access system. If I can see this, I succeeded."
Works for me. ;)
@iwaldrop What line did you change to if(_payload.text == null)
? I've tried in a couple of places (Inside DownloadPayload()
, of course), but I'm not seeing quite where that's helping...
Ahh...I hadn't downloaded and tested your code, but now that I am it is apparent what's (not) happening. Since you haven't inherited from $$anonymous$$onoBehaviour your IEnumerator won't run.
Line 25, if your class was a $$anonymous$$onoBehaviour, should read:
StartCoroutine(DownloadPayload());
A way to test this this is to insert
Debug.Log (_payload.text);
on line 76. It never prints.
One quick hack to make it work; replace the following code;
public ServerConnector(string address, $$anonymous$$onoBehaviour layerTest)
{
if(string.IsNullOrEmpty(address))
throw new ArgumentNullException("address");
Address = address;
layerTest.StartCoroutine(DownloadPayload());
}
#endregion Constructor
#region Static $$anonymous$$ethods
public static T UnpackJSONFromSource< T >(string address)
{
if(string.IsNullOrEmpty(address))
throw new ArgumentNullException("address");
T result = default(T);
using(ServerConnector connector = new ServerConnector(address, null))
{
if(connector.AssetAcquired)
{
result = connector.UnpackJSON< T >();
}
}
return result;
}
And on your NetLayerTest;
_connector = new ServerConnector("http://andrewrgray.webs.com/dataz/test-data.json", this);
Your answer
Follow this Question
Related Questions
Problem Parsing Json (JsonUtility) 1 Answer
Integrating Watson Speech-to-Text with Unity 1 Answer
Multiple Cars not working 1 Answer
Retreive Jsonfile and Read It 0 Answers
Distribute terrain in zones 3 Answers