Modify GameObject Component values from custom EditorWindow - c#

I've created a custom window with a range of buttons. When a game objects are selected, and a button is pressed, the myPrefab value of the MyScript component of the selected game objects are set to a particular prefab (according to which button is pressed).
This is working up until the point where I press play. I may have 10 game objects with the MyScript component, and using the buttons set each of them to contain a particular prefab. In the inspector, I can see the prefab value has updated for each of the game objects.
However, as soon as I press the play button, any modifications made by the buttons is undone.
To clarify, if I set the prefab in the inspector, then with a button, it will revert to the one set in the inspector. If I simply set it by the inspector, it won't revert. If it is by default null, and only set by the buttons, it will revert to null. (Only the button results are being reverted).
Could anyone work out why this is the case? Is there some sort of confirm or save method I should be calling to "lock in" my choice?

Simply add "EditorUtility.SetDirty(component);" after the value is modified.
This marks the object as needing to be stored (instead of simply being the value shown in the editor).
In the inspector, things are marked as dirty as soon as you change them. Changing them through other editors like this however, means that the the object must manually be marked as dirty.
if (GUI.Button(rectangle, GUIContent.none))
{
foreach (GameObject go in Selection.gameObjects)
{
MyScript component = go.GetComponent<MyScript>();
if (component == null)
continue;
component.myPrefab = firstPrefab;
EditorUtility.SetDirty(component);
}
}

Related

Inventory can close once, but fails to open again

I'm creating an inventory system (using Unity 2021.3.4f1) , and want it to be able to pop up/close by pressing the same keycode. The method I've seen others using for this doesn't seem to work for me, since I'm only allowed to close the inventory once, if I start the game without unchecking the inventory. Nothing happens when I press the same key again.
Here's what I've used for the Update()
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
inventory.gameObject.SetActive(!inventory.gameObject.activeSelf);
}
}
Once you disable the game object the script becomes disabled as the game object and it will not run.
what I suggest you do I make a parent game object and attach the script to it and when you want to disable you have to disable the child

How to group a bunch of objects into one gameobject on a button press

So i challenged myself to make a little game where you build a rocket and then you press the button it launches
i want to it to group up all of the objects and adds a placement script to the parent object all within a script i do not know if this is even possible in unity but if there are other methods or others that are better
using tags did not work i want to let them group up and launch!
Each time you instantiate a piece, cache a reference to it. When it's time to launch, use the first cached reference as the parent and then, for each other piece, set its parent to be the first piece. It'd look something like
for(int i=1; i<parts.Count; i++)
{
parts[i].transform.parent = parts[0].transform;
}

Unity - Assign Button in Scene to Prefab

I'm having trouble assigning two Buttons to the Prefab after it is instantiated.
The buttons are in the scene and i don't know how to assign them.
Drag and Drop doesn't work of course. I'm aware of that.
When I make something like
btnnext = GameObject.Find("Next").GetComponent<Button>();
in the Start() function of the Prefabs script it doesn't work either.
Are there any other workarounds?
As #slowikowskiarkadiusz said GameObject.Find is not the best solution, because it's slow and error prone. But there is an easy solution.
On the script which is placed on the prefab make a public function, called AssignButton:
class ScriptOnPrefab : MonoBehaviour {
public void AssignButton(Button button) {
btnnext = button;
}
}
In the script where you instantite the prefab, you then link the buttons and assign them:
var instance = Instantiate(prefab);
var scriptOnPrefab = instance.GetComponent<ScriptOnPrefab>();
scriptOnPrefab.AssignButton(button);
Note: For this to work that the ScriptOnPrefab has to be on the root of the prefab, note on child objects.
Note: prefab is linked as a GameObject.
Note: If you link the prefab as ScriptOnPrefab you can skip the GetComponent step and immediatelly call the Assign method.
By 'doesn't work either' you mean that btnnext is null or you mean that .GetComponent<Button>() throws an exception? The first case would mean the object named "Next" that was found doesn't have a Button component on it. You can check if you're expecting it to have the Button component or maybe something slightly different. You could also have multiple objects named "Next" and the one you're getting is not the one you expect to get. The second case would mean that your object is most likely inactive. Find(string) doesn't search within inactive objects.
That being said - Find(string) is not reliable in any capacity and I would advice to avoid it (it's also terribly slow). Instead I would create a script to be placed on the object with the button. Inside of that script in the Awake() method I would assign the instance of the Button component to some kind of a public static field, so the other script can later pick it up (if you are dealing with two buttons it might be a list or two separate fields. Depends on your case I guess).

Make gameobject unselectable in the Editor window

I have a fadepanel gameobject in my scene that has to sit on top of all the other gameobjects. However, when I click on an object int the editor window, since this gameobject is on top of all, is the one that is automatically selected in the hierarchy.
Is there a way to keep the gameobject on top of the canvas, as it is right now, but make it completely unselectable wIen i click on my scene?
You can use HideFlags on gameobject to make it unselectable:
public class HideFlagsSetter : MonoBehaviour
{
public Component target;
public HideFlags customHideFlags;
public enum Mode
{
GameObject,
Component
}
public Mode setOn = Mode.GameObject;
[ContextMenu("Set Flags")]
private void SetFlags()
{
if (setOn == Mode.GameObject)
{
target.gameObject.hideFlags = customHideFlags;
}
else if (setOn == Mode.Component)
{
target.hideFlags = customHideFlags;
}
}
}
Setting customHideFlags to HideInHierarchy would make it disappear from hierarchy so you won't be able to select it.
Edit: As the object will disappear, there is no way to bring it back if you can't access the script. So this script should be attached to a persistent object and target object should be set in the inspector.
You can use Context menu option by clicking on the gear icon in the top right corner and choose "Set Flags". its the last option in the menu.
Read more
Hope this helps :)
(ADDED BY PERSON WHO ASKED THE QUESTION)
I wanted a way for this to automagically happen on editor mode. So i did the same steps, but i changed the script a bit to work on Editor mode. I added [ExecuteInEditMode] on top of the class and also added an Awake() method that executes the same code as in SetFlags. Seems to work just fine.

Load scene using canvas button

void OnMouseDown() {
SceneManager.LoadScene ("Scene2");
}
I have tried every conceivable method. The method posted has worked for me using GameObjects with colliders. Instead, this time I am using a button on a 2D canvas. It does not work in this context.
How do I load a new scene using a button in a canvas? I have tried so many different things. This should be simple.
Thanks for any advice.
Here (link: Unity page) you can find a video tutorial how to use Button on canvas in UnityGUI. It's for Unity 4.6 but its really simillar to newest (5.3.1).
It's quite simple. U can make a script with public method e.g
public void LoadScene2()
{
SceneManager.LoadScene ("Scene2");
}
Attach this script to some GameObject e.g Controller. And add event in Button inspector.
In my opinion there is a better solution for the one shown by #Paweł Marecki
I use this in my projects.
OK so you will simply create a script called ButtonManager and inside it you can make a method like this
public void ChangeToScene(string sceneName)
{
Application.LoadLevel(sceneName);
OR
SceneManager.LoadScene(sceneName);
}
Now you have your canvas button, you will select it and look for "Event Trigger"
(i got this image from google to help) add a new mouse down event.
Create an empty GameObject on your Scene, name it "ButtonManager" and drag it onto the event box.
Now you need to click that dropDown list and find your "ChangeToScene" method.
You will see that an editor field appears below, type your desired scene name and hit play :P
This way you will always use this script when you want to change scenes.
You can add other methods and add functionality, but the beautiful part is that you dont need to create a method each time the name of the scene changes.

Categories