How to hide a gui canvas after some time? [closed] - c#

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I am displaying a canvas in Unity 3D that shows the instructions of the game at the beginning of the level, which I want to be hidden after 5-6 seconds. ( I don't want to do it with keyDown)
I was wondering what is the best way/practise to do it?
Is it using Animation? Or using some asynchronous methods like coroutine?

IEnumerator hideUI (GameObject guiParentCanvas, float secondsToWait,bool show = false)
{
yield return new WaitForSeconds (secondsToWait);
guiParentCanvas.SetActive (show);
}
To call it, simply start the coroutine and pass in the name of the parent gameobject that contains the UI then pass in how many seconds you want it to wait for before hiding UI canvas. The third parameter is optional and is there if you want to show that UI again. Pass true to it to display that hidden GUI again.
Usage:
StartCoroutine (hideGUI (gameObject, 2.0f)); //Wait 2 seconds then hide UI
StartCoroutine (hideGUI (gameObject, 2.0f, true)); //Wait 2 seconds then show UI

With Unity, they have a WaitForSeconds function that will wait for x seconds, then do something. You can use this so when the level starts up, you wait 5-6 seconds then hide the GUI.
yield return new WaitForSeconds (5);
// GUI hide code

May use a delayed Invoke, like:
public class Hide : MonoBehaviour
{
public float after = 5.0f;
void Start()
{ Invoke("Disable", after); }
void Disable()
{ gameObject.SetActive (false); }
}
Or you can use Start() returning IENumerator, like:
public class Hide : MonoBehaviour
{
public float after = 5.0f;
IEnumerator Start()
{
yield return new WaitForSeconds(after);
gameObject.SetActive (false);
}
}

Related

I am making a "boss fight" in unity2d. I wanted my player to get Iframes on hit. And it works but it bugs out so quickly. Any idea why it gets bugged? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 days ago.
Improve this question
So basically i did a character with 3 health. It seemed like this character needed iframes because he was getting stuck to death very quickly. So i made it so when he gets hit he is untouchable for 5 seconds and it worked but was bugging out too frequently (in about every 8-9 hits).
What i mean by bugging out is... My character did not get hit at all, infinitely. until my character died or i restarted the game.
Here is my code
If you need any of the other codes just say it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Iframes : MonoBehaviour
{
Renderer rend;
Color c;
GameObject character;
// Start is called before the first frame update
void Start()
{
rend = GetComponent<Renderer> ();
c = rend.material.color;
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
StartCoroutine("GetInvulnerable");
}
}
IEnumerator GetInvulnerable()
{
Physics2D.IgnoreLayerCollision(8, 9, true);
yield return new WaitForSeconds(3f);
Physics2D.IgnoreLayerCollision(8, 9, false);
}
}

Unity WaitForSeconds function not working properly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am trying to implement it so that you can shoot 2 times per second. I am doing this by shooting, and then delaying the gun controlling script for 0.5 seconds, but it's not working. I am trying to use the WaitForSeconds function.
I expect that when I click, a shoot immediately happens, and for the next 0.5 seconds clicking will have no effect while the rest of the game happens normally, and after that time, clicking once will shoot again, causing another delay and so on.
Instead, I can shoot over and over with nothing slowing it down.
Here's my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunController : MonoBehaviour
{
public Transform firePoint;
public GameObject bulletPrefab;
public string gunType;
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
switch (gunType)
{
case "pistol":
StartCoroutine(ShootThenDelay(0.5f));
break;
}
}
}
IEnumerator ShootThenDelay(float seconds)
{
Shoot();
yield return new WaitForSeconds(seconds);
}
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
}
}
A Coroutine does not delay the method that is starting it (with one exception - see below) .. otherwise your entire app would be frozen.
You could though simply add a flag like e.g.
bool canShoot = true;
IEnumerator ShootThenDelay(float seconds)
{
canShoot = false;
Shoot();
yield return new WaitForSeconds(seconds);
canShoot = true;
}
and then check for
if (canShoot && Input.GetMouseButtonDown(0))
Alternatively in your case you actually could directly wait until the routine is finished using
// Yes! If you make Start return IEnumerator then Unity
// automatically runs it as a Coroutine
private IEnumerator Start()
{
// Looks dangerous but is totally fine for a Coroutine as long as you yield inside
while(true)
{
if (Input.GetMouseButtonDown(0))
{
switch (gunType)
{
case "pistol":
// "Runs" the shoot routine and waits until it finished
// This way a yield at the end actually has an effect
yield return ShootThenDelay(0.5f));
break;
default:
// Note: This is very important! Make sure all paths within the while yield at least for one frame!
yield return null;
break;
}
}
else
{
// Note: This is very important! Make sure all paths within the while yield at least for one frame!
yield return null;
}
}
}
IEnumerator ShootThenDelay(float seconds)
{
Shoot();
yield return new WaitForSeconds(seconds);
}
That is because after waiting for 0.5 seconds, the coroutine returns to the point in code where execution was halted, in your example it returns to the line that goes after:
yield return new WaitForSeconds(seconds);
However, there is nothing, so nothing happens. If you do something like this:
IEnumerator ShootThenDelay(float seconds)
{
Shoot();
yield return new WaitForSeconds(seconds);
Shoot();
}
bullet must be shot twice with the delay of 0.5 seconds.
I do recommend you checking the documentation next time :)
https://docs.unity3d.com/ScriptReference/WaitForSeconds.html

