- Home /
Cancel Object.Instantiate
Hi,
I'm currently developing an AR app with Unity and Vuforia. I'm loading the 3D objects from my server and instantiating them at the recognition of the image target. Fact is that the objects are quite heavy and the instantiating can take up to 10s. If the user moves away from the target image during this lapse of time then the object is instantiate in front of the camera and will stay there anyway.
Here is how I Instantiate my objects:
using(WWW www = new WWW(assetDwnLink))
{
yield return www;
File.WriteAllBytes(Application.persistentDataPath + "/" + name, www.bytes);
AssetBundle assetBundle = www.assetBundle;
//GameObject gameobj = assetBundle.Load (name) as GameObject;
request = assetBundle.LoadAsync (name, typeof(GameObject));
yield return request;
GO = Instantiate(request.asset) as GameObject;
//GO = Instantiate(gameobj) as GameObject;
GO.transform.parent = GameObject.Find("AugmentationObject").transform;
GO.transform.localPosition = new Vector3(properties[0], properties[1], properties[2]);
GO.transform.eulerAngles = new Vector3(properties[3], properties[4], properties[5]);
GO.transform.localScale = new Vector3(properties[6], properties[7], properties[8]);
rotateAngles = new Vector3(properties[3], properties[4], properties[5]);
distance = properties[6];
zoomMin = properties[9];
zoomMax = properties[10];
zoomFacteur = properties[11];
GO.SetActive(true);
assetBundle.Unload(false);
www.Dispose();
}
And here's how I'm actually destroying the object when the target is lost:
public void OnTrackingLost()
{
Debug.Log ("OnTrackingLost called");
if(GO)
{
Debug.Log("Destroy called");
Destroy(GO);
}
else if(request != null && request.progress == 1)
{
request = null;
Debug.LogError ("done");
}
}
After some hours reading the API, and reading about CancelInvoke etc. it doesn't look like there's a way to stop the Instantiate while it is instantiating... Though, if any of way have an other idea of how to work around that, or know if I'm missing something, I'm listening to you!
As said in the answers I'm now using Async Loading so I can work with .progress and .isDone. But I can't find the condition to use and the action to do to cancel the Instantiate.
Thanks a lot!
Answer by Arlemi · Jul 24, 2014 at 08:02 AM
I found a workaround, I'm sure it's not the best but at least I don't have this problem anymore. I'm using a bool which says whether the user is still pointing at the image target and I'm testing it before setting the GameObject active. If it's false then I destroy the GO, if it's true I set it active.
public void OnTrackingLost()
{
Debug.Log ("OnTrackingLost called");
if(GO)
{
Debug.Log("Destroy called");
Destroy(GO);
}
else
{
outofcontext = true;
}
}
And in my augmentation method:
if(!outofcontext)
{
Debug.LogError("On affiche");
GO.SetActive(true);
}
else
{
Debug.LogError("On détruit");
Destroy (GO);
}
The bool is also set to false in the Start() method and to true in the OnTrackingFound() method.
After some hard testing, it appears that it keeps happening (very less often though), so to make sure I added that in the Update() method:
if(outofcontext && GO != null)
{
Debug.LogError("On détruit");
Handheld.StopActivityIndicator();
Destroy (GO);
}
I don't have the problem at all anymore.
Answer by Wise · Jul 23, 2014 at 03:22 PM
Maybe there's some way you can break up the object you're instantiating?
That way you can use an
IEnumerator StreamModel () {
foreach (GameObject modelPart in listOfAssetbundles) {
if (cancelBool == false) {
Instantiate(modelPart);
} else {
yield break; //breaks if OnTrackingLost () { cancelBool = true; }
}
yield return null; //jumps to next frame for next part
}
yield return null;
}
or something to this affect, and now it will have maybe 1 second loads per chunk instead of 10 per complete model, letting your user cancel the loading with (as per the example) 1 second intervals instead of 10.
Hi Wise,
Thanks for your input but I unluckily can't split my object in separate bundles...
Though, I changed my code a bit to now use Async loading for my object so I can have .progress and .isDone to work with. It now looks like:
AssetBundle assetBundle = www.assetBundle;
//GameObject gameobj = assetBundle.Load (name) as GameObject;
request = assetBundle.LoadAsync (name, typeof(GameObject));
yield return request;
GO = Instantiate(request.asset) as GameObject;
//GO = Instantiate(gameobj) as GameObject;
And now I'm trying to do something in the OnTrackingLost function here:
public void OnTrackingLost()
{
Debug.Log ("OnTrackingLost called");
if(GO)
{
Debug.Log("Destroy called");
Destroy(GO);
}
else if(request != null && request.progress == 1)
{
request = null;
Debug.LogError ("done");
}
}
But I can't find the condition to put in my if condition, nor the action to do...
Your answer
![](https://koobas.hobune.stream/wayback/20220613154807im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Checking if object intersects? 1 Answer
Instantiate an object in a prefab? 1 Answer
instantiating transform.translate in the wrong position? 1 Answer
Translate a 2D position to a 3D space 1 Answer
MMORPG Nearby Mobs - Instantiate? 1 Answer