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 /
  • Help Room /
avatar image
0
Question by Filip8429 · Sep 13, 2020 at 01:48 PM · scripting problemcolliderprogrammingcoroutines

How to stop one specific instance of a Coroutine

So I have an OnTriggerEnter function that removes health every second usig a Coroutine. I want to stop it with a OnTriggerEnter function and StopCoroutine. While this works with only one gameObject in the game, this breaks when multiple colliders enter and leave the trigger zone since it always cancels "routine". What would be the best way to stop just the Coroutine for the object that left the Collider? I feel like there is an easy solution for it but I just don't see it.

OnTriggerEnter/Exit

     private float delay= 1f;
     void OnTriggerEnter(Collider other)
     {
         DealDamage(other, delay);
     }
     private void OnTriggerExit(Collider other)
     {
         StopDamage();
     }



Coroutine

 private Coroutine routine;
 private void DealDamage(Collider col, float damageRate)
 {
     var health = col.GetComponent<IChangeHealth>();
     if (health == null) return;
     routine = StartCoroutine((DamageEverySecond(health, damageRate)));
 }
 IEnumerator DamageEverySecond(IChangeHealth health, float rate)
 {
     while (true)
     {
        health.RemoveHealth(Damage);       
                yield return new WaitForSeconds(rate); 
     }
 }
 protected void StopDamage()
 {
     StopCoroutine(routine);
 }
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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by streeetwalker · Sep 13, 2020 at 02:12 PM

@Filip8429, if the coroutine code is in a script as a component attached to the object your stopping, then you only need to get a reference to that script on the specific object and call StopDamage.

For example, inside of your OnTriggerExit

 other.gameObject.GetComponent<what ever class name holds the coroutine>().StopDamage();



Comment
Add comment · Show 3 · 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 Filip8429 · Sep 13, 2020 at 05:25 PM 0
Share

Hey thanks for the answer. I might try it out later, however I want to keep both functions in the same script actually.

avatar image streeetwalker Filip8429 · Sep 13, 2020 at 05:43 PM 0
Share

That wasn't obvious in your post, but it doesn't matter if you keep the code in one class script or not. You must have several objects with this same script on it? If you don't you are going to have problems getting your idea to work.

You need to start and stop the coroutine on the one that your object collides with. So, you need to also apply the same concept when you start the coroutine, as well - I didn't catch that earlier

OnTriggerEnter you tell the script on object you are colliding with to start it's coroutine (using the same code I delineated). The script on the object you are colliding with keeps a reference to the coroutine.

Likewise, OnTriggerLeave, you tell the script on the object that is leaving the collider to stop it's coroutine. It can do that because it's script keeps its own reference to its coroutine

Coroutines are function calls that run asynchronously. Like function calls, every time you start one a unique copy of the coroutine is created - in the case of a coroutine that unique copy is placed into the coroutine queue.

avatar image Filip8429 streeetwalker · Sep 13, 2020 at 06:57 PM 0
Share

Thanks for the explanation again. I guess it would be more clear if I would formulate my question like "How do I keep reference to one specific Coroutine?". Because even if I put it on the other gameObject, other classes can call that Coroutine, creating a new instance of it. Simply putting a global variable won't work as other scripts might override it.

avatar image
0

Answer by ransomink · Sep 13, 2020 at 09:05 PM

Easiest solution is to create a dictionary with a collider as the key and coroutine as the value

 private Coroutine   _routine;
 private Dictionary<Collider, Coroutine> _colliders;


In DealDamage, after assigning the routine variable to the coroutine, add it to the dictionary

 _routine = StartCoroutine((DamageEverySecond(health, rate)));
 _colliders[col] = _routine; 


In StopDamage, retrieve the coroutine from the dictionary, stop it, then remove it

 Coroutine routine = _colliders[col];
 StopCoroutine(routine); 
 _colliders.Remove(col);


This will allow multiple objects to enter and exit the damage zone and apply damage to each without interruption. I created a small test and it works. Here is my test below

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 namespace Filip8429
 {
     public class DamageOverTime : MonoBehaviour
     {
         [SerializeField] private float delay = 1f;
         [SerializeField] private float damage;
 
         private Coroutine   _routine;
         private WaitForSeconds _wait;
         private Dictionary<Collider, Coroutine> _colliders;
 
         public float Damage { get => damage; private set => damage = value; }
 
         private void Start()
         {
             _colliders = new Dictionary<Collider, Coroutine>();
         }
 
         private void OnTriggerEnter(Collider other)
         {
             Debug.Log($"<color=yellow>{other.name}</color> entered the damage zone");
             DealDamage(other, delay);
         }
 
         private void DealDamage(Collider col, float rate)
         {
             var health = col.GetComponent<IChangeHealth>();
             if (health == null) return;
             _wait    = new WaitForSeconds(rate);
             _routine = StartCoroutine((DamageEverySecond(health, rate)));
             Debug.Log($"DamageOverTime Coroutine started on <color=yellow>{col.name}</color>");
             _colliders[col] = _routine;
         }
 
         private void OnTriggerExit(Collider other)
         {
             StopDamage(other);
         }
 
         protected void StopDamage(Collider col)
         {
             Coroutine routine = _colliders[col];
             StopCoroutine(routine);
             _colliders.Remove(col);
             Debug.Log($"DamageOverTime Coroutine stopped on <color=yellow>{col.name}</color>");
         }
 
         private IEnumerator DamageEverySecond(IChangeHealth health, float rate)
         {
             while (true)
             {
                 health.RemoveHealth(Damage);
                 yield return _wait;
             }
         }
     }
 }
 
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

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

Where am i going wrong with my repeating background? 0 Answers

Projectiles not shooting correctly 1 Answer

How to teleport a car? 1 Answer

why is this script not working??? 0 Answers

Avoid overlapping drag & drop game objects in 3d space 0 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