- Home /
Download prefab at runtime
How can i download prefab at run time? As you can see my code below (I'm using helloAR example from ARCore example). Currently i have list that contains prefabs which i manually have to add prefabs every time i want to add new prefabs. Is it somehow possible to download prefabs let says from Firebase Storage and load that prefab to the list when the user opens the application or let user download new prefabs after they open the app?
namespace GoogleARCore.Examples.HelloAR
{
using System.Collections.Generic;
using GoogleARCore;
using GoogleARCore.Examples.Common;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
#if UNITY_EDITOR
// Set up touch input propagation while using Instant Preview in the editor.
using Input = InstantPreviewInput;
#endif
/// <summary>
/// Controls the HelloAR example.
/// </summary>
public class HelloARController : MonoBehaviour
{
int listIndex = 0;
/// <summary>
/// The first-person camera being used to render the passthrough camera image (i.e. AR
/// background).
/// </summary>
public Camera FirstPersonCamera;
/// <summary>
/// A prefab to place when a raycast from a user touch hits a vertical plane.
/// </summary>
public GameObject GameObjectVerticalPlanePrefab;
/// <summary>
/// A prefab to place when a raycast from a user touch hits a horizontal plane.
/// </summary>
//public GameObject GameObjectHorizontalPlanePrefab;
public List<GameObject> GameObjectHorizontalPlanePrefab;
/// <summary>
/// A prefab to place when a raycast from a user touch hits a feature point.
/// </summary>
public GameObject GameObjectPointPrefab;
/// <summary>
/// The rotation in degrees need to apply to prefab when it is placed.
/// </summary>
private const float k_PrefabRotation = 180.0f;
/// <summary>
/// True if the app is in the process of quitting due to an ARCore connection error,
/// otherwise false.
/// </summary>
private bool m_IsQuitting = false;
/// <summary>
/// The Unity Awake() method.
/// </summary>
public void Awake()
{
// Enable ARCore to target 60fps camera capture frame rate on supported devices.
// Note, Application.targetFrameRate is ignored when QualitySettings.vSyncCount != 0.
Application.targetFrameRate = 60;
}
/// <summary>
/// The Unity Update() method.
/// </summary>
public void Update()
{
Text prefabNameTxt = GameObject.Find("Canvas/prefabLabel").GetComponent<Text>();
prefabNameTxt.text= GameObjectHorizontalPlanePrefab[listIndex].name;
_UpdateApplicationLifecycle();
// If the player has not touched the screen, we are done with this update.
Touch touch;
if (Input.touchCount < 1 || (touch = Input.GetTouch(0)).phase != TouchPhase.Began)
{
return;
}
// Should not handle input if the player is pointing on UI.
if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
{
return;
}
// Raycast against the location the player touched to search for planes.
TrackableHit hit;
TrackableHitFlags raycastFilter = TrackableHitFlags.PlaneWithinPolygon |
TrackableHitFlags.FeaturePointWithSurfaceNormal;
if (Frame.Raycast(touch.position.x, touch.position.y, raycastFilter, out hit))
{
// Use hit pose and camera pose to check if hittest is from the
// back of the plane, if it is, no need to create the anchor.
if ((hit.Trackable is DetectedPlane) &&
Vector3.Dot(FirstPersonCamera.transform.position - hit.Pose.position,
hit.Pose.rotation * Vector3.up) < 0)
{
Debug.Log("Hit at back of the current DetectedPlane");
}
else
{
// Choose the prefab based on the Trackable that got hit.
GameObject prefab;
if (hit.Trackable is FeaturePoint)
{
prefab = GameObjectPointPrefab;
}
else if (hit.Trackable is DetectedPlane)
{
DetectedPlane detectedPlane = hit.Trackable as DetectedPlane;
if (detectedPlane.PlaneType == DetectedPlaneType.Vertical)
{
prefab = GameObjectVerticalPlanePrefab;
}
else
{
prefab = GameObjectHorizontalPlanePrefab[listIndex];
}
}
else
{
prefab = GameObjectHorizontalPlanePrefab[listIndex];
}
// Instantiate prefab at the hit pose.
var gameObject = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
// Compensate for the hitPose rotation facing away from the raycast (i.e.
// camera).
gameObject.transform.Rotate(0, k_PrefabRotation, 0, Space.Self);
// Create an anchor to allow ARCore to track the hitpoint as understanding of
// the physical world evolves.
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
// Make game object a child of the anchor.
gameObject.transform.parent = anchor.transform;
}
}
}
/// <summary>
/// Check and update the application lifecycle.
/// </summary>
private void _UpdateApplicationLifecycle()
{
// Exit the app when the 'back' button is pressed.
if (Input.GetKey(KeyCode.Escape))
{
Application.Quit();
}
// Only allow the screen to sleep when not tracking.
if (Session.Status != SessionStatus.Tracking)
{
Screen.sleepTimeout = SleepTimeout.SystemSetting;
}
else
{
Screen.sleepTimeout = SleepTimeout.NeverSleep;
}
if (m_IsQuitting)
{
return;
}
// Quit if ARCore was unable to connect and give Unity some time for the toast to
// appear.
if (Session.Status == SessionStatus.ErrorPermissionNotGranted)
{
_ShowAndroidToastMessage("Camera permission is needed to run this application.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
else if (Session.Status.IsError())
{
_ShowAndroidToastMessage(
"ARCore encountered a problem connecting. Please start the app again.");
m_IsQuitting = true;
Invoke("_DoQuit", 0.5f);
}
}
/// <summary>
/// Actually quit the application.
/// </summary>
private void _DoQuit()
{
Application.Quit();
}
/// <summary>
/// Show an Android toast message.
/// </summary>
/// <param name="message">Message string to show in the toast.</param>
private void _ShowAndroidToastMessage(string message)
{
AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject unityActivity =
unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
if (unityActivity != null)
{
AndroidJavaClass toastClass = new AndroidJavaClass("android.widget.Toast");
unityActivity.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
AndroidJavaObject toastObject =
toastClass.CallStatic<AndroidJavaObject>(
"makeText", unityActivity, message, 0);
toastObject.Call("show");
}));
}
}
public void ListCycleRight()
{
int sizeOfList = GameObjectHorizontalPlanePrefab.Count;
if (listIndex >= sizeOfList)
{
}
else {
listIndex++;
}
}
public void ListCycleLeft()
{
int sizeOfList = GameObjectHorizontalPlanePrefab.Count;
if (listIndex <= 0)
{
}
else
{
listIndex--;
}
}
}
}
Answer by naviln · Nov 04, 2019 at 06:15 AM
Hi buddy,
You should be able to download prefab assets at runtime using an asset bundle: https://docs.unity3d.com/Manual/AssetBundlesIntro.html
I use them in my project to allow clients to download new card art from my server. Their client will automatically download the new asset bundle at runtime, whenever i upload a new bundle with a new manifest file on my server. I think you should also be able to put prefabs into those asset bundles, although I haven't tried it myself.
There is a learn tutorial here: https://learn.unity.com/tutorial/assets-resources-and-assetbundles?_ga=2.203682832.1259496321.1572847230-1624626891.1547706674# (Although I wish there was a simple example! My implementation is hacked together, but works)
Interestingly, I just realized that this tutorial was deprecated for Addressables. hmm. I haven't bothered learning that yet! My asset bundling works fine for now. I hope it doesn't get deprecated!!!
Answer by RaviVohra · Jun 28, 2020 at 07:36 AM
@naviln @UnityMaru @ThePunisher hey i want some method to download complete scene from server and run it , i tried using asset bundle to download complete scene , that worked inside unity but it didn't works on android , my game crashed after downloading asset bundles.
I am using asset bundle browser to create asset bundle for various platform , and here is my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class playGameScript : MonoBehaviour
{
public string url;
static AssetBundle assetBundle;
// Start is called before the first frame update
private void Start()
{
StartCoroutine(s());
}
IEnumerator s()
{
if (!assetBundle)
{
using (WWW www = new WWW(url))
{
yield return www;
if (!string.IsNullOrEmpty(www.error))
{
print(www.error);
yield break;
}
assetBundle = www.assetBundle;
}
}
string[] scenes = assetBundle.GetAllScenePaths();
foreach (string s in scenes)
{
print(Path.GetFileNameWithoutExtension(s));
loadScene(Path.GetFileNameWithoutExtension(s));
}
}
public void loadScene(string name) {
SceneManager.LoadScene(name);
}
}
please help me i am stuck here , don't know why it is not working in android , i included all the script in my main project as we can not include them in asset bundle and deleted every asset from project like sound , graphics , etc.
Please tell me what is wrong.
Hey mate,
You'll have to find out more about the crash on the Android device.
In your code, add some more error trapping (try-catch blocks) and write all errors to a custom logging text file in Application.persistentDataPath (e.g. CustomLogFile.txt).
e.g.
try
{
//Your code or method name
}
catch (Exception e)
{
var error$$anonymous$$essage = "Something went wrong with method (name): " + e.ToString();
var logFilePath = Application.persistentDataPath + "/" + "CustomLogFile.txt";
if (!File.Exists(logFilePath))
{
using (var file = File.Create(logFilePath))
{
//file gets created
}
}
//write to the log file.
using (StreamWriter w = File.AppendText(logFilePath))
{
w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString());
w.WriteLine(" : {0}", error$$anonymous$$essage);
w.WriteLine("-------------------------------");
}
}
These custom log files should be easy to pull out and inspect on the Android device using the default system file explorer.
Hopefully they help you nail down the stack trace and work out exactly which line of code is crashing.
From there you should be able work out what is going wrong and continue your investigation.
Your answer
Follow this Question
Related Questions
How can i get the name of the current prefab from the list.. 1 Answer
Multiple Cars not working 1 Answer
Augmented Reality SDK for Unity that can compile in .exe for Windows 0 Answers
AR Foundation: How to stop model from moving when tapping buttons on the screen 0 Answers
Distribute terrain in zones 3 Answers