How to make "next scene" button one script - unity3d

When you clear Stage 1, a button is created. Press the button to move to stage 2.
When you clear stage 2, a button is created. Press the button to move to stage 3.
3, then 4, then 5..
Can I make this into one script when moving on to the next scene?
SceneManager.LoadScene("Stage2"); // <-- This method requires multiple scripts.

There are probably many ways .. but as AlexeyLarionov said:
Why not have a
public string targetSceneName;
// or also
//[SerializeField] private string targetSceneName;
configure it in the Inspector and then use
SceneManager.LoadScene(targetSceneName);
You might also be interested in having a Scene field in the Inspector to make this way easier ;)
Alternatively if these anyway are sequencial levels you can also simply go by build index and do e.g.
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);

A nice solution to this would be to have a StageManager class, which holds a List<string> levels of your levels by scene name and an int currentLevel for the current level. Then your StageManager class can have a convenience static method
public void LoadNextLevel()
{
currentLevel++;;
string nextLevel = levels[currentLevel];
SceneManager.LoadScene(nextLevel);
}
The convenience of this is that it would be easier to control the scene flow and less dependent on the order of the scenes in your build settings. If you make the levels properly public or add [SerializeField], you can then easily add new entries to the list and even rearrange them quite simply from the editor. Creating the class in such a way that the method is static would also be very convenient.

Related

How do I arrange a list of buttons into rows of 4

I am trying to display the same game object in a table form of 4 columns and 2 rows so it would look like this:
GO GO GO GO
GO GO GO GO
G0 - gameObject
My gameObject is a button that can be pressed and has a text element on it to display the name of the profile on the button.
I have a List of strings of the names that i need to display on these GO buttons in the table form but i am struggling to position them correctly.
At the moment i have gotten to the point where i can Instantiate them so they all appear on the screen when the game is running, now i just need some advice on how i can position them properly in the format mentioned above.
How do i do this?
This is my code that i used to get the names and add them to the List:
private void GetProfiles()
{
List<string> profileNamesList = new List<string>();
if (Directory.Exists(filePath))
{
string[] files = Directory.GetFiles(filePath);
profileTileTemplate.SetActive(true);
foreach (var file in files)
{
string name;
name = file;
int index = name.IndexOf(filePath + "/", System.StringComparison.OrdinalIgnoreCase);
if (index >= 0)
{
int pathIndexEnd = index + filePath.Length + 1;
int stringLength = name.Length - pathIndexEnd - 5;
name = name.Substring(pathIndexEnd, stringLength);
}
profileNamesList.Add(name);
}
}
DisplayProfiles(profileNamesList);
}
private void DisplayProfiles(List<string> names)
{
}
I have tried using a for loop with in another for loop but i just end up instantiating multiple of the same game object.
This is what i get now:
And this is what i want it to look like:
This is kind of two questions, and I just realized that Unity has a built in component that will do this automatically, so I'll leave the three answers below.
How do I arrange UI gameobjects in rows?
Since it seems like you want to do this for UI elements there's actually a very easy solution. Add an empty GameObject as a child of your Canvas and add a Vertical LayoutGroup component. Add two children to that with horizontal layoutgroups. Add four placeholder prefabs of your gameobject to each horizontal layout group. Arrange them and configure the settings to get them looking the way you want (and make note of what happens if you add fewer than four items!)
Once you have it all set up, delete the placeholders. Then you can add your gameobjects to the horizontal group using Instantiate(Object original, Transform parent) (link) to parent them to the layout group, which will keep them arranged neatly. You can keep a list of those groups and each time you add four, switch to the next parent.
A neater way that seems to fit your use case (assuming there can potentially be more than 8 profiles) is to make a Scroll View that holds horizontal layout groups, which will each be a row of entries. That way instead of tracking which parent you want to add gameobjects to, you can just instantiate a new row every time you pass four entries.
If you're sure there will only ever be eight or fewer, the easiest thing to do would just be arrange eight blank buttons in the UI however you want them to appear. Then keep a list of the eight buttons and edit the text/image on them, no instantiation or looping necessary.
How do I split up a list of gameobjects into rows?
The actual code to process the list is below. This is just an example and there are plenty of different ways to do it, but I thought this demonstrated the logic clearly without depending on what UI elements you choose. As a rules of thumb, make sure to figure out the layout elements you like in Unity first using placeholders (like scroll view etc) and then figure out the code to fill them in. In other words, instantiating and laying out UI elements at runtime is a great way to give yourself a headache so it's best to only do it when you need to.
List<string> profileNamesList = new List<string>();
public int entriesPerRow; //only public so you can edit in the inspector. Otherwise, just use the number per row in your prefab.
public GameObject profileRowPrefab;
public GameObject scrollViewLayout;
private void DisplayProfiles(List<string> names)
{
int i = 0;
while( i < names.Count ) //"while the list has more names"
{
//create a new row as a child of the scroll view content area
//and save a reference for later
GameObject go = Instantiate(profileRowPrefab, scrollViewLayout);
for(j = 0; j < entriesPerRow; j++) //"add this many names"
{
if(i < names.Count)
{
//instantiate a button, or edit one in the row prefab, etc.
//depending on how you're doing it, this is where you'd use the go variable above
YourProfileButtonCreationMethod(names[i]);
i++;
}
else
{
//we've finished the list, so we're done
//you can add empty placeholders here if they aren't in the prefab
break;
}
}
}
}
YourProfileButtonCreationMethod will depend completely on how you want to implement the UI.
I wish I had thought of this an hour ago, but I've never used it myself. Unity has a built in layout feature that will do this for you (minus the scrolling, but you may be able to nest this in a scroll view).
How do I arrange UI elements in a grid?
Instead of making your own grid with horizontal and vertical layout groups, you can use the Grid Layout Group. Then just instantiate each item in the list as a button with the grid layout as their parent (see above). Here's a short video tutorial that shows what the result looks like.

