Unity SetActive(True) Not working? - c#

so I've been spending the past 9 hours trying to fix this. I have a weapon attached to a plane. I want this weapon to appear and be functional, after I get a specific number of kills. It does dissapear when I want it to, but it does not appear back. Also, I cannot use it while it is not visible.
Suggestions? Anyone who can see the problem here, is my saviour!
private GameManager game;
GameObject weapon_rocket;
// This works - Start class removes the object any creates any necessary referances
public void Start ()
{
weapon_rocket = GameObject.Find("weapon_rocket");
weapon_rocket.SetActive(false);
GameObject Player = GameObject.Find("Player");
game = (GameManager)GameObject.FindObjectOfType (typeof(GameManager));
GameManager gameManager = Player.GetComponent<GameManager> ();
}
// Here it doesn't recognise SetActive(True)
public void SwitchWeapon ()
{
if (game.Killed >= 1) {
weapon_rocket.SetActive (true); // this does not make the weapon reappear for some reason
CurrentWeapon = 3; // this makes the weapon usable - doesn't work when the weapon is not visible
}

null Reference Exception Already gave you a hint.
C# has a Garbage Collector as well as Java and any other programs.
Meaning, if your GameObject is Inactive and there is no Pointer/ Reference on it. It will be eligible to be garbage collected and destroyed to free some memory. It is Automatic unless you override the Finalize() function. Which I don't recommend if you don't know how CLR C# works.
To simply fix your problem. I recommend Referencing it first so the Garbage collector will ignore it.
In your Start(), you already Reference your Object so that is not going to be Garbage collected.
But I would bet that in your Editor. Your GameObject is grayed already. Meaning you have set it by InActive by default. That is why your GameObject.Find is throwing an Exception already. Make sure it is active So GameObject.Find can reference the Object First "BEFORE" Setting it to inactive. Or else. It is Garbage Collected already. Or worse, not even going to be Instantiated in the first place.

If you just want to make the object invisible, you could consider just disabling the mesh renderer instead of the entire object. And see if that allows it to be set to true and bring it back.

It's been a while since I have been in Unity, and still somewhat new to it myself. However, from what I remember there was an issue of a deprecated feature/object/method about setting the visibility of a game object. What it ended up being moved to was to the "BEHAVIOR" of a control and setting it from there.
So, that said, and that it HAS been a while, you can probably search on unity "Behavior"
But looking at this Unity link, it also states that if the parent object is not active, neither will any child under it.
So, I hope this can help further identify and resolve your issue. I will check back on this later tonight after work if not already resolved by then.

you must convert the GameObject weapon_rocket to
GameObject weapon_rocket = null;

Related

Unity 5 C# - How to Change Scenes and Import all Resources from Last Scene

I'm not sure how to switch scenes and bring all of my resources with me. I do understand that upon load of new scene, the previous scene gets destroyed on load. I've explored some with DontDestroyOnLoad() but had no luck with what I'm trying to do.
I tried to make my player controller a prefab and simply put him into the next scene; however, I returned a heck of a lot of errors because of the many scripts I have. Mostly stuff like checkpoint, HP bars, and even the weapon.
What I need to know is how to import everything into the next scene. How do I do this without having to recode or even re-make all of the stuff that I need?
You're looking for LoadSceneMode.Additive. This is the second parameter of the LoadScene method and will load the new scene into the current one.
If you need to import every object from the previous scene, then what's the point in creating a new one?
What you could do is saving the objects positions into a file and then loading that file back on the next scene or try (again) with DontDestroyOnLoad();
I recommend to check the documentation of Unity about this function.
If you want an individual object not to be destroyed on the scene change then on the void Awake() function of Unity make a DontDestroyOnLoad(this.gameObject);
Could you provide more information? I ask because it seems from your description that
DontDestoryOnLoad
should accomplish what you want but you say it does not. As long as the object holding the components whose states you want to save is persisted into the next scene using that method, then all of those components' states should be persisted as well. Please elaborate and we can possibly provide a better answer. As for how to use it to save the state of every game object:
GameObject[] allObjects = UnityEngine.Object.FindObjectsOfType<GameObject>();
foreach(GameObject go in allObjects) {
if (go.activeInHierarchy) { /* and any other logic you want. Maybe like !isTerrain */
Object.DontDestroyOnLoad(go);
}
}
For the above code, I ripped it from https://answers.unity.com/questions/329395/how-to-get-all-gameobjects-in-scene.html

How to delete an object in Unity in ExecuteInEditMode

What I am trying to do
I am trying to have one object with a serialized int that will spawn the number of objects I specify. When I change the number to a lower number, it should obviously delete and destroy the previous ones created.
This is causing an issue, however, do to the way Update works with ExecuteInEditMode, in that it gets executed whenever the scene gets changed, making this much harder.
What I've tried
[ExecuteInEditMode]
public class Floor : MonoBehaviour
{
[SerializeField] GameObject gameObject;
[SerializeField] bool destroy;
private void Update()
{
if (destroy)
{
destroy = !destroy;
gameObject.Destroy();
}
}
}
Unreal Engine used this pattern a lot of having a visible bool that turns itself off and behaves more like a button in the editor, which came in handy. This would allow me to press destroy and destroy the object. Obviously, without the check, it would destroy gameObject, and Update is called again, it will destroy it again and so on.
I thought by added this boolean check, when Update was called again, it wouldn't do anything so the loop would stop, but nope, it continues and gets me an infinite loop.
I've also tried using a Corroutine, but that didn't fix anything.
Is there any way to delete an object in ExecuteInEditMode without causing an infinite loop? Maybe there's a better method than Update that doesn't update when anything in the scene changes?
Try
GameObject.DestroyImmediate(gameObject);
in Edit mode: https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html
Use DestroyImmediate() in edit mode since Destroy() is delayed(delayed deconstruction will never be executed in edit mode).
unity docs: https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html

Coroutine wrong Behavior when scene is loaded

Ok so I have this coroutine :
IEnumerator ShowCharTraits()
{
while(!hasPlayerChosen)
{
yield return null;
traitPanel.SetActive(true);
}
hasPlayerChosen = false;
traitPanel.SetActive(false);
// Debug.Log("Got called! job done");
}
It's being called like this from the awake method in my GameManager:
players = GameObject.FindGameObjectsWithTag("Player");
foreach (GameObject g in players)
{
ui_Controller.StartShowCharTraits();
g.GetComponent<PlayerToken>().isTurn = false;
}
StartShowCharTraits() is a simple method that does this :
public void StartShowCharTraits()
{
StartCoroutine("ShowCharTraits");
}
Now, I have checked the tags, no null reference exception, actually no errors or warnings are being thrown. If i load the scene in the editor and then play it everything works fine. traitPanel.SetActive(true); get called and my panel shows up. However when I load my scene from another scene using SceneManager.LoadScene(1); the above mentioned line is never reached. Any ideas why this is happening ?
Say you want to have one central place that is "like a singleton" in a Unity project. Example,
SoundEffects
LapTimer
Scores
SocialMediaConnections
All you do is this.
make your script SoundEffects.cs
recall that every Unity project must have a "preload" scene. (it's impossible to not have one)
in the preload scene, have a empty game object called "holder". make sure it is marked "DontDestroyOnLoad"
attach SoundEffects.cs to that holder
you're done.
there's just nothing more to it.
you're finished.
it's "just that simple"
So, any particular script, which happens to be attached to any particular object, in any particular scene, may need to access "SoundEffects"...
To do so, simply do this in Awake:
SoundEffects soundEffects = Object.FindObjectOfType<SoundEffects>();
then just use soundEffects anywhere in that script, for example soundEffects.PlayBoom(13) etc etc.
So in Awake()
Laps laps = Object.FindObjectOfType<Laps>();
Social social = Object.FindObjectOfType<Social>();
AI ai = Object.FindObjectOfType<AI>();
or whatever.
Unity is simple. Incredibly simple. It's just that easy.
write your script, LapTimer.cs or whatever
put it on a holder object in your preload scene (where else could it be?)
there's no "3", that's all there is. It's just that ridiculously simple.
Note that...
In the early days of Unity, someone unfortunately mentioned "singletons" on a QA board somewhere. (You can't have "singletons" in an ECS system, it's meaningless.) At the time, this led to huge discussions about how you can make a "singleton-like thingy" in Unity, which is piling confusion on confusion. Unfortunately from that day to this, you get people learning Unity, who see "singleton" mentioned here and there on the net, and it leads to endless confusion.
Once again, note that the idea of "managers" is just impossibly simple in Unity - explained above. It's trivial. It just couldn't be easier.
Note, above I mention you might want syntactic candy to avoid the incredible chore of typing Laps laps = Object.FindObjectOfType<Laps>();
There are very unfortunately no macros in Unity/c# so you need another way.
All you do is use a "Grid" script http://answers.unity3d.com/answers/1124859/view.html which has been popular for years in Unity.
But honestly, it's so simple to use Scores scores = Object.FindObjectOfType<Scores>(); that I usually just do that nowadays.
Ok how do I explain this. I have a singleton that acts as a data holder. While developing the scene with the game manager I had attached the singleton to the gamemanger object that hold a bunch of scripts. Now when I made the main menu I ofc added my singleton to it so I can carry info to the game scene and because of this my whole game manger object was being deleted. This is the culprit from the DataHolder :
void Awake()
{
if (instance == null)
instance = this;
else if (instance != this)
Destroy(gameObject);//This right here.
DontDestroyOnLoad(gameObject);
}
So I changed that line to Destroy(gameObject.GetComponent(instance.GetType()));

Unity c# - NullReferenceException: Object reference not set to an instance of an object

Im having an error during runtime with my image and text. I have both objects created in my hierarchy named correctly but apparently my script cant find them. Why isn't what i have written not sufficient? All i get in the error is Object reference not set to an instance of an object, but i don't understand why i need to create an instance of this object when i have one in my hierarchy.
I'm still relatively new to both unity and c# and couldn't find any real explanatory answer by searching and the unity tutorials weren't very helpful since I'm sure its just a basic question about c#
private Text serverInfoText;
private GameObject serverInfoImage;
void Awake()
{
serverInfoImage = GameObject.Find ("ServerInfoImage");
serverInfoImage.SetActive (false);
serverInfoText = GameObject.Find("ServerInfoText").GetComponent<Text>();
}
Impossible to say without looking at your scene.
Things to try:
GameObject.Find only works on active game objects. Make sure the game objects are not greyed out in your scene view.
Double check the name strings are correct and use Debug.Log to sanity check.
You don't mention which line the actual exception occurs. In your above code, it's possible to throw an exception in two locations: on SetActive() if serverInfoImage is null, or on GetComponent<Text>() if the ServerInfoText object is not found. Read the actual exception message you get and make sure you are looking at the correct line/object.
Since your objects are already created in your scene, there's no advantage to using GameObject.Find to get references to the objects. It would be more efficient to directly set the references to the objects via the inspector. This option has the added benefit of working with disabled GameObjects. Either make your two member variables private, or use the SerializeField attribute to make the properties visible in the inspector.

Unity MissingReferenceException when loading same scene for second time

I'm trying to create Arkanoid 3d game using Unity with C#. I've created simple Menu (Scene 0), where I can start my game, my main scene where actual game takes place(Scene 1) and Scoreboard (Scene 2), which is shown after losing all 3 balls Player has at start. After pressing any key i go back to Menu and can start game again. And this is where problem begins.
During second game after loosing 1st ball, my game goes crazy. I get loads of "MissingReferenceException"s like one below (but some linked to other objects (like GUIText's etc):
MissingReferenceException: The object of type 'Player' has been destroyed but
you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
Player.BallLost () (at Assets/Player/Player.cs:164)
GameEventManager.TriggerBallLost () (at Assets/Menagers/GameEventManager.cs:30)
Ball.Update () (at Assets/Ball/Ball.cs:47)
I noticed loads of MissingReferenceExceptions that are casued by not assigning variables. But this feels kinda diffrent for me since it all works perfectly during "1st play". What can cause this problem? I cheked in inspector after launching game for the second game and all variables are assigned to objects.
I'm not sure if shoudl insert game code since it has grown rather big and is split into >10 scripts.
In my case, the problem were two static events. One assigned to call a method whenever it was raised (created by another class), and one created in this class to inform other classes for the occurance of something.
So I just added the following two in the OnDestroy() method:
OtherClass.onNewX_event -= X_eventHandler;
for the fist one (where OtherClass was the other class which was raising the onNewX_event and the current class was handlening it)
onThisClassEvent = null;
for the event created and raised in this class.
I'm guessing you used Application.loadLevel(xx). This is what I found out about it:
Reloading the scene should reset all the variables unless you are using static variables because logically creating a new instance of every object would reset its values to their initial state.
Static variables on the other hand are not destroyed because they are part of a class, not an instance. You have to reset these manually.
DontDestroyOnLoad() is a little different. It tells Unity not to destroy an object when you load a new scene. So these objects won't be reset either because they aren't being destroyed and recreated.
The only way to reset them is just to manually go through and turn the variables back to some initial state. It is your choice how you do that. You can either save all the initial values, or copy the values over from a newly instantiated class.
As an addition I'd like to say if you use static variables, it might be more useful to put them all in a Singleton or change them into non-static variables.
Include below function in your GameEventManager class
public static void Nullify(){
GameStart = null;
GameOver = null;
LevelWon = null;
GamePause = null;
GameResume = null;
BallLost = null;
}
and call this function (GameEventManager.Nullify();) in Menu(scene0) before loading other scenes ;
GameEventManager.Nullify();
Application.LoadLevel("Scene1);
Hope this help...... :-)

Categories

Resources