please help me with my game my game have a problem [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I am making a objectpoolingManager which is supposed to put bullets under an empty object called objectpoolingManager and in my code i wrote that it must enable the bullet when i click the mouse button then after 2 second it will diables the bullet now my problem is that it is always disabled.
public GameObject bulletPrefab;
public int bulletAmount = 20;
private List<GameObject> bullets;
// Start is called before the first frame update
void Awake()
{
instance = this;
bullets = new List<GameObject>(bulletAmount);
for (int i = 0; i < bulletAmount;i++)
{
GameObject prefabInstance = Instantiate (bulletPrefab);
prefabInstance.transform.SetParent (transform);
prefabInstance.SetActive(false);
}
bullets.Add(bulletPrefab);
}
public GameObject GetBullet ()
{
foreach (GameObject bullet in bullets)
{
if(!bullet.activeInHierarchy)
{
bullet.SetActive (true);
return bullet;
}
}
GameObject prefabInstance = Instantiate (bulletPrefab);
prefabInstance.transform.SetParent (transform);
bullets.Add(bulletPrefab);
return prefabInstance;
}
}
Your getter/setter of objects in your pool manager should not instantiate or destroy gamobjects, but enable and disable them. That is the purpose of pooling.
It makes more sense to EnQueue/deQueue them and activate/deactivate like this.
private Queue<GameObject> objPool;
private Queue<GameObject> activeObj;
//get from pool
public GameObject GetObjFromPool(Vector3 newPosition, Quaternion newRotation)
{
GameObject newObject = objPool.Dequeue();
newObject.SetActive(true);
newObject.transform.SetPositionAndRotation(newPosition, newRotation);
//keep actives to be retrieved
activeObj.Enqueue(newObject);
return newObject;
}
//return to pool
public void ReturnObjToPool(GameObject go)
{
go.SetActive(false);
objPool.Enqueue(go);
}
Find this question in case its helpfull.
You can find plenty of pooling examples if you goolgle that up. Here is one.

Is there a reason why only one coroutine works in my code? [duplicate]

