Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 willianbrasil · Feb 10, 2018 at 01:17 PM · ontriggerstay

flamethrower 2D not hitting sometimes

Hi, i have a script for the flame of my flamethrower and i've debugged all i could i'm using unity remote to test, idk if could cause this, i have a turret that fires like a flamethrower and damage target's every 0.4 seconds using ontriggerstay2d and 4 enemies in front of it, sometimes hits do not land on 1, 2 or 3 of them i've tried to check if any boxes were off at the time, or if anything was disabled and nothing so here's my code.

    void FixedUpdate() {
         if (dot_timer > 0)
             dot_timer -= Time.deltaTime;
         else
         {
             dot_timer = base_dot_timer;
             Debug.Log("should hit");
             Debug.Break();
         }
     }
 
     private void OnTriggerStay2D(Collider2D other)
     {
         if (dot_timer <= 0)
         {
             if (other.gameObject.layer == target_layer)
             {
                 Enemy_Manager enemy = other.gameObject.GetComponent<Enemy_Manager>();
                 enemy.Hp -= damage;
                 Debug.Log("hit");
                 enemy.Blink_fx.SetActive(true);
                 Vector3 screenPoint = Camera.main.WorldToViewportPoint(other.gameObject.transform.position);
                 bool onScreen = screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
                 if (onScreen)
                 {
                     for (sbyte i = 0; i < 30; i++)
                     {
                         if (!game_manager.TextInstPool[i].activeInHierarchy)
                         {
                             game_manager.TextInstPool[i].transform.position = other.gameObject.transform.localPosition;
                             game_manager.TextInstPool[i].SetActive(true);
                             game_manager.TextPool[i].text = damage.ToString();
                             break;
                         }
                     }
 
                 }
             }
         }
     }
Comment
Add comment · Show 13
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 pako · Feb 10, 2018 at 05:37 PM 1
Share

@willianbrasil your question is very unclear. Why would the turret select a different enemy every time, apparently using: Enemy_$$anonymous$$anager enemy = other.gameObject.GetComponent<Enemy_$$anonymous$$anager>(); where "other" would return the first collider it detects. So, why would it detect 4 different colliders?

