Enable object Parent in the hierarchy - c#

How do I get an object in the hierarchy is enabled through scrip?
void OnCollisionEnter2D (Collision2D colisor)
{
if (colisor.gameObject.tag == "Floor") {
Destroy (gameObject, 0.6f);
} else {
if (colisor.gameObject.tag == "Bee") {
coinCollectSound.Play ();
heart = GameObject.FindGameObjectWithTag ("Hearts").GetComponent<Hearts> () as Hearts;
if (heart.TakeHeart ()) {
Destroy (gameObject);
} else {
//Here i want setActive(true) Object parent in hierarchy called "GameOver"
//And setActive(false) Object in hierarchy Called "Game"
}
}
}
}
I do not want to call a different scene for the Game Over, but now I just want to enable it.

You should access the GameOver using GameObject.Find("GameOver"), but if it's disabled you won't be able to do that. Instead, create a public GameObject variable on a enabled script that references the object you wanna SetActive. Then, find the object by type and access it's variable, enabling it.

Since this is a gameover object you could probably get away with simply calling
GameObject.Find("GameOver").SetActive(true);
GameObject.Find("Game").SetActive(false);
However this will have performance implications if there are many objects in your game.

To disable the parent of GameObject the script is attached:
transform.parent.gameObject.setActive(true);
To get specific GameObjects use a public variable and link them in the Inspector. To improve performance avoid using GameObject.Find.

Related

Why can't I "unhide" my gameobject in unity by using SetActive(true)

