Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Apples_mmmmmmmm · Jan 07, 2012 at 12:41 AM · c#waitforsecondsienumeratormethod

Problem with using IEnumerator for method, c#

So in order to use 'yield return new WaitForSeconds();' I needed to return IEnumerator for my PlayerFire(); method in order to not get compiler errors. However, now that I can play the game, the method doesn't seem to do anything though it is still being called. I'm not clear on why this is and any explanation or a better way to do this without using WaitForSeconds function would be helpful.

 using UnityEngine;
 using System.Collections;
 
 public class ShipControls : MonoBehaviour 
 {
     public bool pausedState;
     public float speed;
     public float nextFire;
     public float fireRate;
     public float fireRate2;
     public int playerLives;
     public int powerup;
     public int shootForce;
     private Vector3 moveDirection;
     public Rigidbody shipProjectile;
     public Rigidbody shipProjectile1;
     public Rigidbody shipProjectile2;
     public Rigidbody shipProjectile3;
     public GameObject playerShip;
     
     void Awake()
     {
         pausedState = false;
         speed = 3.0F;
         nextFire = 0.0F;
         fireRate = 0.25F; //allows for up to 4 shots per second. Used for GetButtonDown.
         fireRate2 = 0.5F; //asllows for up to 2 shots per second. Used for GetButton.
         playerLives = 3;
         powerup = 0;
         shootForce = 10;
         moveDirection = Vector3.zero;
     }
     
     void Update() 
     {
         if(gameObject.tag == "Player")
         {
             if(pausedState == false)
             {
                 //movement controls
                 CharacterController controller = GetComponent<CharacterController>();
                 moveDirection = new Vector3(0, Input.GetAxis("Vertical"), 0);
                 moveDirection = transform.TransformDirection(moveDirection);
                 moveDirection *= speed;
                 controller.Move(moveDirection * Time.deltaTime);
                 //weapon controls
                 if(Input.GetButtonDown("Fire1") && Time.time > nextFire)
                 {
                     nextFire = Time.time + fireRate;
                     PlayerFire();    
                 }
                 else if(Input.GetButton("Fire1") && Time.time > nextFire)
                 {
                     nextFire = Time.time + fireRate2;
                     PlayerFire();
                 }
                 if(Input.GetKeyDown(KeyCode.F)) powerup = 1;
                 if(Input.GetKeyDown(KeyCode.G)) powerup = 2;
             }
         }
     }
     
     void OnControllerColliderHit(ControllerColliderHit hit)
     {
         if(hit.collider.gameObject.CompareTag("Enemy"))
         {
             Destroy(hit.collider.gameObject);
             Destroy(gameObject);
             playerLives --;
             
             Instantiate(playerShip);
         }
         
         
     }
     
     IEnumerator PlayerFire()
     {
         if(powerup == 0)
         {
             shipProjectile = shipProjectile1;
         }
         else if(powerup == 1)
         {
             shipProjectile = shipProjectile2;
             yield return new WaitForSeconds(5);
             powerup = 0;
         }
         else if(powerup == 2)
         {
             shipProjectile = shipProjectile3;
             yield return new WaitForSeconds(5);
             powerup = 0;
         }
         Rigidbody clone;
         clone = Instantiate(shipProjectile, transform.position + new Vector3(1, 0, 0), transform.rotation) as Rigidbody;
         clone.rigidbody.AddForce(transform.forward * shootForce);
     }
 }
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Jan 07, 2012 at 01:37 AM

Coroutines are not normal functions. They are so called generator--functions which "generates" or create a special object which is returned by the function. This object can be used to iterate through your coroutine, in other words: to execute it. This iteration is done by Unity's coroutine scheduler, but you have to "hand over" the generated object to Unity. This is done by calling StartCoroutine() with the generated object as parameter.

So far, that's how coroutines work. In your case however it makes no sense. You have a firerate of 4 shots / sec. The coroutine would wait 5 seconds (if powerup == 1 or 2) before even shoot. You will have 5*4 == 20 coroutines running at the same time. Your powerup timeout check should be done elsewhere.

Those two lines looks like debugging code:

if(Input.GetKeyDown(KeyCode.F)) powerup = 1;
if(Input.GetKeyDown(KeyCode.G)) powerup = 2;

It's better to use a function or property to set / activate a powerup.

void SetPowerUp(int aPowerUpType)
{
    powerup = aPowerUpType;
    switch (aPowerUpType)
    {
        case 1:
            StartCoroutine(ResetPowerUp(5.0f));
        break;
        case 2:
            StartCoroutine(ResetPowerUp(5.0f));
        break;
        default:
        break;
    }
}
IEnumerator ResetPowerUp(float aWaitTime)
{
    yield return new WaitForSeconds(aWaitTime);
    powerup = 0;
}

and then use it like this

if(Input.GetKeyDown(KeyCode.F)) SetPowerUp(1);
if(Input.GetKeyDown(KeyCode.G)) SetPowerUp(2);

edit ps, you might want check if you already use a powerup atm. If you start two coroutines both would set powerup to 0 after the waittime. This will propably overlap. To be able to "retrigger" the timeout you better work with timeout values which can be changed at any time.

private float m_PowerUpTimeOut = 0.0f;

void SetPowerUp(int aPowerUpType) { powerup = aPowerUpType; switch (aPowerUpType) { case 1: m_PowerUpTimeOut = Time.time + 5.0f; break; case 2: m_PowerUpTimeOut = Time.time + 5.0f; break; default: m_PowerUpTimeOut = 0.0f; break; } }

and in Update do your timeout check:

if (powerup != 0 && Time.time >= m_PowerUpTimeOut)
{
    SetPowerUp(0);
}
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Apples_mmmmmmmm · Jan 07, 2012 at 05:18 AM 0
Share

Thanks, that cleared up my confusion. All the examples I had seen of how to use IEnumerator were pretty unclear to me, and it was very helpful to have everything explained properly. Also, thank you for suggesting a much more elegant way of doing things.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

5 People are following this question.

avatar image avatar image avatar image avatar image avatar image

Related Questions

Only the first half of my coroutine works 1 Answer

Run Coroutine once, but finish Lerping 2 Answers

Using WaitForSeconds and trigger 1 Answer

Can't get past WaitForSeconds in my coroutine 1 Answer

c# - Having problems with the WaitForSeconds() method. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges