can't be loaded because another AssetBundle with the same files is already loaded. error while loading different bundles - c#

I've tried load asset bundles from URLs. When I load only single asset bundle, it works well. But if I try to load multiple asset bundles, Unity gives this error: The AssetBundle 'https://example.com/uc?export=download&id=1234567' can't be loaded because another AssetBundle with the same files is already loaded.
example code as follows
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using TMPro;
public class sahnecagir : MonoBehaviour
{
public TextMeshProUGUI Log;
// Start is called before the first frame update
void Start()
{
StartCoroutine(LoadBundleFromUrl("https://example.com/uc?export=download&id=123456", 2, 0, (uint)Crc.Gifts));
}
IEnumerator LoadBundleFromUrl(string url, int tip, uint version, uint crc)
{
using (UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(url, version, crc))
{
uwr.SendWebRequest();
while (!uwr.isDone)
{
if(tip == 1) Log.text = "Rooms loading " + (uwr.downloadProgress * 100).ToString("0") + "%";
else if(tip == 2) Log.text = "Gifts loading " + (uwr.downloadProgress * 100).ToString("0") + "%";
yield return null;
}
if (uwr.isNetworkError || uwr.isHttpError)
{
Debug.Log(uwr.error);
}
else
{
if (tip == 1)
{
MainConfig.Instance.RoomBgBundle = DownloadHandlerAssetBundle.GetContent(uwr);
}
else if (tip == 2)
{
MainConfig.Instance.GiftBundle = DownloadHandlerAssetBundle.GetContent(uwr);
}
}
if (uwr.isDone && tip == 1)
{
Log.text = "Rooms loading 100%";
StartCoroutine(LoadBundleFromUrl("https://example.com/uc?export=download&id=1234567", 2, 0, 0));
}
else
{
Log.text = "Gifts loading 100%";
}
yield return null;
}
}
}

In my case I've been trying to modify a bundle with different files but Unity refuses to load the two different files even if they have different names, a different structure, different files inside, nothing.
Opening the bundle in Notepad++ brings up what I assume to be a "container name" of CAB-a317cdbf067bab183d6dd12d870c1407 as an example. This is what Unity seems to be checking for to determine whether a bundle is "identical."
A simple find and replace to a different name and boom. The bundles load now.

Related

Index was outside the bounds of the array. Login+<LoginPlayer>d__4.MoveNext () (at Assets/Login.cs:29)

I'm building a system in Unity that takes a register and login menu connected to a MySQL database through PHPMyAdmin, has users log in, then allows them to choose between playing two games. I've been getting this error since I linked the games and I can't figure out how to fix it. The register works fine, but it won't allow for log in.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class Login : MonoBehaviour
{
public TMP_InputField nameField;
public TMP_InputField passwordField;
public Button submitButton;
public void CallLogin()
{
StartCoroutine(LoginPlayer());
}
IEnumerator LoginPlayer()
{
WWWForm form = new WWWForm();
form.AddField("name", nameField.text);
form.AddField("password", passwordField.text);
WWW www = new WWW("http://localhost/sqlconnect/login.php", form);
yield return www;
if (www.text[0] == '0')
{
dbmanager.username = nameField.text;
dbmanager.score = int.Parse(www.text.Split('\t')[1]);
UnityEngine.SceneManagement.SceneManager.LoadScene(0);
}
else
{
Debug.Log("User Login failed. Error #" + www.text);
}
}
public void VerifyInputs()
{
submitButton.interactable = (nameField.text.Length >= 8 && passwordField.text.Length >= 8);
}
}
I've been trying to figure out what happened for hours and need some extra insight, can anyone please help?

Generate new prefab using prefab after edit in runtime

I have simple script and work perfect, but only runing in Unity Editor. I Try build for mobile, not complete and error build. i using Unity 2019.3.4.
Is there a subtitute "using UnityEditor" for mobile script.
I need script for mobile. Any idea for running in mobile.
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.Collections.Generic;
public class Prefabz : MonoBehaviour
{
public GameObject selObj;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
CreatePrefab();
}
}
void CreatePrefab()
{
//GameObject[] selObjs = Selection.gameObjects;
string charName = selObj.name;
// duplicate
GameObject newInstance = Instantiate(selObj);
newInstance.name = charName;
// now replace the prefab
string prefabPath = "Assets/trideeScript/" + charName + ".prefab";
var existingPrefab = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
if (existingPrefab != null)
{
PrefabUtility.ReplacePrefab(newInstance, existingPrefab, ReplacePrefabOptions.ReplaceNameBased);
}
else
{
PrefabUtility.CreatePrefab(prefabPath, newInstance);
}
// delete dupe
DestroyImmediate(newInstance);
Debug.Log("Prefab'd " + charName + "! \"" + prefabPath + "\"");
}
}
UnityEditor namespace is not supported on any platform, except actually Editor. That's why all editor scripts must be placed inside "Editor" folder, and that's why it's a good practice to keep any editor-related stuff inside pre-processor directives #if UNITY_EDITOR

