Spawning Advanced/Imported Content (Unity)

Now that you have learned how to Spawn Prefabs at Runtime, you may be wondering if you can spawn more advanced things that can’t be easily per-defined as a prefab?

Fortunately, you can leverage the prefab spawning system, combined with Properties, to do just that!

Spawning a “Loader Object”

As a simple example, let’s say you want to spawn a 2d image into a Space in a way that is fully synchronized. In this example you already have the URL you want to use.

To achieve this, instead of somehow spawning the image in question, we will spawn a blank “Image Loader”.

image-20240328-001732.png

It is simply a blank sprite image living underneath a world-space canvas. At it’s root we have created a new SyncImageUrl script. This script will listen for the property of the URL we wish to load.

Note: “Send My Changes” is disabled on the Url script. This is because we don’t want to be monitoring activity on this object and sending out transient updates behind-the-scenes. As you will see below we want to Post() the Url string property ONCE, and then never touch it again.

Here is the script we will be using to load the image on this prefab. Basically it works just like any of the other No-Code Components, except when it gets the string value it goes on to run Unity’s image loading scripts.

using CavrnusSdk.PropertySynchronizers; using System.Collections; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class SyncImageUrl : CavrnusValueSyncString { public Image displayImage; public override string GetValue() { //We don't wanna "send" any values from this component, so we don't need to fill this in. //Un-checking "Send My Changes" ensures this is never called. return ""; } public override void SetValue(string value) { if(!string.IsNullOrEmpty(value)) { StartCoroutine(LoadImageFromUrl(value)); } } private IEnumerator LoadImageFromUrl(string url) { UnityWebRequest www = UnityWebRequestTexture.GetTexture(url); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.Log(www.error); } else { Texture myTexture = ((DownloadHandlerTexture)www.downloadHandler).texture; var sprite = Sprite.Create(myTexture as Texture2D, new Rect(Vector2.zero, new Vector2(myTexture.width, myTexture.height)), Vector2.zero); displayImage.sprite = sprite; } } }

Then, when the time comes to spawn this image, you simply call SpawnObject like in the previous guide, and post a value to its “Url” property!

private void SpawnImage() { string newContainerName = spaceConn.SpawnObject("Image Loader"); //Set its url spaceConn.PostStringPropertyUpdate(newContainerName, "Url", "https://upload.wikimedia.org/wikipedia/commons/7/78/Jan_Matejko%2C_Sta%C5%84czyk.jpg"); //Give it an initial position spaceConn.PostTransformPropertyUpdate(newContainerName, "Transform", new Vector3(5, 0, 5), Vector3.zero, Vector3.one); }

And thus the Image will show up!

image-20240328-003127.png

Further Improvements

One thing to note here is that, until the www.SendWebRequest() finishes your users will instead just see a blank image. A way to improve on this is to, maybe, hide the image until it is done loading. In it’s place you can show, say, a Text field that says “Loading”. You can get as fancy with this as you want, as at this point you are really just limited by the data coming back from whatever content loader you are using.

Also note that the process above can be used for anything, not just images. If you had a .fbx or .usd loader you wished to integrate into your application you would only need to plug its logic into the LoadImageFromUrl function and everything else will work just fine.