Assigning multiple assets to multiple variables on inspector - unity3d

Is there a way to assign multiple assets to multiple variables on the inspector???
My case is this, I have 5 objects, those objects have a script wich have around 1200 variables used to play SFXs. When Unity compile the script I have to manually drag and drop the SFX from the assets to the variable on the inspector, or go to the inspector, scrol to the variable, click the dot and then select the SFX file from the window.
Is there a way to speed this up?

You should create a public List of Audio Sources which will appear in inspector. Lock the inspector by clicking look in right top.
Now select all the files from Project and drag on list. All files will be added to list. Now if you want a specific file you can find the file by its name for example:
AudioSource GetAudioSource(string SourceName)
{
return audioSourceList.Find(item => item.Name == SourceName);
}

Use the Resources.LoadAll method to access all the assets from the path parameter via scripting. Probably put that method call in Start. Might have to rename the files to pull the right order from the LoadAll method if they result in some alternate order.
EDIT: Here's some example code...
(NOTE: Loads from Resources/Sound/SFX folder)
For reference: http://docs.unity3d.com/ScriptReference/Resources.LoadAll.html
public class YourClassNameGoesHere : MonoBehaviour
{
Public AudioClip[] BA;
void Start ()
{
BA = (AudioClip[]) Resources.LoadAll("Sound/SFX");
}
}

I found a solution for this problem. I must say, it's not perfect, in fact, it should not be used unless is absolutely necessary.
To speed up the assign you could do this:
Create a variable
public AudioClip ma, me, mi, mo, mu;
At Start() add
ma = Resources.Load("Sound/SFX/MA") as AudioClip;
me = Resources.Load("Sound/SFX/ME") as AudioClip;
mi = Resources.Load("Sound/SFX/MI") as AudioClip;
mo = Resources.Load("Sound/SFX/MO") as AudioClip;
mu = Resources.Load("Sound/SFX/MU") as AudioClip;
After compile the public variables will be available on the Inspector as empty variables, but, on runtime the variables will be filled with the content of the folder Resources/Sound/SFX (Assets\Resources\Sound\SFX).
Why shouldn't be use unless necessary?, first, it's a bad practice; second, it's a cheap trick that comes at a price (on mobile devices it load all the resources so will consume RAM fast). In my test, all my sound clips take as much as 169 MB. On PC it's not much of a problem, but if your target is Mobile games, this is something to take into consideration. And third, on web player, ALL resources will be streamed first.
On a side note, this cheap trick ignores the way Unity handles assets. Unity force you to assign assets manually because if the asset is not use, it will not be integrated into the build. This trick force everything to be loaded and be integrated into the final build, used or no. On the other hand, if you are assign it, you will use it... right?
The answer and example given by #Jayson Ash lead me to the right direction.

Related

Unity scaling an object when duplicating (not wanted)

I'm making a mining game, where you have a rest area, and a mine area (all of this stuff works well) but when I "hire a new worker" the main miner clones, and is put in the starting area. When I clone the main miner, the cloned miner's size goes to 6k something something.
public void moreMiners(){
if (gm.Diamonds >= gm.mmcost){
gm.Diamonds -= gm.mmcost;
GameObject newplr = GameObject.Instantiate(plr);
newplr.gameObject.transform.localPosition = plr.transform.position;
}
}
duplicating code ^
help is appreciated
Make sure that "plr" reference is the original Prefab from your assets folder and not from your scene, then what you can do is to check your original prefab inside your assets folder and see if the scale is the one that you want to have.
Also when you Instantiate an object you can parse the position too as a parameter like this:
GameObject.Instantiate(plr,position);

Save and load entire scene in Unity

