I'm trying to Load AssetBunddle form Android Folder from in Unity.
but it doesn't work...
I thought URL is wrong.
Changed URL many time, recommended or specification of Unity document but every case failed
Here is My Code.
public string BundleURL;
public int version;
void Start()
{
CleanCache();
BundleURL = "file://"+Application.persistentDataPath + " /BundleTest";
StartCoroutine(LoadAssetBundle(BundleURL));
version = 0;
}
I thought BundleURL is wrong or has problem
IEnumerator LoadAssetBundle(string BundleURL)
{
//BundleURL = "file://" + path ;
GameObject obj;
//ARLog.d ("LoadAssetBundle" + BundleURL);
while (!Caching.ready)
yield return null;
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, version))
{
yield return www;
AssetBundle bundle = www.assetBundle;
String[] mPath = bundle.GetAllAssetNames();
String bundleName = null;
if (bundleName != null)
{
AssetBundleRequest request = bundle.LoadAssetAsync(bundleName, typeof(GameObject));
yield return request;
obj = Instantiate(request.asset) as GameObject;
bundle.Unload(false);
www.Dispose();
}
}
}
}
I want Instance Model in my Scene(from BundelTest Folder in Androind)
You have an additional space there in
BundleURL = "file://"+Application.persistentDataPath + " /BundleTest";
in " /BundleTest"!
For paths in general you allways rather should use Path.Combine instead of manually concatenating strings:
BundleURL = Path.Combine(Application.persistentDataPath,"BundleTest");
this makes sure that in the resulting path automatically the correct path separator (/ or \) for the according atrget system is used.
Than note that WWW is obsolete and not that fast → you should have a look at AssetBundle.LoadFromFileAsync there is an example of how to use it
public void IEnumerator LoadBundle()
{
var bundleLoadRequest = AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, "BundleTest"));
yield return bundleLoadRequest;
var myLoadedAssetBundle = bundleLoadRequest.assetBundle;
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
var assetLoadRequest = myLoadedAssetBundle.LoadAssetAsync<GameObject>("MyObject");
yield return assetLoadRequest;
GameObject prefab = assetLoadRequest.asset as GameObject;
Instantiate(prefab);
myLoadedAssetBundle.Unload(false);
}
If you prefer synchronous loading checkout AssetBundle.LoadFromFile instead.
Another note in general: if you are using
using (WWW www = WWW.LoadFromCacheOrDownload(BundleURL, version))
{
....
}
you don't have to use Dispose as it is disposed at the and of the using block automatically.
Related
I am downloading assetBundle from server using UnityWebRequest and it is working good in unity editor but in andriod it gives null value can someone help
public IEnumerator DownloadAsset(string url, string assetName)
{
using (UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(url))
{
yield return www.SendWebRequest();
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(www);
if (bundle != null)
{
AGUIMisc.ShowToast("Not Null");
GameObject temp = bundle.LoadAsset(assetName) as GameObject;
var newobjj = Instantiate(temp);
newobjj.transform.parent = maleparent.transform;
}
else
{
AGUIMisc.ShowToast("Null");
}
}
}
Target-platform Android:
The AssetBundles need to be built in the target-platform where they are going to be used at later.
Since you want to use the AssetBundles in Android, the target-platform should also be Android when you build your AssetBundles.
Please also check:
You should set UnityWebRequest.downloadHandler first before call UnityWebRequest.SendWebRequest() to use DownloadHandlerAssetBundle.
public System.Collections.IEnumerator DownloadAsset(string url, string assetName)
{
using (var uwr = new UnityEngine.Networking.UnityWebRequest(url, UnityEngine.Networking.UnityWebRequest.kHttpVerbGET))
{
uwr.downloadHandler = new UnityEngine.Networking.DownloadHandlerAssetBundle(url, 0);
yield return uwr.SendWebRequest();
AssetBundle bundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(uwr);
if (bundle != null)
{
AGUIMisc.ShowToast("Not Null");
GameObject temp = bundle.LoadAsset<GameObject>(assetName);
var newobj = GameObject.Instantiate(temp);
newobj.transform.parent = maleparent.transform;
}
else
{
AGUIMisc.ShowToast("Null");
}
}
}
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.
I'm working on an iOS app on Unity. Eventually, the app should be able to download, import and load .obj files saved on my website server. But I'm currently developing locally so the files are saved in my laptop file system (local server side of my website).
My question is what I should use to access those files. I used WWW to access it but it seems not working. Please see my code below.
public void OnClick()
{
StartCoroutine(ImportObject());
}
IEnumerator ImportObject (){
Debug.Log("being called");
WWW www = new WWW("http://localhost:8080/src/server/uploads/user-id/file name");
Debug.Log("being called");
yield return www;
Debug.Log("NOT BEING CALLED !");
**//Everything below here seems not being called...**
if (string.IsNullOrEmpty(www.error)) {
Debug.Log("Download Error");
} else {
string write_path = Application.dataPath + "/Objects/";
System.IO.File.WriteAllBytes(write_path, www.bytes);
Debug.Log("Success!");
}
GameObject spawnedPrefab;
Mesh importedMesh = objImporter.ImportFile(Application.dataPath + "/Objects/");
spawnedPrefab = Instantiate(emptyPrefabWithMeshRenderer);
spawnedPrefab.transform.position = new Vector3(0, 0, 0);
spawnedPrefab.GetComponent<MeshFilter>().mesh = importedMesh;
}
I tried multiple solutions from the internet and finally find the correct method to download and save the file by using the code below:
IEnumerator DownloadFile(string url) {
var docName = url.Split('/').Last();
var uwr = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET);
string modelSavePath = Path.Combine(Application.dataPath, "Objects");
modelSavePath = Path.Combine(modelSavePath, docName);
//Create Directory if it does not exist
if (!Directory.Exists(Path.GetDirectoryName(modelSavePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(modelSavePath));
}
var dh = new DownloadHandlerFile(modelSavePath);
dh.removeFileOnAbort = true;
uwr.downloadHandler = dh;
yield return uwr.SendWebRequest();
if (uwr.isNetworkError || uwr.isHttpError)
Debug.LogError(uwr.error);
else
Debug.Log("File successfully downloaded and saved to " + modelSavePath);
}
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);
}));
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?