Also, you should use Update() not FixedUpdate()in this case (you are not moving a rigidbody.

In any case, more info is needed about the problem.

avatar image Nomenokes pako · Feb 11, 2018 at 02:37 PM 1
Share

Agreed, use Update with deltaTime and FixedUpdate with real time. I think that willianbrasil's Enemy_$$anonymous$$anager is not a "manager" as we're used to but just a script attached to each enemy object.

avatar image pako Nomenokes · Feb 11, 2018 at 03:52 PM 1
Share

Actually, you are right. Last time I read his code was yesterday, and forgot that his call GetComponent<Enemy_$$anonymous$$anager>(). Today, I mistakenly thought that Enemy_$$anonymous$$anager was the code he posted in his question.

So, indeed Enemy_$$anonymous$$anager is not actually a "manager" per "normal "usage", as you say.

I think his code needs "untangling".

Show more comments
Show more comments
avatar image willianbrasil · Feb 11, 2018 at 01:38 PM 0
Share

@pako sorry about that, well actually we are talking about OnTriggerStay, so actually other will return all colliders that are colliding, one by one, and will run the code once for every collider it detecs.

So, what i have here is this scenario: a turret that tests a raycast against enemies, once it returns true, it will set active a fire of it's pool. The script that i showed here is used for the fire to hit all object colliding with it once every 0.4 seconds, from all my debug tests i can tell that: when i'm using Update() ins$$anonymous$$d of FixedUpdate() the fire won't hit any enemy when it should, and when it lands a hit, it will not hit all enemies, leaving one or two untouched.

What i've noted is that when i use FixedUpdate(), it will hit all enemies almost everytime, but eventualy one or two enemies are ignored, i debugged to see if they actually should have been hit at the collision time and, from all i've tested, the enemies should definetly have been hit.

avatar image pako willianbrasil · Feb 11, 2018 at 03:06 PM 0
Share

Per the documentation:

OnTriggerStay is called almost all the frames

https://docs.unity3d.com/ScriptReference/Collider.OnTriggerStay.html

...so it's not called every frame.

On the other hand, FixedUpdate() is called multiple times per frame.

Consequently, once dot_timer becomes less than 0 inside FixedUpdate(), it will make the condition if (dot_timer <= 0) true inside OnTriggerStay2D, and all is well, however, on the same frame FixedUpdate() will execute multiple times, so it will reset dot_timer = base_dot_timer, so for subsequent calls of OnTriggerStay2D if (dot_timer <= 0) will be false, and that seems to be the source of the problem, in combination with the fact that OnTriggerStay2D might miss a frame "here and there".

So, I think it might be best if you use just the raycasting, and "play" with the ti$$anonymous$$g of the raycasting to achieve the 0.4 s fire rate.

If you think that this would work with your mechanics and your remaining code, we could work out a solution.

avatar image Nomenokes pako · Feb 11, 2018 at 03:30 PM 0
Share

Yes, see my answer about the fixedupdate ti$$anonymous$$g, it's the same idea. Raycasting would be a lot cheaper but wouldn't get a residual flame effect, I suppose willianbrasil can balance between the options

avatar image pako willianbrasil · Feb 11, 2018 at 03:08 PM 0
Share

BTW it might be helpful to post some more relevant code, especially where you do your raycasting.

avatar image willianbrasil · Feb 11, 2018 at 01:42 PM 0
Share

sorry i took quite some time to reply, i'ts the first time someone answered me and i didn't knew that comments were hidden.

avatar image willianbrasil · Feb 11, 2018 at 09:39 PM 0
Share

@pako @Nomenokes hi here is a piece of my fire turret's code, sorry that it's a little big, i use a raycast to check if there is any enemy within the turret's range so it'll start the fire, is using a RaycastAll really cheaper then ontriggerstay? because i've seen a lot of posts saying that raycasts are very expensive since you have to use it every frame, also one thing that bothers me is that when i try to make timed events they seem unaccurate, what is the best way to guarantee that i'll get the desired effect always at the desired time? i try to use FixedUpdate for that.

 private void FixedUpdate()
     {
         if (script.Activated)
         {
             Turret_Enemy_Raycast();
             StartAtk();
         }
         else
             CancelAtk();
         EndAtk();
     }
 
     private void Turret_Enemy_Raycast()
     {
         hit = Physics2D.Raycast(origin, new Vector2(script.Dir.x, 0), script.Range, layer_mask_hit);
         hit2 = Physics2D.Raycast(origin2, new Vector2(-script.Dir.x, 0), script.Range, layer_mask_hit);
         Debug.DrawRay(origin, new Vector2(script.Dir.x, 0));
         Debug.DrawRay(origin2, new Vector2(-script.Dir.x, 0));
         if (hit)
         {
             Turret_Fire();
         }
         else
         {
             if (isAtk)
             {
                 for (sbyte i = 0; i < 2; i++)
                 {
                     if (fire[i].Firing)
                     {
                         fire[i].Firing = false;
                         fire[i].Em = false;
                         fire[i].Fading = true;
                         isAtk = false;
                         fadingNum = i;
                         break;
                     }
                 }
             }
         }
         if (hit2)
         {
             Turret_Fire2();
         }
         else
         {
             if (isAtk2)
             {
                 for (sbyte i = 0; i < 2; i++)
                 {
                     if (fire2[i].Firing)
                     {
                         fire2[i].Firing = false;
                         fire2[i].Em = false;
                         fire2[i].Fading = true;
                         isAtk2 = false;
                         fadingNum2 = i;
                         break;
                     }
                 }
             }
         }
     }



avatar image pako willianbrasil · Feb 12, 2018 at 12:45 PM 0
Share

@willianbrasil I'm still confused... If this is (part of) the script that is attached on the turret, where is the script you posted in your question attached?

There's too much info missing to be able to give a complete answer, e.g. script names, variable declarations, your general setup...

Please read and follow the FAQ before posting.

avatar image willianbrasil pako · Feb 12, 2018 at 07:05 PM 0
Share

@pako Actually i have been quite specific into that, my first words here were: i have a script for the flame of my flamethrowe, which is the first code that i have posted and when i posted this code i've said, this is a part of my turret's code, i've just posted this part so you could see that the turret itself raycasts for any enemies, so it can start shooting and the fire itself use OntriggerStay to distribute damage through all instances colliding with it, the reason i do not use a RaycastAll at the turret is because i've read in unity best practices that raycasts are expensive, since i'm going for android i'm seeking for the best optimization as much as i can

2 Replies

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

Answer by willianbrasil · Feb 12, 2018 at 08:09 PM

I've come up with and answer, it happens that ontriggerstay isn't reliable for any over time effect, and also RaycastAll is very much more expensive than the situation demmands, to solve this i've created a enemy list, whenever an enemy collides with the fire(`OnTriggerEnter2D`), it will add him into the list, (`OnTriggerExit2D`) will remove him from the list, and when the timer reaches 0 it'll apply damage to every enemy on the list, i believe this is one of the best ways to make AoE and DoT heres my fire's code now:

     private Game_Manager game_manager;
     private List<Enemy_Manager> enemies;
     private int target_layer;
     private float base_dot_timer;
     private float dot_timer = 0;
     private int damage;
     private Vector2 dir;
 
     // Use this for initialization
     void Start () {
         Vector3 scale = transform.localScale;
         scale.Set(-dir.x, 1, 1);
         transform.localScale = scale;
         enemies = new List<Enemy_Manager>();
     }
 
     // Update is called once per frame
     void FixedUpdate() {
         if (dot_timer > 0)
             dot_timer -= Time.deltaTime;
         else
         {
             for(sbyte i = 0; i < enemies.Count; i++)
             {
                 enemies[i].Hp -= damage;
                 Debug.Log("hit");
                 enemies[i].Blink_fx.SetActive(true);
                 Vector3 screenPoint = Camera.main.WorldToViewportPoint(enemies[i].transform.position);
                 bool onScreen = screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
                 if (onScreen)
                 {
                     for (sbyte s = 0; s < 30; s++)
                     {
                         if (!game_manager.TextInstPool[s].activeInHierarchy)
                         {
                             game_manager.TextInstPool[s].transform.position = enemies[i].transform.localPosition;
                             game_manager.TextInstPool[s].SetActive(true);
                             game_manager.TextPool[s].text = damage.ToString();
                             break;
                         }
                     }
 
                 }
             }
             dot_timer = base_dot_timer;
         }
     }
 
     private void OnTriggerEnter2D(Collider2D other)
     {
         if (other.gameObject.layer == target_layer)
         {
             enemies.Add(other.gameObject.GetComponent<Enemy_Manager>());
         }
     }
 
     private void OnTriggerExit2D(Collider2D other)
     {
         if (other.gameObject.layer == target_layer)
         {
             enemies.Remove(other.gameObject.GetComponent<Enemy_Manager>());
         }
     }

thank for all your answers and sorry being unclear with my problem

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
avatar image
0

Answer by Nomenokes · Feb 11, 2018 at 02:31 PM

I think the problem is that OnTriggerStay will not necessarily line up with the FixedUpdate function. The moment that dot_timer is 0, there might not be an OnTriggerStay called. What you should do is make the dot_timer dependent on OnTriggerStay. For example,

      void FixedUpdate() {
      }
  
      private void OnTriggerStay2D(Collider2D other)
      {
          dot_timer -=.01; //Physics is based on real time, not deltaTime.
          if (dot_timer <= 0)
          {
               dot_timer=base_dot_timer;
 //...
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 Nomenokes · Feb 11, 2018 at 02:36 PM 0
Share

The problem would have been worse when you had Update going because it calls less frequently

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

76 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 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 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 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

OnTriggerEnter only working once. 0 Answers

Detect gameObjects within range and assign them as movetarget 1 Answer

Can't catch event of the pressing the button 1 Answer

Problem with OnTriggerStay()... 1 Answer

Work around for onTriggerStay? 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