Okay, so I've been struggling around and searching for a while, saw a lot of different posts, but I did not find answer to my question.
My problem:
I have a scene in Unity with nothing in it, everything is created proceduraly and randomly on game start, and of course I want the player to be able to save his progress. I have found ways of saving progress in Unity, but everything was about writing a script for each class or object I want to save, but these seem to me inefficient, since in my game, there are randomly generated houses and buildings (which would be relatively easy to save), but there can also be objects placed inside these buildings and so on. Also later I plan on adding characters, which also need to be saved (like where they are, what are they holding and such). And as I mentioned, writing a save and load script for each object seems inefficient to me, since I'm used to Java's serializtaion, where I just write my Main Object containing all data to a file, so I'm looking for some easier ways to do so. Possibly a way to save entire scene state and then on loading just load the scene instead of generating it from scratch.
My Question:
Is there a way to save whole scene with all objects and information about them and then load it?
Thank you in advance!
There's no built-in method by which you can "save a scene" during runtime and then reload it later. In a Unity build, scenes are stored in a non-editable format, meaning that whenever you load a scene it will load up with the same format as it was built. This is a good thing, because you don't want to edit the contents of your build in a deployed game.
Now, that doesn't mean that a scene can't contain logic to configure itself differently. In fact, it sounds like that's what you're doing. The goal instead is to store the contents into a save file.
Consider switching your mentality from "I want to load a scene that generates random gameplay" to "I want to load a scene that configures itself based on a file." This is a layer of abstraction that gives greater control over what happens when you load your scene.
I would suggest creating a JSON configuration file that stores your important information, something like this might do:
{
"house_locations": [
{
"position": "(0, 0, 0)",
"objects": []
},
{
"position": "(10, 10, 10)",
"objects": []
}
],
"characters": [
{
"position": "(0, 0, 0)",
"inventory": [
{
"item_name": "knife"
},
{
"item_name": "shovel"
}
]
}
]
}
This is just a simple example, as you'll have to add the important data you want to represent your game.
Next, all you have to do when you want to start your game is to do one of the following things:
Are you starting a new game? => Generate a random configuration file, then use that to populate your scene.
Are you loading a saved game? => Use the saved configuration file to populate your scene.
You'll need some kind of WorldBuilder script to handle this. In your scene, you can have something like the following:
public class WorldBuilder : MonoBehaviour
{
// This is the actual contents of the world, represented as a JSON string.
private string _json = "";
public void BuildWorld(string configFilePath)
{
_json = LoadConfiguration(configFilePath);
BuildWorld(_json);
}
public void GenerateWorld()
{
_json = GenerateConfiguration();
BuildWorld(_json);
}
public void SaveWorld(string targetFilePath)
{
// Save the contents of _json out to a file so that it can be loaded
// up again later.
}
private string LoadConfiguration(string configFilePath)
{
// Load the actual file and return the file contents, which is a JSON string.
}
private void BuildWorld(string json)
{
// Actually build the world using the supplied JSON.
}
private string GenerateConfiguration()
{
// Return a randomly generated configuration file.
}
}
This approach separates the problem of saving the contents of the scene and generating the contents of the scene, making the code easier to write and maintain.
I do not know how to build a scene save patternor principles.
But there is a plugin which save scene in play mode, you may configure it according to your project.
https://assetstore.unity.com/packages/tools/utilities/autosaver-don-t-waste-time-anymore-54247
I would name 'LoadConfiguration' to 'LoadWorld'. Actually, I'd name it 'WorldSave' and 'WorldLoad' so it all matches up alphabetically.
Also, have loading be asynchronous:
public IEnumerator WorldLoad(string localWorldFilePath)
{
string filePath = Application.persistentDataPath + "/" + localWorldFilePath + ".json");
string lines = null;
//Loading the level loop:
using (SteamReader streamReader = new StreamReader(filePath,Encoding.UTF8))
{
lines += streamReader.ReadToEnd();
if (UnityEngine.Random.Range(0f,20f) > 15f) //< - probably a fancier way of doing this part)
yield return new WaitForEndOfFrame();
}
//Okay, we're done loading so return this:
yield return lines;
}
In fact, have saving be asynchronous too, using StreamWriter and make sure it's also encoded in UTF8, you can't just use File.Save and File.Load in other words.
Another idea, encrypt your files if you don't want modding (but people will just decrypt it anyway).
Start the coroutine somewhere else, the lower you make that '15f' the more it'll lock up your game, the higher you make it the less it will but the slower it'll go. There's a way to do it on a separate thread or something but I'm not an advanced programmer.
worldBuilder.StartCoroutine(WorldLoad);
TIP 1:
Ideally you wanna create your own scripting language through a console, if the idea of real-time custom scene file loading and saving is that you can create and edit your levels while the actual game is running so that you're bypassing using Unity as a level editor for example.
In other words you could press ~ and bring a console up and type 'WorldLoad(worldNameGoesHere)' and it'll load the world in your games built folders.
There's also a way using an editor script you can actually hook in and override Unity's standard 'Scene Save', in case you wanna do that also.
TIP 2:
Also make sure you encode in UTF8 format like above, saving and loading so you don't have it become a pain later when you want to implement asian languages like Japanese, Chinese, etc...