I am making a little game and I want my character to disappear until you press space, but I don't want to destroy it since it has a script inside. I tried what I wrote below, but it didn't work.
void Start () {
gameObject.SetActive(false);
}
void Update () {
if (Input.GetKeyDown(Keycode.Space)) {
gameObject.SetActive(true);
}
Have any clues to fix it or replacement code?
You set the GameObject to disabled with SetActive(false). As a result, the Update() method is no longer executing. Because of this, the code that will unhide your character can never run.
There are many ways to get the behavior you want, but the simplest I can think of is this: Instead of disabling the entire gameobject, just disable the renderer (whether it's a sprite renderer or mesh renderer). This will make your character disappear, but this script will keep running.
Example:
public Renderer renderer; // drag your renderer component here in the Unity inspector
void Start ()
{
renderer.enabled = false;
}
void Update ()
{
if (Input.GetKeyDown(Keycode.Space))
renderer.enabled = true;
}
Another approach (and I think, better) is to create a child object of your character's GameObject, call it "Body", and place everything that deals with rendering your character in there. Then disable/enable that child gameobject as desired.
Using gameObject.SetActive(false) disables the gameObject and all its components, including the script you're running so it can't turn itself on if the script driving it is off.
If you add the script to a parent object of the object you're trying to disable you can get the effect you're looking for like this:
public gameObejct childObject;
void Start()
{
childObject.SetActive(false);
}
void Update()
{
if (Input.GetKeyDown(Keycode.Space))
{
childObject.SetActive(true);
}
}

Efficient way to not delete gameobject reference of singleton after scene reload

I have a singleton class and everytime I reload a scene the object reference I store in variable is destroyed
public class GameManager : MonoBehaviour
{
private void Awake()
{
if (instance == null)
{
instance = this;
}
else
{
Destroy(this.gameObject);
}
DontDestroyOnLoad(this);
Debug.Log("Scene reloaded");
}
void Start()
{
shapeSpawnerGO = GameObject.Find("SpawnShapesObj");
scoreGO = GameObject.Find("ScoreText");
lifeGo = GameObject.Find("LifeText");
}
public bool RedShapeStatus(int rcv_RedShapeIndex)
{
if (shapeSpawnerGO == null)
{
shapeSpawnerGO = GameObject.Find("SpawnShapesObj");
}
return shapeSpawnerGO.GetComponent<ShapeSpawnerChild>().listofRedShape[rcv_RedShapeIndex].activeSelf;
}
}
What I've done is check if shapeSpawnerGO is null then reference again the gameobject. And I think this is not efficient. Is there other way to solve this issue?
There are certainly other ways to accomplish this, but my official answer is "You're already doing it an acceptable way." You specifically said this:
"What I've done is check if shapeSpawnerGO is null then reference
again the gameobject. And I think this is not efficient. Is there
other way to solve this issue?"
You said the only time your code reinitializes the variables is whenever the scene reloads.That operation time doesn't even matter. You're literally talking about optimizing something completely irrelevant. Reinitializing scene data during a reload is what normal scene loading is all about.
The only exception to this would be if your idea of a scene reload is something you're doing every few seconds. If you're talking about the normal idea of a scene reload where you load the game scene once and then proceed to run the game for many minutes before a new scene reloads, then there's no reason to be worried about this code doing its normal initialization behavior.

How to activated object again in unity

I created a dot following my mouse around in 2D and I created a cube object changing position on x and y. Now when I point my mouse to cube, it deactivates I set that, and now I want to activate it again. I try on trigger exit, but it didn't work.
public GameObject tapObject;
private float respawnTime = 1f;
public float xMin;
public float xMax;
public float yMin;
public float yMax;
void Start()
{
StartCoroutine(spawnEnemyTime());
}
private void RandomSpawnObject()
{
tapObject.transform.position = new Vector2(Random.Range(xMin, xMax), Random.Range(yMin, yMax));
}
private void OnTriggerEnter2D(Collider2D collision)
{
tapObject.SetActive(false);
}
IEnumerator spawnEnemyTime()
{
while (true)
{
yield return new WaitForSeconds(respawnTime);
RandomSpawnObject();
}
}
Once inactive the scripts on that object are not executed anymore => messages like OnTriggerExit are not called/executed.
One solution is to simply wrap the target object in a parent object and attach your script to the parent instead but make it (de)activate the child.
So the parent stays active and receives the message.
I am just going to repeat what everyone else here said:
A inactive object in Unity is truly inactive, meaning it does not receive any updates, can't collide with stuff and all the MonoBehaviour stuff that usually calls your code does not work either. You have to manually re-activate the object using a reference that you cached somewhere.
But, instead of just flat out disabling the whole object you could disable the components that you don't want to be active.
Example:
private void OnTriggerEnter2D(Collider2D collision)
{
tapObject.GetComponent<Renderer>().enabled = false;
}
private void OnTriggerExit2D(Collider2D collision)
{
tapObject.GetComponent<Renderer>().enabled = true;
}
This only deactivates your renderer component but leaves everything else as it is. So your object can still collide and it's still registered via e.g. OnTriggerExit.
Keep in mind that GetComponent<T>() is a pretty expensive operation so caching your component references is a good idea. The best solution would be to start out with a reference by creating a variable for it and assign it in the inspector.
Example:
//Set in inspector
public Renderer renderer
private void OnTriggerEnter2D(Collider2D collision)
{
renderer.enabled = false;
}
private void OnTriggerExit2D(Collider2D collision)
{
renderer.enabled = true;
}
When a GameObject is not active in Unity , you can't click it(no rendering,no colliding , nothing )
But ,You can create a hotkey (new script or in other script) , that can set it back to active , if it is not active.
public GameObject GO;
Use GO.setactive(true);
whereas gameobject is the object use to define the specific thing or object which needs to be active and the whole code needs to written in the method "spawnEnemyTime" so that it could be get active after the specific time period
You can just use an empty GameObject and get a reference the object that you want to enable/disable. If you get the reference before you disable it you will be able to activate it again.
the alternative is to do what TehMightyPotato said. Disable components it's actually the best way to solve this problem, but if you have lot's of components/subcomponents disable the gameobjects is faster.

Unity3D - unable to respawn an object after it has been destroyed

I am having an issue respawning a prefab after it has been destroyed. I can't seem to get it to respawn back at its original start position after a second of being destroyed. I have created an empty game object and attached the SpawnTargets.cs script to it. I'm not sure of what the best methodology to approach this situation. Another object with a script attached to it does the actual destroy of the prefab. BulletCollisionHandler.cs works fine though. Thanks for any help. Code is below:
SpawnTargets.cs:
using UnityEngine;
using System.Collections;
public class SpawnTargets : MonoBehaviour
{
public GameObject targetCircle;
public GameObject targetSquare;
public GameObject targetStar;
private Vector3 circleSpawnPosition = new Vector3(0.0f, 1.227389f, -7.5f);
private Vector3 squareSpawnPosition = new Vector3(0.0f, 1.027975f, -7.993299f);
private Vector3 starSpawnPosition = new Vector3(0.0f, 1.8f, -7f);
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
SpawnTarget ();
}
void SpawnTarget()
{
}
}
BulletCollisionHandler.cs:
using UnityEngine;
using System.Collections;
public class BulletCollisionHandler : MonoBehaviour
{
public GameObject targetCircle;
// Use this for initialization
void Start ()
{
Destroy (gameObject, 2);
}
// Update is called once per frame
void Update ()
{
}
void OnCollisionEnter(Collision other)
{
if(other.gameObject.name == "TargetSquare")
{
other.gameObject.rigidbody.isKinematic = false;
((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;
Destroy (other.gameObject, 1);
Debug.Log("Hit square");
}
else if(other.gameObject.name == "TargetCircle")
{
other.gameObject.rigidbody.isKinematic = false;
((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;
Destroy (other.gameObject, 1);
Debug.Log("Hit circle");
}
else if(other.gameObject.name == "TargetStar")
{
other.gameObject.rigidbody.isKinematic = false;
((TargetMovementHorizontal)other.gameObject.GetComponent<TargetMovementHorizontal>()).enabled = false;
((TargetMovementVertical)other.gameObject.GetComponent<TargetMovementVertical>()).enabled = false;
Destroy (other.gameObject, 1);
Debug.Log("Hit star");
}
}
}
You're not calling Instantiate() anywhere, so it's hard to see where the new object would come from in the code you've supplied.
In any case, it might be better not to use Destroy. If you want to immediately reset the object, why not simply recycle it back to the start position? It's a good idea to avoid instantiating and destroying lots of objects, it's better to hide/disable the ones your don't need and unhide/re-enable them.
Here's a tutorial on the general idea. The tutorial is about groups of objects but the same trick would work for recycling single objects too.
You are better of using gameObject.SetActive( true/false ); for activating / deactivating the gameObject instead of just using Destroy.
Then if you are using Destroy you have 3 options that comes to mind for getting it into the desire position before the Player sees it.
1) You enable the game object after disabling its Renderer component. Then you equalize the transform's position / rotation the one you need. After this you re-enable the Renderer component. It should be placed where you want it.
2) You Instantiate the gameObject, but first making sure the Renderer component is disabled on its Prefab, by default, so you can re-assign its Transform values then - re-enable the Renderer again.
3) You make an invisible gameObject (an Empty gameObject) and Instantiate the wanted gameObject, you then make the Empty to be the parent of the newly created gameObject.. Provided that the parent Empty is exactly where you want it to be, when you instantiate and reset the child's position it should jump off right on top the the Empty parent.
I'm not giving code since you haven't and I don't have no idea of which method you might end up liking more. In terms of performance the Enable/Disable are the best option.
And as theodox says Object Pooling is your best friend for things like bullets, although it might be applied to many other gameObjects that might work as 'collections of objects' on your game's logic. It's totally worth learning.

Switch between multiple materials on a button press

I need to have an object in my scene change between two different materials at run time, when ever a button is pressed in my Unity project. However, I have never done this before and I'm having an issue getting my head around how to do this.
In my scene I have one game object I've called my controller. This script holds my material switching class and is looking like this:
public GameObject cupMesh;
bool isOn = true;
// Use this for initialization
void Start ()
{
cupMesh = GameObject.Find("CupMesh");
}
// Update is called once per frame
void Update ()
{
}
void OnGUI()
{
if(GUI.Button(new Rect(10,10, 100, 40), "Show mesh"))
{
renderer.enabled = false;
}
}
I know this doesn't change the material, but the above code does nothing. I've never modified anything on the mesh renderer before but I know there is a list of materials on it.
How can I access that list so I can have my program switch between the two materials found there?
To show or hide a gameObject, rather than using render.enabled property, you should use this:
// Unactivates the game object.
gameObject.SetActive (false);
However it's not clear from the code if you want to adjust the material of the object the script is attached to, or the cupMesh game object.
If you wanted to make the cupMesh disappear, you would use:
cupMesh.SetActive (false);
Or if you wanted to access the material component of the cupMesh, this is
cupMesh.renderer.material

Categories

Resources