beeeen
beeeen5d ago

How can I keep my Realtime prefabs out of the Normal/Resources folder?

Prefabs that have a realtime view in them must be kept within the Normal/Resources folder. Is there anyway to change this? I'd like to keep the prefabs organized within my directory as best suits my project.
5 Replies
kapa.ai
kapa.ai5d ago
Hi @beeeen. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- You don't need to keep your Realtime prefabs specifically in a "Normal/Resources" folder. The requirement is simply that they need to be in any "Resources" folder within your project so they can be loaded at runtime. However, if you want to avoid using Resources folders altogether (which is recommended for larger projects due to performance issues), Normcore provides a way to use the Addressables system instead. Normcore includes two interfaces that can hook into the prefab loading and instantiation pipeline: - IRealtimePrefabLoadDelegate - IRealtimePrefabInstantiateDelegate You can implement a custom prefab load delegate to use Addressables instead of Resources. Here's how you can set it up: 1. Create a script that implements IRealtimePrefabLoadDelegate:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Normal.Realtime;

public class CustomPrefabLoadDelegate : MonoBehaviour, IRealtimePrefabLoadDelegate {
[SerializeField]
private List<AssetReference> _realtimePrefabsToPreload = new List<AssetReference>();
private Dictionary<string, AsyncOperationHandle<GameObject>> _assets;

private void Start() {
// Preload all assets
_assets = new Dictionary<string, AsyncOperationHandle<GameObject>>();
foreach (AssetReference assetToLoad in _realtimePrefabsToPreload) {
if (assetToLoad.RuntimeKeyIsValid() == false)
continue;

string key = assetToLoad.RuntimeKey as string;
if (key == null)
continue;

_assets.Add(key, Addressables.LoadAssetAsync<GameObject>(key));
}
}

private void OnDestroy() {
// Unload all assets
// Note: Make sure all of your realtime prefabs are destroyed before this script is destroyed otherwise it may unload assets that are in use by realtime prefabs in the scene.
foreach (var assetHandle in _assets.Values) {
Addressables.Release(assetHandle);
}
}

public GameObject LoadRealtimePrefab(RealtimePrefabMetadata prefabMetadata) {
string key = prefabMetadata.prefabName;
AsyncOperationHandle<GameObject> asset = default;

// Check if we have already preloaded this asset.
if (_assets.TryGetValue(key, out asset) == false) {
// Not found, log a warning that the asset will need to be loaded into memory.
Debug.LogWarning($"CustomPrefabLoadDelegate: Asked to load a prefab that doesn't exist in our list of preloaded assets. Will load synchronously, but this may be slow if the asset isn't already loaded.");

// Start loading the asset
asset = Addressables.LoadAssetAsync<GameObject>(key);

// Store the load operation for future calls
_assets.Add(key, asset);
}

// Wait for the asset to load (anything preloaded will return instantly)
return asset.WaitForCompletion();
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using Normal.Realtime;

public class CustomPrefabLoadDelegate : MonoBehaviour, IRealtimePrefabLoadDelegate {
[SerializeField]
private List<AssetReference> _realtimePrefabsToPreload = new List<AssetReference>();
private Dictionary<string, AsyncOperationHandle<GameObject>> _assets;

private void Start() {
// Preload all assets
_assets = new Dictionary<string, AsyncOperationHandle<GameObject>>();
foreach (AssetReference assetToLoad in _realtimePrefabsToPreload) {
if (assetToLoad.RuntimeKeyIsValid() == false)
continue;

string key = assetToLoad.RuntimeKey as string;
if (key == null)
continue;

_assets.Add(key, Addressables.LoadAssetAsync<GameObject>(key));
}
}

private void OnDestroy() {
// Unload all assets
// Note: Make sure all of your realtime prefabs are destroyed before this script is destroyed otherwise it may unload assets that are in use by realtime prefabs in the scene.
foreach (var assetHandle in _assets.Values) {
Addressables.Release(assetHandle);
}
}

public GameObject LoadRealtimePrefab(RealtimePrefabMetadata prefabMetadata) {
string key = prefabMetadata.prefabName;
AsyncOperationHandle<GameObject> asset = default;

// Check if we have already preloaded this asset.
if (_assets.TryGetValue(key, out asset) == false) {
// Not found, log a warning that the asset will need to be loaded into memory.
Debug.LogWarning($"CustomPrefabLoadDelegate: Asked to load a prefab that doesn't exist in our list of preloaded assets. Will load synchronously, but this may be slow if the asset isn't already loaded.");

// Start loading the asset
asset = Addressables.LoadAssetAsync<GameObject>(key);

// Store the load operation for future calls
_assets.Add(key, asset);
}

// Wait for the asset to load (anything preloaded will return instantly)
return asset.WaitForCompletion();
}
}
2. Add this component to the same GameObject as your Realtime component. 3. Set up your Addressables system and add your Realtime prefabs to it. 4. When instantiating, you'll use the asset key as the prefab name:
string assetKey = _testAsset.RuntimeKey as string;
GameObject gameObject = Realtime.Instantiate(assetKey, Realtime.InstantiateOptions.defaults);
string assetKey = _testAsset.RuntimeKey as string;
GameObject gameObject = Realtime.Instantiate(assetKey, Realtime.InstantiateOptions.defaults);
This approach allows you to organize your prefabs however you want in your project structure while still making them available to Normcore at runtime. Using Addressables By implementing this system, you can keep your prefabs organized in a way that makes sense for your project structure rather than being forced to use Resources folders. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@690217885540417680> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
maxweisel
maxweisel5d ago
This is a Unity requirement. If a prefab isn’t referenced anywhere it gets stripped from builds unless it’s in a Resources folder You can use addressables if you’d like but why not just put a Resources folder within your other folders? You can have multiple Resources folders and that’s how most folks organize this stuff
beeeen
beeeenOP5d ago
That's a very astute question 😂 It never occured to me I'll just do that! Thanks @maxweisel !
maxweisel
maxweisel5d ago
sure thing

Did you find this page helpful?