Unity is always throwing a Win32 Exception [duplicate]

so I'm new to Unity and I've been trying to test the scene with the script attatched to a character. However, it keeps saying "The associated script cannot be loaded. Please fix any compile errors and assign a valid script." It also says that the name of the file could be different from the name in the code but it isnt, and also it says that the code could be missing MonoBehaviour Scripts. It wont even allow me to attach the script to characters because it cant find the script class.
I've copied and downloaded character movement codes from the internet but they didnt work either. I've also tried deleting and re-making the CS files but that didnt work either. Even adding empty scripts to characters didnt work unless i do it from "Add component"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
SpriteRenderer sprite;
Rigidbody2D rigid;
// Start is called before the first frame update
void Start()
{
sprite = GetComponent<SpriteRenderer>();
rigid = GetComponent<Rigidbody2D>();
}
private void FixedUpdate()
{
if (Input.GetKey("d"))
rigid.velocity = new Vector2(2, 0);
else if (Input.GetKey("a"))
rigid.velocity = new Vector2(-2, 0);
}
}
There are also these errors in Unity if that helps
I think your class name is different from file name.
Unity apparently can't handle apostrophes (single-quote ') in the directory name of the editor. You need to get rid of the apostrophe in your directory name. Once you make that change, Unity should be able to build the scripts as intended.
Edit: This has been fixed in more recent versions - see https://issuetracker.unity3d.com/issues/scripts-do-not-get-compiled-if-the-unity-editor-path-contains-apostrophes for reference
First, it is recommended to use "Add component" to create a script, if you want to attach it to a GameObject, as it automatically imports necessary libraries. Implementing MonoBehaviour is necessary for adding a script to a GameObject.
Second, FixedUpdate() should not be set to private, it does not need an access modifier, just like Start(), see https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html.
Third, the errors in your first screenshot seem to imply that there is a problem with your Unity installation. Try reinstalling it and make sure that the Editor you install matches your operating system (64 or 32 bit?).
Fourth, the second screenshot is shown when you use any obsolete libraries or classes, which does not seem to be the case in the script you shared.
Hope that helps.
It's basically because you deleted some script or renamed it or degraded unity version. you might have to reassign the script at the required position/component.
Note: Make sure that class name is the same as the script name in unity.

Can I programatically load scenes in the Unity editor?