How to have custom script icons other than using "Assets/Gizmos" in Unity3D

I know this was asked a lot of times probably .. but it is very often answered wrong.
What I want is:
Use a custom icon for specific components/scripts in the Inspector (e.g. Figure 2 and Figure 3) and the ProjectView (e.g. Figure 1)
What I do so far:
For each component/class that shall have the icon I have an accroding Icon file in the folder
Assets/Gizmos/<Path>/<To>/<Namespace>/<ClassName> icon
and in the Import Settigns set TextureType to Editor GUI and Legacy GUI
This is working fine .. and until now the only way how I could achieve that (having in mind the below section What I definitely do NOT want).
But
However, I wondered if there is really no better way having to have a unique Icon file for each script. This makes the project/UnityPackage unnecessarily huge. Also if I rename a class I always have to rename the according icon file as well ... This imply doesn't feel right!
Most Unity build-in Behaviours and Components have a unique icon. But also external Packages coming from the new PackageManager have built-in icons and sometimes a Gizmos folder but it is not following the above naming rule ... so apparently the icon is configured somehow else for them.
Therefore my questions:
Is there any better way to have those icons for scripts/components?
Preferably scripted and reusing ONE single icon file instead of having the same icon in multiple differently named files.
And/or also Where/How are those icons defined for the scripts coming from the PackageManager?
!NOTE! What I definitely do NOT want:
Show the Icon also in the SceneView for all GameObjects having those components attached (e.g. Figure 4). This is caused by either selecting the icon for this script via the Inspector as in Figure 5 (as allways suggested e.g. in this post or here and even by Unity - Assign Icons ) or using OnDrawGizmos or DrawGizmo. This is not happening using the approach I use currently with the Gizmos folder!
Update
Because this was suggested in this answer: I also know that I could do that and turn them off via the Gizmos settings of the SceneView. But imagine I have like 25 different modules and various different icons each. I don't want to have to disable their Gizmos in the SceneView settings one by one on a per project basis! Even the provided script seems like a vast hackaround. Reflection would be the very last resort I would ever take. Also I'ld prefer to not even have those icons appear as possible Gizmos at all instead of disabling them all.
You can set the icon with figure 5 and then turn the gizmos for that icon off from the gizmos drop down.
Edit: Injunction with the step above you could try this script derived from here it uses reflection to find the class responsible for turning off the the gizmos and icons. This would execute any time your scripts recompiled to keep those icons off or if you added any new icons to the autohide icon file. Note: scriptClass will be an empty string for built in components eg.Camera, AudoSource
using UnityEditor;
using System;
using System.Reflection;
public class DisableAllGizmos
{
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnScriptsReloaded()
{
var Annotation = Type.GetType("UnityEditor.Annotation, UnityEditor");
var ClassId = Annotation.GetField("classID");
var ScriptClass = Annotation.GetField("scriptClass");
var Flags = Annotation.GetField("flags");
var IconEnabled = Annotation.GetField("iconEnabled");
Type AnnotationUtility = Type.GetType("UnityEditor.AnnotationUtility, UnityEditor");
var GetAnnotations = AnnotationUtility.GetMethod("GetAnnotations", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
var SetIconEnabled = AnnotationUtility.GetMethod("SetIconEnabled", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
Array annotations = (Array)GetAnnotations.Invoke(null, null);
foreach (var a in annotations)
{
int classId = (int)ClassId.GetValue(a);
string scriptClass = (string)ScriptClass.GetValue(a);
int flags = (int)Flags.GetValue(a);
int iconEnabled = (int)IconEnabled.GetValue(a);
// this is done to ignore any built in types
if (string.IsNullOrEmpty(scriptClass))
{
continue;
}
// load a json or text file with class names
const int HasIcon = 1;
bool hasIconFlag = (flags & HasIcon) == HasIcon;
// Added for refrence
//const int HasGizmo = 2;
//bool hasGizmoFlag = (flags & HasGizmo) == HasGizmo;
if (/*Compare class names in file to scriptClass == true*/)
{
if (hasIconFlag && (iconEnabled != 0))
{
UnityEngine.Debug.LogWarning(string.Format("Script:'{0}' is not ment to show its icon in the scene view and will auto hide now. " +
"Icon auto hide is checked on script recompile, if you'd like to change this please remove it from the config",scriptClass));
SetIconEnabled.Invoke(null, new object[] { classId, scriptClass, 0 });
}
}
}
}
}
Shown in the inspector with a gizmo
Hide Icon from gizmos dropdown
Icon still appears in the inspector and in the project view but not in the scene
So I did a bit more research about built in types as well as packages coming from the package manager and the asset store. Anything that is external (packagemanager or assetstore) if it has a custom icon for the script and inspector it will Always have a gizmo in the scene view. As it has its icon set using your figure 5 example, as seen in the screenshots with the debug inspector.
Also if you want to set the icon with a script or hide it ,currently reflection is your only option as these APIs are not publicly accessible.
My Script showing the debug inspector for its script
PixelPerfect package script from the packagemanager in the debug inspector
PixelPerfect Icon showing in the scene
I was hoping to add this as a comment to your original question but not enough rep yet.

Codename One Drag & Drop get target

I have an application with some labels and containers. I want to drag the labels into the containers and assert that the containers receive a specific label. (A game for kids [starting with my 6-year-old daughter, who is learning to read], where the next level can be accessed after the labels are arranged in a specific order to form words or phrases.)
For the moment, I am using something like this :
label_1.addDropListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String string = label_1.getParent().toString();
}
But this approach only gets the value of the container where the label has been before, and not the value of the drop target.
I could get the current position by a new button, but I'd rather solve this through the drag & drop operation.
There seems to a draggingOver method (like in JavaFX), but I can't figure out a way to use it.
Any kind hint would be appreciated.
The best approach is probably to subclass Container where you can override the drag over. In that case you will also know the container instance.
In the case of the listener you would need one listener per container and that way you could have the container reference.

Show/ hide Unity 3D elements

I hope I am posting in the correct section. I know that it is possible to write a custom code in Unity so I have the following questions:
Imagine a house model in Unity. Would it be possible to have a code which helps to hide/unhide certain objects? For example, letter "W" would hide/unhide all windows, letter "C" would hide/unhide all columns etc.
If it would be possible to develop a code for that, what would be the workflow? How would Unity know what is window and what is door?
Taking one step further.. Would it be possible to have a code that unhides the next step of the project. For example, the first step would be building foundations. Would it be possible to have a code that would unhide the next step, say, 1st floor floor element, with a klick of a keyboard key? And then with the same key unhide the next step which might be 1st floor walls. And would it be possible with another key go backwards?
If such code would be possible, what do you think would be the workflow? How would Unity know which element is in which step?
Yes just have a class with an array of objects to show/hide and another property for what button will do it. Then just have a method that will hide/unhide each object in that class. In the update method of a behavior just check the input and call the method of the class based on what button was pressed.
Would it be possible to have a code which helps to hide/unhide?
Yes, you can do that by calling GameObject.SetActive() function
door.SetActive(true); // door is a game object;
How would Unity know what is window and what is door?
You can give the window/door a name, then access the game object by name
var door = GameObject.Find("MyDoor") as GameObject;
Would it be possible to have a code that would show the next step, say, 1st floor floor element, with a klick of a keyboard key?
Yes, you can do that with code snippet below:
int step = 1;
void Update() {
if (Input.GetKeyDown("space")){
print("space key was pressed");
step++;
}
if(step == 1) {
// do sth
}
else if(step == 2) {
// do sth
}
}
Given the above snippet, your last answer can be easily deduced.
I see 2 ways of doing what you asked.
1st way
GameObject[] walls;
walls = GameObject.FindGameObjectsWithTag("Wall");
foreach (GameObject wall in walls)
{
wall.setActive(true);
}
What you will have to do, besides the code, is to assign to those object a correct tag (like "Wall" "Window" "WatheverYouWillNeed"). So you can easily find all objects by giving them some kind of order (with tags).
Best practice tip
You may want to create a static class "Tags", and set public constants string inside the class, with all tag names.
public static class Tags
{
public static const WINDOW_TAG = "Window";
// ... more tags
}
2nd way
If what you want to set is only "visibility", you may want to modify only camera tag rendering. It doesn't even require any cycle at all. When you want to view windows, you just tell your camera to render the tag "Window".
// Turns on Windows Layer on mask using an OR operation
private void Show()
{
camera.cullingMask |= 1 << LayerMask.NameToLayer("Window");
}
// Turn off the bit using an AND operation with the complement of the shifted int:
private void Hide()
{
camera.cullingMask &= ~(1 << LayerMask.NameToLayer("Window"));
}
It may look odd the second option, but keep in mind that the cullingMask is composed of bits, and every bit is a Layer defined by your tags. The "Everything" culling mask is 111111. If you want to see only Window, for example, and window is the last element, your culling mask would look something like 0000001
Hope it helped! :)