This question already has an answer here:
Wait for coroutine to finish [duplicate]
(1 answer)
Closed 3 years ago.
I have an enemy which currently attacks all the time, with no stopping in between attacks. I want to make enemy wait amount of time before he attacks again to simulate enemy "resting" and giving player a chance to attack him while not attacking. I needed coroutine to finish my animation playing so it can go to idle animation while waiting:
IEnumerator Attacking()
{
yield return new WaitForSeconds(animLenght);
isAttacking = false;
}
I have made another coroutine to wait for a second before enabling attacking again, but it doesen't work. Enemy attacks without brakes, like coroutine doesen't work:
IEnumerator WaitForAttack()
{
yield return new WaitForSeconds(1);
}
I have put WaitForAttack() coroutine in my Attack function:
private void Attack()
{
StartCoroutine(WaitForAttack());
isAttacking = true;
StartCoroutine(Attacking());
}
I would like to know what I'm doing wrong with coroutines, as I have just started using them, and this problem is troubling me for a very long time now.
The documentation for MonoBehaviour.StartCoroutine says
StartCoroutine function always returns immediately
So the Attack method will not wait after calling StartCoroutine(WaitForAttack()); and set isAttacking = true; immediately. Instead, set isAttacking in the coroutine itself. Also do both in the same coroutine to ensure the operations are performed in sequence. Otherwise both coroutines will run at the same time in parallel.
IEnumerator WaitAndAttack()
{
yield return new WaitForSeconds(1);
isAttacking = true;
yield return new WaitForSeconds(animLenght);
isAttacking = false;
}
private void Attack()
{
StartCoroutine(WaitAndAttack());
}
Coroutines can only suspend themselves (yield return ____) and not the method or object calling them. They are not the same as a synchronous method. When a coroutine is invoked and returns back to the parent method, that parent method will continue in the same frame.
In your method, you call "WaitForAttack()" and "Attacking()" from the same method on the same frame. "WaitForAttack()" literally does nothing.
Here's an example of a Coroutine that runs 5 separate times, once every second after it is called. Note that the var waitForSeconds is initialized once rather than every time I yield control back to the main thread. This is a minor optimization, but is considered best practice.
class TimedCoroutine : MonoBehaviour
{
var waitForSeconds = new WaitForSeconds(1);
IEnumerator CountdownToAction()
{
int countdown = 5;
while(countdown >= 0)
{
print(countdown--);
yield return waitForSeconds;
}
//Perform action here
}
}

How come Unity's StartCoroutine work with and without assignment? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I tried searching but was lost between all the threads that explain the co-routine system but not this detail. I already know that StartCoroutine returns a Co-routine, so I tried looking if there's some sort of implicit operator overloading for a void return type and even tried it, but it didn't work and I found nothing. That's honestly all I could think of, you can tell i'm a beginner
There's no specific goal of this question, i'm just really interested. thanks in advance
Edit :I apologize for not making my question clear :
How can say both StartCoroutine(example()); and Coroutine myCoroutine = StartCoroutine(example()) ? How does the first one work like a void if the return type is Coroutine ?
Compare
StartCoroutine(example());
and
Coroutine myCoroutine = StartCoroutine(example());
How does the first one work like a void if the return type is Coroutine ?
You've got the rule backwards in your head. The rule in C# is not "A non-void method must have its returned value assigned or used." The rule is the opposite: a void method can only be used as a statement.
If you use a non-void method as a statement, the compiler generates code which discards the returned value.
Whether that is a smart thing to do or not is not for the compiler to decide.
However, it is the case that only certain expressions may be used as statements; unsurprisngly, they are those expressions which are useful for their side effects. They are:
method calls
assignments (yes, assignments are expressions)
increments / decrements
constructor invocations ("new") -- this is rare
awaits
So you can say:
M();
x = 123;
x++;
new Abc();
await someTask;
But not
2 + 2;
(string)M();
and so on.
You don't always need to save the result of a function that has a return value. If you did
public void Awake()
{
Foo();
}
private int Foo()
{
return 42;
}
The compiler would have no problem with it.
The reason StartCoroutine returns anything is if you wanted to do nested Coroutines and you wanted to wait for the inner routine to finish before continuing with the outer.
Here is a example where rooms get loaded dynamically in a game, once the first room is loaded the player is allowed to move then the additional rooms get loaded sequentially afterward.
private bool _allowPlayerMovement;
public Room FirstRoom;
public Room SecondRoom;
public Room ThirdRoom;
//...
public void Awake()
{
_allowPlayerMovement = false;
StartCoroutine(LoadRooms())
}
private IEnumerator LoadRooms()
{
//Runs the LoadFirstRoom Coroutine then waits for it to finish.
yield return StartCoroutine(LoadFirstRoom())
//One the first routine finishes set the variable to true.
_allowPlayerMovement = true;
//Start loading the 2nd room, wait for it to finish
yield return StartCoroutine(LoadSecondRoom())
//Once the 2nd room is finished loading start loading the 3rd room.
yield return StartCoroutine(LoadThirdRoom())
//... And so on
}
private IEnumerator LoadFirstRoom()
{
WWW www = new WWW("http:\\example.com\levels\FirstRoom.json")
yield return www;
FirstRoom = JsonUtility.FromJson<Room>(www.text);
}
//... And so on
If you don't care about when the Coroutine "finishes" there is no need to save the result from StartCoroutine (like in the Awake function of my above example)

Categories