Copy code to clipboard on build in Visual studio

I have an unusual situation here.
Problem
I'm using Visual studio (VS) to write scripts to use in-game in the game Space Engineers.
The problem is that you only use a portion of the code from the file in-game. (I.E, Ctrl+A wont do). So selecting the correct portion is tedious.
I want to streamline the process of copying the desired code in VS and pasting it in Space Engineers.
The idea is to trim all unnecessary white space (there's a character limit) and copy to clipboard when pressing run in VS.
Where I'm at
I've found that you can make your own build configuration and use the "Pre-build event command line" to run something custom. The idea is to make a simple console application that does what I described above. But I don't know how to get the correct file to send to said application.
Am I on the right track? How do I send the desired file to the trimming application? Is there a better way?
Edit:
This is what I had in mind when I said "simple console application".
It does everything I needed it to do (trimming white-space and adding a portion of the code to clipboard). Only thing missing is that I have to specify the file name I want it to use. Which isn't important, it would just be nice.
using System;
using System.Windows.Forms;
namespace TrimFileToClipboard
{
class Program
{
[STAThread()]
static void Main(string[] args)
{
string startString = (args.Length > 1) ? "#region " + args[1] : "#region in-game";
string line;
string trimmed = "";
bool read = false;
int depth = 0;
System.IO.StreamReader file = new System.IO.StreamReader(args[0]);
while ((line = file.ReadLine()) != null)
{
if (!read && line.Contains(startString)) read = true;
else if (read && line.Contains("#region")) depth++;
else if (read && line.Contains("#endregion"))
{
if (depth == 0) break;
else if (depth < 0)
{
Console.WriteLine("There's something wrong with your #regions. Please edit the file.");
Console.ReadLine();
Environment.Exit(0);
}
else depth--;
}
else if (read) trimmed += line.Trim() + "\n";
}
file.Close();
Clipboard.SetText(trimmed);
}
}
}
It can be used by adding
"<path>\TrimFileToClipboard.exe" "$(ProjectDir)<classname>.cs"
to Pre-build event command line, in the project properties/Build events. Where <path> is the path to the application above and <classname> is the file you want to process.
Maybe I should post this part as an answer but I don't know if it's a decent approach or an ugly hack.
Instead of coping the code to the clipboard, I save it directly inside the game as saved workshop script with this simple C# console application.
The SE script I edit using VS has the comments \\script-begin and \\script-end to tell the application where to look for the actual code that needs to be in the programmable block.
After the execution the script will be available at the local workshop. It makes it very easy to work with the SE scripts, whenever I make a change using VS, I run the console application again and the script will be updated inside the game.
internal class Program
{
private static void Main(string[] args)
{
String[] InputLines, outputLines;
Int32 scriptBegin = 0, scriptEnd = 0;
String scriptName = args[0];
String inputPath = "C:\\Users\\hfand\\source\\repos\\se-scripts\\" + scriptName + ".cs";
if (File.Exists(inputPath))
{
InputLines = File.ReadAllLines(inputPath);
for (int i = 0; i < InputLines.Length; i++)
{
if (InputLines[i].Contains("script-begin"))
{
scriptBegin = i + 1;
}
if (InputLines[i].Contains("script-end"))
{
scriptEnd = i - 1;
}
}
outputLines = new List<string>(InputLines).GetRange(scriptBegin, scriptEnd - scriptBegin + 1).ToArray();
for (int i = 0; i < outputLines.Length; i++)
{
if (outputLines[i].Length >= 8)
{
outputLines[i] = outputLines[i].Substring(8);
}
}
String outputPath = "C:\\Users\\hfand\\AppData\\Roaming\\SpaceEngineers\\IngameScripts\\local\\" + scriptName;
if (Directory.Exists(outputPath))
{
File.WriteAllLines(outputPath + "\\Script.cs", outputLines);
}
else
{
Directory.CreateDirectory(outputPath);
File.WriteAllLines(outputPath + "\\Script.cs", outputLines);
}
Console.WriteLine(scriptName + " sincronizado");
}
else
{
Console.WriteLine("Arquivo \"" + inputPath + "\" não encontrado");
}
}
}
Here is an example of how the code in VS should look like
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using VRageMath;
using VRage.Game;
using Sandbox.ModAPI.Interfaces;
using Sandbox.ModAPI.Ingame;
using Sandbox.Game.EntityComponents;
using VRage.Game.Components;
using VRage.Collections;
using VRage.Game.ObjectBuilders.Definitions;
using VRage.Game.ModAPI.Ingame;
using SpaceEngineers.Game.ModAPI.Ingame;
namespace BlankScript
{
public class Program : MyGridProgram
{
//script-begin
public Program()
{
}
public void Save()
{
}
public void Main(string argument, UpdateType updateSource)
{
}
//script-end
}
}
You can write a C# command with my Visual Commander extension that gets active file path in Visual Studio as DTE.ActiveWindow.Document.FullName and then runs your file.ReadLine() loop over it and calls Clipboard.SetText(trimmed) at the end. See for example Copy current file, line, method sample code.

Unity 3D: Loading FBX dynamically using AssetBundle

i am trying to load an already created FBX object into the scene at runtime, i searched around and found that assetbundle can be used to do so. I tried this code but it doesnt seem to instantiate the object in the scene and neither does it pop an error.
Here is the code
using System;
using UnityEngine;
using System.Collections;
public class CachingLoadExample : MonoBehaviour {
public string BundleURL;
public string AssetName;
public int version;
void Start() {
StartCoroutine (DownloadAndCache());
}
IEnumerator DownloadAndCache (){
// Wait for the Caching system to be ready
while (!Caching.ready)
yield return null;
// Load the AssetBundle file from Cache if it exists with the same version or download and store it in the cache
using(WWW www = WWW.LoadFromCacheOrDownload (BundleURL, version)){
yield return www;
if (www.error != null)
throw new Exception("WWW download had an error:" + www.error);
AssetBundle bundle = www.assetBundle;
if (AssetName == "")
Instantiate(bundle.mainAsset);
else
Instantiate(bundle.Load(AssetName));
// Unload the AssetBundles compressed contents to conserve memory
bundle.Unload(false);
} // memory is freed from the web stream (www.Dispose() gets called implicitly)
}
}
I added a new empty game object, dragged the C# code to that game object, supplied the asset bundle link "file://C:/Users/Sahibzada/Documents/New Unity Project/Assets/100777102370.FBX" but no luck
Can someone please guide me, whats wrong with the code, i am totally new with scripting in Unity, Thanks
Create a folder named AssetBundles inside your Assets folder, then
you need to create the AssetBundle of your FBX with an Editor script as show in: http://docs.unity3d.com/Manual/BuildingAssetBundles.html
using UnityEditor;
public class CreateAssetBundles
{
[MenuItem ("Assets/Build AssetBundles")]
static void BuildAllAssetBundles ()
{
BuildPipeline.BuildAssetBundles ("Assets/AssetBundles");
}
}
Lastly you need to introduce, in the BundleURL the URL to the new AssetsBundle:
"file://C:/Users/Sahibzada/Documents/New Unity Project/Assets/AssetsBundles/yourassetbundle"
and on the AssetName you need to introduce "yourassetbundle"
I also recommend not having paths with spaces, this can also be an issue.

How to play sounds loaded on the fly

I trying to make a tool for the sound designer of my group that would allow him to hear his sound file played in Unity.
Check if it's loadable
Check if the volume is right
Check if loops properly
and so on ...
My issue is to find how Unity can manage loading audio files laying somewhere in a folder.
I found a lot of topics speaking about it but no real solutions to how you can make Unity load external files dynamically.
If you want to load files from the same directory as the .exe / .app you can use this :
Using the System.IO DirectoryInfo() to get all files names
Using the WWW class to stream/load the files found
Here the code :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class SoundPlayer : MonoBehaviour {
string absolutePath = "./"; // relative path to where the app is running
AudioSource src;
List<AudioClip> clips = new List<AudioClip>();
int soundIndex = 0;
//compatible file extensions
string[] fileTypes = {"ogg","wav"};
FileInfo[] files;
void Start () {
//being able to test in unity
if(Application.isEditor) absolutePath = "Assets/";
if(src == null) src = gameObject.AddComponent<AudioSource>();
reloadSounds();
}
void reloadSounds() {
DirectoryInfo info = new DirectoryInfo(absolutePath);
files = info.GetFiles();
//check if the file is valid and load it
foreach(FileInfo f in files) {
if(validFileType(f.FullName)) {
//Debug.Log("Start loading "+f.FullName);
StartCoroutine(loadFile(f.FullName));
}
}
}
bool validFileType(string filename) {
foreach(string ext in fileTypes) {
if(filename.IndexOf(ext) > -1) return true;
}
return false;
}
IEnumerator loadFile(string path) {
WWW www = new WWW("file://"+path);
AudioClip myAudioClip = www.audioClip;
while (!myAudioClip.isReadyToPlay)
yield return www;
AudioClip clip = www.GetAudioClip(false);
string[] parts = path.Split('\\');
clip.name = parts[parts.Length - 1];
clips.Add(clip);
}
}
[EDIT]
If people wants to improve on the file management I recommend this link

Categories

Resources