open and play a scene in Unity3d

I have done a project with many scenes in Unity3D.
In the first scene there are buttons, each of them will play a scene when clicked.
For example, if the player clicks the button “Show the balloon”, then the scene called Balloon (which contains a balloon object and its animation) will be opened.
How can I do it using JavaScript code?
See Application.LoadLevel(...).
From the documentation:
[...]. Before you can load a level you have to add it to the list of levels
used in the game. [...]
// Loads the level with index 0
Application.LoadLevel (0);
// Load the level named "HighScore".
Application.LoadLevel ("HighScore");
First thing you have to do is add all the levels you want into the Build Settings Property.
Go to Unity or File Menu, Build Settings, and drag and drop your scenes into the scroll window. Then it'll assign them a logical number (or you can reference by name).
Application.LoadLevel(0); // this loads the first level in the list
Application.LoadLevel("nameoflevel"); //does the same thing numerically except by name
Application.LoadLevel(Application.loadedLevel); //reloads current level
Application.LoadLevel(Application.loadedLevel + 1); //loads the next level in order
Application.LoadLevel(Application.loadedLevel - 1); //loads the prior level in order
Application.LoadLevel(Application.levelCount - 1); //loads the last level in list
The int version of LoadLevel takes the id from build settings.
You can also call the string version, which takes the scene name from the project view (Though it still has to be in build settings for it to be found)
Go to File->Build Settings and drag your scenes there then use following.
Application.LoadLevel("Ballon");
If you want to reload the current level, you can use
Application.LoadLevel (Application.loadedLevel);
You'll, of course, need to make sure to manually reset or destroy anything that was created by the scene and marked as DontDestroyOnLoad.
And yes, the only way to put levels in any order in your build is from the build settings menu. You can jump around to which level is loaded by specifying its name or build order, but if you wanted to insert your levels in order in the build sequence and just want to jump from one level to the next (ie, Menu->Level1->Level2->EndGame), you can use
Application.LoadLevel (Application.loadedLevel + 1);