- Home /
Enable/Disable Game objects after Wait For seconds
I need to know the best way to enable a game object after "WaitForSeconds"
Here's a Sample Code in C#
IEnumerator Start ()
{
//Wait for 14 secs.
yield return new WaitForSeconds (14);
//Turn My game object that is set to false(off) to True(on).
GameObject.Find ("MyObject") .SetActive (true);
//Turn the Game Oject back off after 1 sec.
yield return new WaitForSeconds (1);
//Game object will turn off
GameObject.Find ("MyObject") .SetActive (false);
}
}
So My problem is, The wait for seconds line of code doesn't work. The game Object Becomes active on Start without waiting for 14 secs like i want it to do. Same for the Disable portion of the code. What is done wrong here? Can WaitForseconds Be used this way? The Game Object has a script attach that makes a certain thing during the game to happen after the given time
The code seems fine, but I think an issue you would run into is the GameObject.Find function. AFAI$$anonymous$$ it will only work if the object is already active. I copied your script verbatim and was able to get this to work by removing the Find call and replacing it with a direct reference to an object.
However the behavior you described (object starting immediately) makes it sound like the object is being affected from something other than this piece of script.
FWIW, using IEnumerator Start is completely $$anonymous$$osher. I noticed all of the answers took an extra step of writing a separate coroutine but this is completely unnecessary, since setting IEnumerator as the return value of Start() will ensure the engine runs it as a coroutine. There is absolutely nothing wrong with the logic you have in there for delays.
Answer by Bieere · Feb 08, 2015 at 09:47 PM
Edit: As mentioned by sysameca
If your game object is disabled it won't run the Start() method at all, not to mention that GameObject.Find() can't find any disabled game objects.
In addition to these points, you cannot start a coroutine from an object that is disabled or destroyed, however, you can still start the coroutine on any other Monobehaviour.
Its recommended that you don't use any FindObject() by string, as it is pretty slow and costly in the long run, so either store it locally within the inspector, which makes it pretty easy to access and use, or add the script straight onto the object.
Now within the start, you can make it start disabled, while leaving it active within the scene, helps with debugging a bit if that's the way you do it.
Use this script as a manager/container for your coroutines:
public class MyController : MonoBehaviour
{
}
Use the script here to disable the object
public class MyObject: MonoBehaviour
{
public float sec = 14f;
public MyController MyController;
void Start()
{
MyController.StartCoroutine(LateCall(sec));
}
IEnumerator LateCall(float seconds)
{
if (gameObject.activeInHierarchy)
gameObject.SetActive(false);
yield return new WaitForSeconds(seconds);
gameObject.SetActive(true);
//Do Function here...
}
}
A more advanced implementation would look like this:
public class MyController : MonoBehaviour
{
private static MyController _instance;
private void Awake()
{
if (_instance == null)
_instance = this;
}
public static void DelayedStart(GameObject target, float time, Action onFinishedCallback)
{
_instance.StartCoroutine(DelayedStartCoroutine(target, time, onFinishedCallback));
}
private static IEnumerator DelayedStartCoroutine(GameObject target, float time, Action onFinishedCallback)
{
if (target.activeInHierarchy) target.SetActive(false);
yield return new WaitForSeconds(time);
target.SetActive(true);
onFinishedCallback?.Invoke();
//Do Function here...
}
}
public class MyObject : MonoBehaviour
{
public float sec = 14f;
void Start()
{
MyController.DelayedStart(gameObject, sec, () =>
{
//Do Function Here
});
}
}
I dont get it, for me it doesn't work. If an object is inactive, the code of the coroutine doesn't get called. And if you deactivate first (like the suggested solution), you get the following. error: "Coroutine couldn't be started because the the game object is inactive!"
you have to place this script on another gameobject that remains active all the time
Right, that's what I did, but didn't the answering guy said you can place it on the same object and wrote a matching script?
The answer provided by sysameca is correct http://answers.unity.com/answers/896796/view.html
Answer by sysameca · Feb 08, 2015 at 09:28 PM
If your game object is disabled it won't run the Start() method at all, not to mention that GameObject.Find() can't find any disabled game objects. The way you can do this is to expose the public GameObject variable in some active game object and from there to activate the disabled one.
public class ActivatorObject : MonoBehaviour
{
public GameObject objectToActivate;
private void Start()
{
StartCoroutine(ActivationRoutine());
}
private IEnumerator ActivationRoutine()
{
//Wait for 14 secs.
yield return new WaitForSeconds(14);
//Turn My game object that is set to false(off) to True(on).
objectToActivate.SetActive(true);
//Turn the Game Oject back off after 1 sec.
yield return new WaitForSeconds(1);
//Game object will turn off
objectToActivate.SetActive(false);
}
}
Answer by AndrewHerrera1998 · Apr 20, 2019 at 01:20 AM
easy, use Invoke and specify the time in secs:
Invoke("HideShowGameobject", 5);
create a new method called HideShowGameobject:
void HideShowGameobject()
{
if (objectToHide.active)
objectToHide.SetActive(false);
else
objectToHide.SetActive(true);
}
Answer by nirharpaz · Feb 08, 2015 at 09:30 PM
try this:
Don't make Start as IEnumerator and move all the content to other function. let's call the function
functin StartFunction()
{
.....
}
then you need to put on start
StartCoroutine(StartFunction());
i can give you a code example i did for creating shards storm in 1 of my games
int _shardsPerStorm;
//function is called from outside
public void initiateShardStorm()
{
StartCoroutine(ShardStorm());
}
// shards maker
IEnumerator ShardStorm()
{
for(int CurrentShardCount=0;CurrentShardCount<_shardsPerStorm;CurrentShardCount++)
{
//Debug.Log ("Before Waiting " + _cooldown + " seconds");
createShard();
yield return new WaitForSeconds (_cooldown);
//Debug.Log ("After Waiting " + _cooldown + " Seconds");
}
}
void createShard()
{
....
}
Last comment, in terms of resources, 'Find' function is extremely expensive and you rather avoid it almost at all cost. make 'MyObject' or an object that can reach 'MyObject' accessible from that script.
hope it helps
Answer by RoyalDio2 · Apr 04, 2016 at 09:07 AM
using UnityEngine; using System.Collections;
public class PlayerController : MonoBehaviour {
public GameObject cubes;// Object to active
public float sec = 14f;
void OnTriggerEnter(Collider other)
{
if (other.tag == "JetPack") { //tag name Object to Pick Up
cubes.SetActive (true);
StartCoroutine (LateCall());
}
}
//after same sec Object to false
IEnumerator LateCall()
{
yield return new WaitForSeconds (sec);
cubes.SetActive (false);
}
}
Your answer
Follow this Question
Related Questions
Hey! how to connect two objects? So to make one? 3 Answers
how to get objects that are in some radius with the point in certain center 1 Answer
Selecting and unselecting objects with raycast 0 Answers
Memory Leak Adventures in Editor (3.4, lot of instantiated objects) 1 Answer
NullReferenceException: Object reference not set to an instance of an object 0 Answers