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 AKJ9 · May 04, 2014 at 01:18 PM · c#instantiatecoroutineprojectilefire

Working projectile scripts do not work due to if condition

Hi there,

I've successfully managed to have my player shoot fireballs from his hands. However, this is done on a key press.

I now want my enemy to fire fireballs, and so I tried to use exactly the same script. However, the fireball stays in its position and does not move forward. The reason for this is because the firing of this fireball happens when the enemy is a certain distance away from my player. Therefore, I believe the fireball keeps instantiating itself, keeping each one from moving forward. I tested this by adding a sound, and the sound rapidly repeats multiple times, indicating that the fireballs are being instantiated far too often.

Here is a code snippet from my first script, which is attached to my enemy game object:

 void PatrolAndChase()
     {
                 // calculate the distance to the player
                 int distanceToPlayer = (int)Vector3.Distance (player.transform.position, transform.position);
         
                 // calculate vector direction to the player
                 Vector3 directionToPlayer = transform.position - player.transform.position;
         
                 // calculate the angle between AI forward vector and direction toward player
                 // we use Mathf.Abs to store the absolute value (i.e. always positive)
                 int angle = (int)Mathf.Abs (Vector3.Angle (transform.forward, directionToPlayer));
     **if
         (distanceToPlayer > 60) {
                         StartCoroutine (Shoot ());
                 }**
                 // if player is within 30m and angle is greater than 130 then begin chasing the player
                 else if (distanceToPlayer < 30 && angle > 130) {
                         // move towards the players position
                         //MoveTowards (player.transform.position);
             
                         // attack the player ONLY if not already attacking
                         if (!attacking && distanceToPlayer < 15) {
                                 StartCoroutine (Attack ());
                         } else if (!attacking) {
                                 // player is "out of sight"
                                 MoveTowards (player.transform.position);
                         }
                 } 
         else {
                         // patrol
                         Patrol ();
             
                         // if attacking, then toggle to stop
             
                 }
 
         }

The code surrounded by asterisks is what we're interested in. This calls the Shoot coroutine, which is in the same script and is as follows:

 IEnumerator Shoot()
     {
         yield return new WaitForSeconds(2);
         attacking  = true;
            StartCoroutine (BowserFireball.Instance.Fire());
         attacking  = false;
 
     }

We can see here that this coroutine is calling yet another coroutine from my BowserFireball script. I've also added a WaitForSeconds clause to have the fireball sequence happen every 2 seconds. However, the routinely firing of the fireball does not work. Here is the BowserFireball script:

 using System.Collections;
 
 public class BowserFireball : MonoBehaviour {
     public static BowserFireball Instance { get; private set; }
     
     public Rigidbody projectile;
     public AudioClip fireballSound;
     public GameObject target;
     
     void Awake()
     {
         if (Instance == null) 
         {
             Instance = this;
         }
         else
         {
             Destroy(gameObject);
         }
     }
     
     public IEnumerator Fire()
     {
         animation.CrossFade("fireball (1)", 0.2F);
 
         audio.PlayOneShot (fireballSound);
         
         Rigidbody instantiatedProjectile = Instantiate (projectile,
                                                         transform.position,
                                                         transform.rotation)
             as Rigidbody;
         instantiatedProjectile.velocity = transform.TransformDirection (new Vector3 (0, 0, 50));
         yield return new WaitForSeconds(2);
         Destroy (instantiatedProjectile.gameObject);
     }
 }

This script governs the firing of the fireball and how it destroys itself. It is attached to an empty game object called FireballSpawn, which is a child of my enemy.

As stated previously, these scripts (with a few tweaks) worked for my player, but not for my enemy (because of the condition that the enemy fires the fireball constantly if he's a certain distance away from my player, I'm assuming). I need my enemy to fire a fireball every 1.5-3 seconds or so, so that 1): it is more routine and not a constant flow of fireballs and 2) (and most importantly): my fireballs can actually move and the noise he makes happens once per fire.

Your time and support would be thoroughly appreciated,

Many thanks!

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
0

Answer by robertbu · May 04, 2014 at 02:36 PM

