How to delete an object in Unity in ExecuteInEditMode - c#

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

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

Unity Script with an Update Function attached to multiple Objects

//GUI Function
private void Update()
{
healthMeterPos.position = WorldToGuiPoint(new Vector2(position.xPos,position.yPos));
}
This is my Update Function which is in a Parent class from which all my gameobjects inherit problem though is that it's only updating the Position for the first GameObject not all of them. Anybody know why?
When you write healthMeteorPos.position = ..., unless healthMeteorPos is either public or [SerializeField] and set uniquely to each one of the objects separatedly, all the object basically execute the same command over the same target which is one object healthMeteorPos.
If you post a little more code we could help more, but generally speaking, if you want every object to affect itself, use transform.position instead of assigning the position of another shared object.

How to execute a sound when an object goes through another object?

Hey StackOverflow community, I am making my very first game and I've run into a problem. The game is about a ball dodging obstacles in order to reach the end of a level. So my issue is that I want to implement a "Woosh" sound whenever the ball passes an obstacle. I have created an invisible object which is supposed to execute the "Woosh" sound whenever the ball passes the invisible object.
These are the settings on the "invisible" object:
If you look at the image you can see that there is a "Woosh" script which contains these lines of code:
using UnityEngine;
public class Woosh : MonoBehaviour
{
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Player")
{
FindObjectOfType<AudioManager>().Play("Woosh");
}
}
}
This code is supposed to make the invisible object play the "Woosh" audio whenever it collides with the Player. However, when I try it out in game, the audio never gets played when I pass the invisible object.
For your information, I do have an audio manager, which contains all my sounds that I have implemented so far. It can be seen here:
Note: All the other sounds work, but not the "Woosh" sound.
Any help is appreciated!
Thanks in advance,
E.W
Comments aren't sufficient.
What I'm trying to tell you is that you can't just automatically assume that the problem is with the "Woosh" sound. That's just one of the things that can go wrong. You have this code:
public class Woosh : MonoBehaviour
{
void OnCollisionEnter(Collision collisionInfo)
{
if (collisionInfo.collider.tag == "Player")
{
FindObjectOfType<AudioManager>().Play("Woosh");
}
}
}
Your expectation is that when OnCollisionEnter is called, the "Woosh" sound will be played. You say the sound isn't playing, so you have to figure out what's wrong. This is what I would check:
Can you make the "Woosh" sound play somewhere else? You should be able to add code to your program to make the "Woosh" sound play. Maybe replace code that plays "ShatterSmall" with "Woosh". If the sound doesn't play there, then there's probably something wrong with the "Woosh" sound, and you need to fix it. If the sound does play there, then there's some other problem.
If "Woosh" plays in other places, but not in this code, then you have to check to see if the code is even being executed. If you're running this code in your debugger, put a breakpoint on the OnCollisionEnter method to see if it gets called. If it doesn't get called, then the problem is somewhere else. If you don't have a debugger, then you can output some kind of message like "Hey, I got here!" to tell you that the OnCollisionEnter function actually was called.
If you're getting to OnCollisionEnter, then you need to check to see if collisionInfo.collider.tag does indeed contain the value "Player". Again, use some kind of output function to tell you what is in that variable.
If collisionInfo.collider.tag == "Player", then check to see if the call to FindObjectOfType<AudioManager> returns the expected value.
You can break up your code:
var mgr = FindObjectOfType<AudioManager>();
if (mgr == null)
{
// some error here. Maybe throw an exception.
}
else
{
// Make sure (somehow) that it's really the object you wanted
}
mgr.Play("Woosh");
If the above tells you that you're getting the right object, then perhaps there's a problem playing the sound. Does Play throw any exceptions?
The point I'm trying to make here is that debugging involves questioning all of your assumptions, and doing tests to see where things are failing. This is best done with a debugger, because it lets you move through your code step-by-step to see exactly what's happening.
If you don't know how to use the debugger, now is the perfect time to learn. It will save you days of debugging.
It won't be making the sound because your collider is a trigger not a collision, so if you disable that box of Is Trigger, the sound will play when you collide with it.
If you want to pass through the collider like a trigger you need to use this functions.
void OnTriggerEnter(Collider other) {}
void OnTriggerStay(Collider other) {}
void OnTriggerExit(Collider other) {}
EDIT:
Also using FindObjectOfType is an expensive function, just make the Audio Manager a Singleton

Unity 5 particle-deleting c# Script

I was following a unity tutorial started on Unity 4 but I am on Unity 5, and when I try to use the script seen (https://youtu.be/vwUahWrY9Jg?t=1337) and I try to use it, it gives an error:
Assets/Scripts/DestroyFinishedParticle.cs(18,17): error CS0246: The type or namespace name `Destroy' could not be found. Are you missing a using directive or an assembly reference?
this is the code:
using UnityEngine;
using System.Collections;
public class DestroyFinishedParticle : MonoBehaviour {
private ParticleSystem thisParticleSystem;
// Use this for initialization
void Start () {
thisParticleSystem = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update() {
if (thisParticleSystem.isPlaying)
return;
Destroy (GameObject);
}
}
It can be because C# code for unity changed from 4 to 5? what should I change? The problem seems to be in the Update method.
There are couple of issues with this code.
First, you didn't mention to what exactly is it attached too? I assume it attached to the Particle System.
Secondly, use "gameObject", not "GameObject", since GameObject is the name of the class.
Third, I believe there's a much more efficient way to destroy the gameObject without checking every frame whether the particles system has finished or not, maybe set a small timer? or invoke the function with time?
Depending on how your event is set up would depend on the approach to checking if the particles are running. If you can setup a collider to when you walk in, you can trigger an event to know the particles are on. Upon exiting the collider, the particles will shut off.
I'm not 100% on the syntax of return in C# but seems like it should go after you destroy your game object. I think return works in a similar fashion as the break in that aspect.(Especially since you don't seem to be returning any values anyway why do you need it?)

Unity SetActive(True) Not working?

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;

Categories

Resources