Im kind of lost in trying to import my Content Archives during runtime, i have looked at unity entities content management documents, successfully managed to build my content archives however im having issues importing them in at runtime. Below is my code on how im building my content Archives
private void BuildContentArchivesForScene(string destinationFolder, string sceneName)
{
Scene currentScene = SceneManager.GetActiveScene();
string outputPath = destinationFolder;
// Step 3: Prepare scene references and object references
var sceneRefs = new HashSet<UntypedWeakReferenceId>();
var objectRefs = new HashSet<UntypedWeakReferenceId>();
// Convert the scene path to a GUID and create a weak reference ID for the scene
string sceneGUID = AssetDatabase.AssetPathToGUID(currentScene.path);
var sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(currentScene.path);
if (sceneAsset != null)
{
var sceneRef = UntypedWeakReferenceId.CreateFromObjectInstance(sceneAsset);
if (!sceneRefs.Contains(sceneRef))
sceneRefs.Add(sceneRef);
}
else
{
Debug.LogError("Failed to load scene asset.");
return;
}
// Get dependencies for the scene (all assets the scene depends on)
string[] dependencies = AssetDatabase.GetDependencies(scenePath, true);
foreach (string dependency in dependencies)
{
if (!dependency.EndsWith(".unity") && dependency.StartsWith("Assets/YOUR_PLUGIN_HERE")) // Skip the scene itself
{
var asset = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(dependency);
if (asset != null)
{
var objectRef = UntypedWeakReferenceId.CreateFromObjectInstance(asset);
if (!objectRefs.Contains(objectRef))
objectRefs.Add(objectRef);
}
}
}
Debug.Log("Building....");
Debug.Log("Scene refs: " + sceneRefs.Count);
Debug.Log("Object refs: " + objectRefs.Count);
foreach (var objectRef in objectRefs)
{
Debug.Log($"Object Reference: {objectRef}");
}
foreach (var sceneRef in sceneRefs)
{
Debug.Log($"Scene Reference: {sceneRef}");
}
// Step 4: Define the custom content (if any)
var customContent = new List<CustomContent>();
// Step 5: Prepare for the build
IBundleBuildResults buildResults;
var buildTasks = new List<IBuildTask>()
{
new BuildPlayerScripts(),
// Calculate asset dependency data
new CalculateAssetDependencyData(),
//calculate scene dependency data
new CalculateSceneDependencyData(),
// Generate bundle maps
new GenerateBundleMaps(),
// Generate bundle packing layout
new GenerateBundlePacking(),
// Generate commands for writing the bundles
new GenerateBundleCommands(),
// Write the serialized asset files
new WriteSerializedFiles(),
// Archive and compress the bundles
new ArchiveAndCompressBundles()
};
BuildCache.PurgeCache(true);
// Step 6: Build the content archive
var result = V_ContentArchiveBuildUtility.BuildContentArchives(
BuildTarget.StandaloneWindows, // Use the appropriate BuildTarget
objectRefs,
sceneRefs,
customContent,
sceneName,
outputPath,
out buildResults,
buildTasks,
null
);
if (result == ReturnCode.Success)
{
var instance = DotsGlobalSettings.Instance;
var playerGuid = instance.GetPlayerType() == DotsGlobalSettings.PlayerType.Client ? instance.GetClientGUID() : instance.GetServerGUID();
if (!playerGuid.IsValid)
throw new Exception("Invalid Player GUID");
var subSceneGuids = new HashSet<Unity.Entities.Hash128>()
{
sceneRefs.First().GlobalId.AssetGUID
};
RemoteContentCatalogBuildUtility.BuildContent(subSceneGuids, playerGuid, BuildTarget.StandaloneWindows64, outputPath);
var publishFolder = Path.Combine(outputPath, $"{sceneName}-RemoteContent");
RemoteContentCatalogBuildUtility.PublishContent(outputPath, publishFolder, f => new string[] { "all" });
}
}
this builds my scene into 2 asset bundles, one with the assets and one with the scene (followed using the ContentArchivesBuildUtility scripting API) and then push a remote content update
However i am having issues in importing these files at runtime. The following is my code on how im doing it
public static void LoadContentArchive(string pluginName)
{
string buildLocation = Path.Combine(Application.persistentDataPath, "build", pluginName);
Uri fileUri = new Uri(buildLocation + "/" + pluginName + "-RemoteContent" + "/" + "catalogs.bin");
RuntimeContentSystem.LoadContentCatalog(fileUri.ToString(), buildLocation + "/" + pluginName + "-cache", "all");
RuntimeContentManager.Initialize();
AssetBundleCreateRequest assetsRequest = AssetBundle.LoadFromFileAsync(buildLocation + "/" + pluginName + "_Assets");
AssetBundle assetsBundle = assetsRequest.assetBundle;
foreach (var asset in assetsBundle.LoadAllAssets())
{
if(asset != null)
{
UntypedWeakReferenceId obj = (UntypedWeakReferenceId.CreateFromObjectInstance(asset));
RuntimeContentManager.LoadObjectAsync(obj);
}
}
AssetBundleCreateRequest sceneRequest = AssetBundle.LoadFromFileAsync(buildLocation + "/" + pluginName + "_Scene");
AssetBundle scenesBundle = sceneRequest.assetBundle;
foreach (var scene in scenesBundle.LoadAllAssets())
{
UntypedWeakReferenceId sceneRef = (UntypedWeakReferenceId.CreateFromObjectInstance(scene));
ContentSceneParameters sceneParams = new ContentSceneParameters()
{
loadSceneMode = LoadSceneMode.Single,
localPhysicsMode = LocalPhysicsMode.None,
autoIntegrate = true,
};
RuntimeContentManager.LoadSceneAsync(sceneRef, sceneParams);
}
}
When i do this on debugging i ran into some issues.
Firstly when I load my content catalog, the delivery update is always stuck to None, i have triple checked that it points to the correct file
Secondly, it throws the error of
Asset file does not exist or does not contain LFID 0
On debugging i find out that despite my asset is valid, the weakreferenceID is always set to 000000000000:0 and is valid to false.
Am i importing these archives correctly? is there an alternative approach i should take to importing them in?