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 Digital-Phantom · Mar 29, 2015 at 04:13 PM · timewaitforsecondsdelayrandom.rangefire

30 Objects all firing at exactly the same time and not randomly

I have 30 objects/enemies in my scene and they all fire at exactly the same time.

So I added a random delay into the firing script, hoping to make them fire at different times but they still 'all' fire at exactly the same time.

 using UnityEngine;
 using System.Collections;
 
 public class InvaderShoot : MonoBehaviour
 {
 
     //private float delay = Random.Range(1.5f,3f);
 
     private bool canFire = false;
     public float attackDistance = 150;
 
     public GameObject bolt;
     public Transform boltSpawn01;
 
     public float fireSpeed;
     private float fireAgain;    //set the time between shots
     
 
     void Update()
     {
         RaycastHit hit;
 
         Ray shootingRay = new Ray(transform.position, -Vector3.forward);
 
         //Debug.DrawRay(transform.position, -Vector3.forward * attackDistance);
 
         if(Physics.Raycast(shootingRay, out hit, attackDistance))
         {
 
             if(hit.collider.tag == "ShieldCube")
             {
                 canFire = true;
                 StartCoroutine(InvaderFireWeapon());
             }
 
             if(hit.collider.tag == "Enemy")
             {
                 canFire = false;
             }
 
             if(hit.collider.tag == "Player")
             {
                 canFire = true;
                 StartCoroutine(InvaderFireWeapon());
             }
         }
 
         else
         
         {
             canFire = true;
             StartCoroutine(InvaderFireWeapon());
         }
     }
 
 
     IEnumerator InvaderFireWeapon()
     {
         float delay = Random.Range(1.5f,3f);
 
         yield return new WaitForSeconds(delay);
 
         print("Waiting For " + delay);
 
         if(canFire == true && Time.time > fireAgain)
         {
             fireAgain = Time.time + fireSpeed;
             Instantiate(bolt, boltSpawn01.position, boltSpawn01.rotation);
         }
     }
 }
 

I know all 30 are using the same script, but I don't understand how(or why) they are still all firing at the same time.

Need some help on this one please guys

???

Comment
Add comment · Show 1
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 Glurth · Mar 29, 2015 at 06:25 PM 0
Share

just to confirm I understand- is this correct?

You are telling them all to fire at the same time (or at least, the in same update cycle). Then you want each to wait a random 1.5-3 seconds before it actually shoots.

If so, I don see where it going wrong.... Can you confirm that RandomRange and WaitForSeconds are working as expected? $$anonymous$$gest a print command both above an below the "yield wait" command, like: print("time now:" + Time.time.ToString() + " delay:"+delay.ToString());

Alternate Idea: I would have done this differently, and created a new variable called fireAtTime. Setting fireAtTime equal to Time.time + delay during FireWeapon. I would check this value against Time.time during Update(). If it has "expired" (fireAtTime>=Time.time), and canFire, then instantiate projectile. (similar to what you are doing with fireAgain)

P.S. gratz on 1$$anonymous$$+ karma!

1 Reply

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

Answer by DiegoSLTS · Mar 29, 2015 at 09:17 PM

You wrote that "they still 'all' fire at exactly the same time", those single quotes mean that only some fire at the same time and not literally all of them?

I'm not sure about the problem here, but one thing that looks suspicious is that you start the "InvaderFireWeapon" coroutine on every frame that the raycast returns false, doesn't it start the coroutine in a lot of consecutive frames for most of the enemies?

Now, inside the coroutine, you wait a random time, but they don't shoot after that random time, they only shoot if the current time is grater than "fireAgain", wich is the same value for every object that has that component.

So, your enemies start a lot of coroutines and in all of them they wait some time. Each coroutine continues after that wait, and some of them reach the "if" before the "fireAgain" time, so those coroutines don't produce a shot. At some point one coroutine reaches that if and Time.time is actually greater than fireAgain, but since there where so many coroutines runing, Time.time is probably really close to fireAgain. Now, that coroutine sets fireAgain to a new time in the future, so when the rest of the coroutines that where waiting continue, they all evaluate "Time.time > fireAgain" as false, and don't shoot. During añl this time a lot of coroutines where started, so at some point one coroutine finishes the wait when Time.time is again greater than fireAgain, but it's probably really close again, so the cycle repeats.

I'd suggest you control the shooting ONLY with coroutines, not from the Update. Instead of starting the coroutine on the Update, start the coroutine again at the end of the same coroutine, something like this:

 IEnumerator InvaderFireWeapon()
 {
     // doing this you make sure that the enemy waits at least the "fireSpeed" time before shooting again
     float delay = Random.Range(fireSpeed,fireSpeed + 1.5f);
     yield return new WaitForSeconds(delay);
 
     if(canFire == true)
     {
         fireAgain = Time.time + fireSpeed; //I think you can remove this line
         Instantiate(bolt, boltSpawn01.position, boltSpawn01.rotation);
     }
 
     StartCoroutine(InvaderFireWeapon());
 }

And start that coroutine for the first time in some method that's called only once.

Comment
Add comment · 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

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

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

shot delay in between bullets 1 Answer

Loading Screen and Lerp 3 Answers

How to delay a function (how to use WaitForSeconds() and yield) 1 Answer

Yielding for a changing amount of time? 2 Answers

WaitForSeconds() Is not working. 5 Answers


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