I'm using the A* pathfinding algorithm for my 2D game (from my understanding, Unity Nav Meshes don't work in 2D). I would like to be able to pre-calculate navigation grids for all of my scenes, and save them in resource files that can be loaded whenever the player enters a new scene. Rather than having to remember to click "calculate" for every scene -- and remember to recalculate all of my scenes if I make a change to my navigation grids -- I want to be able to programatically have the Unity Editor iterate though each scene and calculate the grids.
Is there a way to create a command in the Unity editor that will iteratively open each scene in the editor and run a method on a MonoBehaviour that's in the scene? Alternatively, is there another way to accomplish what I'm trying to do?
Yes you can!
In editmode you can't use SceneManager but have to use the EditorSceneManager.
First of all you need the scenes you want to iterate.
Could be e.g. a public static field with a list of SceneAsset in the Inspector where you simply reference the scenes
public static List<SceneAsset> Scenes = new List<SceneAsset>();
or you could get them by script e.g. for only use the scenes added to the build settings using EditorBuildSettings.scenes
List<EditorBuildSettingsScene> Scenes = EditorBuildSettings.scenes;
For both you can get a list of the scene paths e.g. using LinQ Select (this is basically a kind of shortcut for a foreach loop) and AssetDatabase.GetAssetPath like
List<string> scenePaths = Scenes.Select(scene => AssetDatabase.GetAssetPath(scene)).ToList();
for the EditorBuildSettingsScene from EditorBuildSettings.scenes you can also simply use
List<string> scenePaths = Scenes.Select(scene => scene.path).ToList();
Now you can iterate over them all and do your stuff by using EditorSceneManager.OpenScene, EditorSceneManager.SaveScene and EditorSceneManager.CloseScene (and if you need it AssetDatabase.SaveAssets)
foreach(string scenePath in scenePaths)
{
// Open a scene e.g. in single mode
var currentScene = EditorSceneManager.OpenScene(scenePath);
/* Do your calculation for currentScene */
// Don't know if it makes changes to your scenes .. if not you can probably skip this
EditorSceneManager.SaveScene(currentScene);
// Finally Close and remove the scene
EditorSceneManager.CloseScene(currentScene, true);
}
// you might be doing changes to an asset you want to save when done
AssetDatabase.SaveAssets();
Before starting you should probably ask to save the current open scene(s) using EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo
if(EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
{
// Saved => the foreach loop here
}
else
{
// aborted => do nothing
}
Than in order to finally start that method the simplest would be to add a [MenuItem]
public static class Calculation
{
[MenuItem("YourMenu/RunCalculation")]
public static void RunCalculation()
{
// all the before mentioned snippets here
// depending how exactly you want to do it
}
}
This will add a new menu YourMenu with one entry RunCalculation to the top menubar of the Unity Editor.
Note:
Since this uses a lot of types (EditorSceneManager etc) that only exist in the UnityEditor namespace you should either place the whole script in an Editor folder (so it is ignored in the final build) or use pre-processors like
#if UNITY_EDITOR
// ... code here
#endif
so in the build the code is also ignored.
Note that I'm assuming so far you also did your calculation in editmode. The thing is if this calculation relies somewhere aon any Start or Awake method you have to call it manually from that editorscript before running the calculation.

SceneManager.LoadScene(string) doesn't recognize scene name

I've seen similar questions all over the internet, but none seem to apply to my situation.
I have a very simple project with two scenes: MainMenuScene and OtherScene. OtherScene is nothing but a blank canvas, and MainMenuScene just has a button which is meant to be used to navigate to OtherScene. The Main Camera has the following script attached to it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LaunchScene : MonoBehaviour {
public void LaunchSceneOnButtonClick(int index)
{
SceneManager.LoadScene(index);
}
public void LaunchSceneOnButtonClick(string sceneName)
{
SceneManager.LoadScene(sceneName);
}
}
and in the OnClick() of the button, this script is called. I have made sure to add both levels to the Build Settings.
If I call the version of the LanchSceneOnButtonClick which takes an integer argument (and specify the appropriate value in the OnClick() method) then the desired scene loads.
However, if I call the version which takes a string argument and use the exact name of the scene I want to load (and I've quadruple checked that it is indeed the exact string, that the string name has no spaces or hidden characters, and have copy pasted the scene name into the OnClick() argument field) the scene does not load and instead I get the error message
Scene "OtherScene" couldn't be loaded because it has not been added to
the build settings or the AssetBundle has not been loaded.
Since using the scene index works, we know it was added to the Build Settings properly, so I reason that there is some issue with the scene name. But I've copied it exactly. I want to avoid using the full path of the scene in case I later decide to move scenes around to different folders, so what are my options here?
Thanks in advance.
EDIT:
Adding screenshots.
Scene in folder structure:
Scenes in build settings:
OnClick() input:
Keep in mind I've also tried the input to OnClick() with and without quotation marks.
The only possible problems are these:
The string passed is different from the scene name; bear in mind, the string used in LoadScene is not case sensitive, i.e. you can use OtherScene, OTHERscene, etc.
The scene in the build settings is not active (i.e. with the checkmark on the left disabled).
The scene isn't present at all in the build settings.
The full path of the scene is irrelevant btw, you can have OtherScene inside any dir/subdir in the Assets, and you'll need only the name of the scene. You need the full path of the scene only if you have more than scene with the same name in different paths (and anyway you shouldn't, it's such an obvious terrible practice).
EDIT: You say that you tried even without " (as you should do, when entering string fields in the inspector you don't need them), what happens if you modify the method body to:
public void LaunchSceneOnButtonClick(string sceneName)
{
SceneManager.LoadScene("OtherScene");
}
Try this and report back what happens please.
I had also the problem that
public void loadScene(string scene)
{
SceneManager.LoadScene(scene);
}
did not work for me in the first place. What did I do? I'm saving the names of my scenes in a List (read from a file) and from that List I choose the scene I need.
But somehow the reading progress seems to give me some unwanted characters so the scene loading does not work as intended. When I added .Trim() it started to work.
For a better understanding, here's an example:
string s = sceneList[1].Trim();
this.loadScene(s);
public void loadScene(string scene)
{
SceneManager.LoadScene(scene);
}
So make sure that you get rid of unwanted characters.