Recently I have decided to start creating a game, and during this time I have run into many problems, most I have been able to fix myself but I'm having trouble with this. Basically, I want my code to make a Box Collider appear when clicked, and then disappear after a certain amount of time.
Here's my code:
void Start()
{
StartCoroutine(bruh())
}
void Update()
{
IEnumerator bruh()
{
if (Input.GetMouseButtonDown(0))
{
this.GetComponent<BoxCollider2D>().enabled = true;
yield return new WaitForSeconds(2);
}
else
{
this.GetComponent<BoxCollider2D>().enabled = false;
}
}
}
Your co-routine wasn't doing anything after it resumed from the yield return. I assume you want;
...
this.GetComponent<BoxCollider2D>().enabled = true;
yield return new WaitForSeconds(2);
this.GetComponent<BoxCollider2D>().enabled = false;
...
Possible new up the WaitForSeconds and then return that because it looks like you are just creating it not using it.
Related
I have a coroutine which takes in some variable running in the update function and I need the code to be something like this:
void Update(){
if(/*coroutine is not running*/){
StartCoroutine(coroutine(some variable));
}
}
Is there a way to know if the coroutine is still running before I run it with some other variable. I know that there is a way of doing it where I put that coroutine into another coroutine and use yield return coroutine(some variable) and that should work. But in my case the variable that the coroutine takes in depends on an event that my script is subscribed to, so the above implementation won't work. So is a way to know if my coroutine is still running or not?
bool isCouroutineRunning = false;
void Update()
{
if(isCouroutineRunning == false)
{
StopCoroutine("MyCourutine");
StartCoroutine("MyCourutine",variable);
}
}
IEnumerator MyCourutine()
{
isCouroutineRunning = true;
yield return new WaitForSeconds(1.0f);
isCouroutineRunning = false;
}
I assume that there is something fundamental about coroutines that I don't understand because I cannot get my head around why this is happening.
I have this coroutine that works perfectly as intended the first time but completely fails the second time I try to use it.
public IEnumerator CharacterDialogue()
{
inDialogue = true;
playerController.enabled = false;
mouselook.enabled = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
dialogueMenu.SetActive(true);
yield return new WaitForEndOfFrame();
for (int i = 0; i < dialogueStrings.Length; i++)
{
while (!Input.GetKeyDown("e"))
{
yield return null;
}
yield return new WaitForEndOfFrame();
dialogueText.text = dialogueStrings[i];
}
yield return new WaitForEndOfFrame();
while (!Input.GetKeyDown("e"))
{
yield return null;
}
yield return new WaitForEndOfFrame();
QuestManager.Instance.SpawnDouxland();
inDialogue = false;
playerController.enabled = true;
mouselook.enabled = true;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
dialogueMenu.SetActive(false);
}
It is pretty straightforward: I disable the controls of my player and make the dialogue window pop. I then wait for the input of the player between each string of text so that he may read at his own pace. Once he's done reading I reactivate the controls and close the dialogue window.
This code works exactly like I want the first time but the second time it just goes through the for loop without waiting for the input.
What am I doing wrong here and why does it work the first time?
Edit:
Comments pointed out that the issue must be in the way I call the coroutine. This now makes sense to me as I use the same key (e) to call the coroutine. So maybe it reads the key as pressed and runs through the for loop. Bu why would it only do so the second time?
Here's the snippet of code where I call my coroutine:
if (hit.collider.CompareTag("Character"))
{
raycastedObj = hit.collider.gameObject;
CrosshairActive();
interactionManager.InteractiveFeedbackTextCall("CharacterQuest");
if (Input.GetKeyDown("e"))
{
Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
StartCoroutine(canvasAnimManager.CharacterDialogue());
}
}
Thanks to some comments I figured out what the issue was.
if (Input.GetKeyDown("e"))
{
Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
StartCoroutine(canvasAnimManager.CharacterDialogue());
}
I thought the idea of GetKeyDown was that it was triggered only once... there must be something I'm not getting. Anyways the issue was that this was called multiple times and it make the coroutine go through the loop even after I was finished with my dialogue.
I just added a little bool check to fix the issue:
if (Input.GetKeyDown("e") && !canvasAnimManager.inDialogue)
{
Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
StartCoroutine(canvasAnimManager.FoukiDialogue());
}
Cheers and thanks for the help!
I need to make a screenshot in Unity. I did it the next way:
public void Capture(){
StartCoroutine(CaptureScreenshot());
}
private IEnumerator CaptureScreenshot(){
GameObject canvas = GameObject.Find("Canvas");
canvas.SetActive(false); // hide all buttons
yield return new WaitForEndOfFrame();
string timestamp = DateTime.Now.ToString("dd_MMMM_hh_mm_ss_tt");
Application.CaptureScreenshot("screenshot" + timestamp + ".png");
Debug.Log("Screenshot was captured.");
yield return new WaitForEndOfFrame();
canvas.SetActive(true); // restore all buttons
yield return null;
}
When I invoke Capture(), canvas hides but neither screenshot takes nor text logs.
What is wrong with this code? Thanks for response.
Because your script is running on a object in the canvas when you do canvas.SetActive(false); that also disables the script, preventing the coroutine from continuing from yield return new WaitForEndOfFrame();.
Move the script to a game object that does not live on the canvas and it should solve the problem.
You could also do this.
foreach(Transform t in GameObject.Find("Canvas").transform)
{
if(transform.gameObject.name != t.gameObject.name)
t.gameObject.SetActive(false);
}
Be sure to re-enable them with
foreach(Transform t in GameObject.Find("Canvas").transform)
{
t.gameObject.SetActive(true);
}
In unity I am aware how to translate and rotate an object and I always do it in the Update function, the problem I am having is that I want a series of translations and rotations to happen in sequence but the only translation/rotation that occurs is the one that I call first in the code, is there any way to do a translation, wait a certain amount of time and then carry out another translation for example. Thanks.
void Update ()
{
if (enemyHit == false)
{
//enemy moving
transform.LookAt(TTarget);
}
else if (enemyHit == true)
{
Debug.Log (enemyHit);
Evade();
}
}
IEnumerator Wait(float duration)
{
yield return new WaitForSeconds(duration);
}
void Evade()
{
enemyHit = playerMovement.hitEnemy;
transform.Translate(Vector3.back * Time.deltaTime * movementSpeed);
Wait(2);
transform.Rotate(0,90,0);
}
I tried using a seperate function but that didnt seem to do anything.
IEnumerator Wait()
{
yield return new WaitForSeconds(2);
}
You may want to start a CoRoutine as well.
StartCoroutine("Wait");
This should allow you to achieve what you're trying to do.
I want my character to stop when I press a button on my gamepad or keyboard. The character must do a specific animation when I press the button and nothing else, so no movement at all, just the animation.
I'm trying to figure out how WaitForSeconds works, but when I try to use it, it doesn't work. Here the code of the function that calls WaitForSeconds
public IEnumerator Wait()
{
yield return new WaitForSeconds (6);
}
When the bool variable animationTest is true I want the program to wait for 6 seconds
if (animationTest)
{
UnityEngine.Debug.Log ("check1");
StartCoroutine (Wait ());
UnityEngine.Debug.Log ("check2");
animationTest = false;
}
but this doesn't work! check1 and check2 are printed at the same time. I'm missing something. This runs in FixedUpdate().
The Coroutine does not work like this. It starts a new (parallel) execution.
In order to achieve the wait you'd have to do it in the IEnumerator.
public IEnumerator SomethingElse() {
animationTest = false;
Debug.Log("check1");
yield return new WaidForSeconds(6f);
Debug.Log("check2");
yield return true;
}
void FixedUpdate() {
if (animationTest) {
StartCoroutine(SomethingElse());
}
}
Now when you set the animationTest at some point, you should see the two logs with a time gap of 6 seconds in between.