I'm guessing a bit because the code I need to see to nail down the problem is not here. I'm guessing that you are calling PatrolAndChase() frequently...perhaps every frame or FixedUpdate(). For each one of those calls, you are generating a new coroutine. So if your game is running at approximately 60 fps, in the 2 seconds that Shoot() waits before firing, you stack, your code will stack up 120 coroutines. At the end of 2 seconds, you will start to see calls to BowserFireball.Instance.Fire() at approximately one frame apart. So you are going to need to figure out some mechanism so that Shot() is not call while it is currently running. Something as simple as a boolean flag:

 IEnumerator Shoot()
 {
    shooting = true;
    yield return new WaitForSeconds(2);
    attacking  = true;
    StartCoroutine (BowserFireball.Instance.Fire());
    attacking  = false;
    shooting = false;
 }  

Then your check would become:

  if (!shooting && distanceToPlayer > 60)
Comment
Add comment · Show 4 · 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 AKJ9 · May 04, 2014 at 07:51 PM 0
Share

@robertbu Thanks very much for your time. Yes, PatrolAndChase() is happening very frequently as I forgot to mention that the Waypoint assigned to my enemy is on my player, which means he'll always be following him and so if he gets close PatrolAndChase() will run.

I will give your solution a try and let you know in due course. Once again, your help is much appreciated!

avatar image AKJ9 · May 05, 2014 at 12:49 AM 0
Share

@robertbu After much, much rearranging of and experimenting with code, I still haven't managed to achieve my desired outcome. Here's my code in Shoot():

     IEnumerator Shoot()
     {            
         shooting = true;
         animation.Play("fireball (1)");
         audio.PlayOneShot (fireballSound);
         StartCoroutine (BowserFireball.Instance.Fire());
         yield return new WaitForSeconds(animation["fireball (1)"].length);
         shooting = false;
     }  

What happens here is my enemy runs towards my player, attempts to do his fireball animation but then gets cut off and starts running again. The fireball also does not move forward and ins$$anonymous$$d freezes there (possibly because loads are instantiating?). However, the sound correctly plays once every couple of seconds (the animation's length of time), so that's a start! :-)

If I move animation.Play("fireball (1)"); and yield return new WaitForSeconds(animation["fireball (1)"].length); ABOVE shooting = true;, then the animation plays fully but then the sound rapidly plays at multiple times again, as well as the fireball continuing to remain still - almost back to square one! So both code attempts do a different part of what I want to achieve, but none get the fireball moving!

With this information, are you able to help me resolve this issue? This is the final puzzle piece to my game, and I really don't know what to do! In case you need it, here is my BowserFireball script:

 using UnityEngine;
 using System.Collections;
 
 public class BowserFireball : $$anonymous$$onoBehaviour {
     public static BowserFireball Instance { get; private set; }
     
     public Rigidbody projectile;
     public GameObject target;
     public AudioClip fireballSound;
 
     void Awake()
     {
         if (Instance == null) 
         {
             Instance = this;
         }
         else
         {
             Destroy(gameObject);
         }
     }
     
     public IEnumerator Fire()
     {
 
 
         Rigidbody instantiatedProjectile = Instantiate (projectile,
                                                         transform.position,
                                                         transform.rotation)
             as Rigidbody;
         instantiatedProjectile.velocity = transform.TransformDirection (new Vector3 (0, 0, 50));
         yield return new WaitForSeconds(3);
         Destroy (instantiatedProjectile.gameObject);
     }
 }

$$anonymous$$any thanks for all your time!

avatar image AKJ9 · May 06, 2014 at 08:02 PM 0
Share

@robertbu Sorry to pester you, did you manage to look into my above comment? This is really starting to grate on me! Could anyone assist on this matter please?

$$anonymous$$any thanks for your time!

avatar image robertbu · May 06, 2014 at 11:12 PM 0
Share

There are potentially multiple issues, but I spot one here:

 IEnumerator Shoot()
     {
        yield return new WaitForSeconds(2);
        attacking  = true;
         StartCoroutine (BowserFireball.Instance.Fire());
        attacking  = false;
  
     }

You are setting 'attacking' to true after the two second wait. That means that during that two seconds, your coroutines are stacking up just like they did originally. You need to move the:

 attacking = true; 

...line to the first line of the 'Shoot' function. That way once a shoot has be instigated, no more shots will be taken.

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

20 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

Related Questions

Make multiple Projectiles move at the same Time... 0 Answers

Distribute terrain in zones 3 Answers

IEnumerator not looping correctly? 1 Answer

How to disable a script on a bunch of instantiated objects with tag ? 1 Answer

c# 2D top down, fire projectale which continuously move in a direction 3 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