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 rickymanalo · Jul 08, 2020 at 02:32 PM · coroutinecomponent

Can I use a custom component as a parameter of a IEnumerator?

I'm trying to make a poison/bleed mechanic by getting the GameObjectof the enemy hit then getting my hp helper custom Component of that GameObject then pass it to a helper class that would start a Coroutine to do the poison/bleed.

In that Coroutine, I passed the hp helper, dmg, and the duration to the Coroutine. I keep getting a NPE to something that I don't know, it just point to the StartCoroutine and doesn't point out which variable was causing the NPE so I decided to change way I call the IEnumerator. Before I was using something like StartCoroutine(Coroutine(hpHelper, dmg, duration)) then changed to StartCoroutine("Coroutine", params) where params is object[]. Using the latter just gave some stupid, pointing to a line that doesn't make sense so I reverted to using StartCoroutine(Coroutine(hpHelper, dmg, duration)).

I swear that everything is not null. I'm still trying about what is the best way to make things work, I'm open to your suggestion on how can I implement this.

This is the error I'm getting if you're interested.

 NullReferenceException
 UnityEngine.MonoBehaviour.StartCoroutine (System.Collections.IEnumerator routine) (at <f38c71c86aa64e299d4cea9fb7c715e1>:0)


Here's the code where it all happens.

 public void StartDebuff(Skill skill, GameObject target){
     EnemyController enemyController = target.GetComponent<EnemyController>();
     HealthHelper targetHpHelp = target.GetComponent<HealthHelper>();
 
     enemyController.debuffLst.Add(skill.debuffType);
 
     switch(skill.debuffType){
         case Skill.DebuffType.Poison:
             StartCoroutine( DamagePerSecondDebuff(targetHpHelp, skill.buffDebuffValue, skill.buffDebuffDuration) );
             break;
         case Skill.DebuffType.Bleed:
             StartCoroutine( DamagePerSecondDebuff(targetHpHelp, skill.buffDebuffValue, skill.buffDebuffDuration) );
             break;
         case Skill.DebuffType.Burn:
             StartCoroutine( DamagePerSecondDebuff(targetHpHelp, skill.buffDebuffValue, skill.buffDebuffDuration) );
             break;
     }
 }




After some suggestion, I realized that I can't use a MonoBehaviour class for what I want to do. So I did some changes to my code and made everything a Singleton. CoroutineHelper class that contains StartDebuff is now a singleton and my GameManager is also now a Singleton.

Now, I call StartDebuff like this

 CoroutineHelper.Instance.StartDebuff(skill, colllidedToArr[i].gameObject);

Then call a real StartCoroutine() inside CoroutineHelper like this

 GameManager.Instance.StartChildCoroutine( DamagePerSecondDebuff(targetHpHelp, skill.buffDebuffValue, skill.buffDebuffDuration) );

And that function looks like this

 public void StartChildCoroutine(IEnumerator coroutineMethod){
     try{
         StartCoroutine(coroutineMethod);
     }catch(Exception e){
         Debug.Log("StartChildCoroutine err: "+e);
     }
 }

And I still get a mysterious NPE.

 StartChildCoroutine err: System.NullReferenceException
   at (wrapper managed-to-native) UnityEngine.MonoBehaviour.IsObjectMonoBehaviour(UnityEngine.Object)
   at UnityEngine.MonoBehaviour.StartCoroutine (System.Collections.IEnumerator routine) [0x00014] in <f38c71c86aa64e299d4cea9fb7c715e1>:0 
   at GameManager.StartChildCoroutine (System.Collections.IEnumerator coroutineMethod) [0x00002] in PATH\GameManager.cs:40 
 UnityEngine.Debug:Log(Object)
 GameManager:StartChildCoroutine(IEnumerator) (at Assets/Scripts/Utils/GameManager.cs:42)
 CoroutineHelper:StartDebuff(Skill, GameObject) (at Assets/Scripts/Utils/CoroutineHelper.cs:40)
 AOEController:Start() (at Assets/Scripts/Controllers/Skills/AOEController.cs:35)


Comment
Add comment · Show 7
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 Captain_Pineapple · Jul 08, 2020 at 03:10 PM 0
Share

could you share the relevant code parts?

avatar image Captain_Pineapple Captain_Pineapple · Jul 08, 2020 at 09:15 PM 0
Share

also could you run this in editor or do a debug build? This way it will actually pinpoint the exact line of code for you.

avatar image rickymanalo Captain_Pineapple · Jul 09, 2020 at 09:43 AM 0
Share

I know the actual line of the error. It points to the first StartCoroutine. When I double click the error, it does point me to the file and the line that caused the error. But just having a line without knowing which exact variable is causing the error is kinda useless. As someone who came from a language (it's not really a new language) with a specialized IDE for developing like android, I find Unity kinda disappointing with it's lack of the features that make developers life easier.

avatar image rickymanalo · Jul 08, 2020 at 03:26 PM 0
Share

added some code. hope that's enough

avatar image Bunny83 rickymanalo · Jul 08, 2020 at 04:46 PM 1
Share

in which class is your "StartDebuff" method defined? Since you directly use StartCoroutine this class has to be a $$anonymous$$onoBehaviour derived class. So do you actually use a valid instance of that class when you try to call this method? Keep in $$anonymous$$d that you can not create $$anonymous$$onoBehaviour derived classes with "new". Components / $$anonymous$$onoBehaviours have to be attached to a gameobject in the scene in order to run coroutines.


Note that swearing that something is not null doesn't really help ^^. Have you actually checked that the parameters you pass are not null? Keep in $$anonymous$$d that GetComponent will return null (or a fake null object when testing inside the editor) when the component does not exist on the given gameobject.

avatar image Captain_Pineapple Bunny83 · Jul 08, 2020 at 09:13 PM 0
Share

interesting thoughts. Though what i am not sure about: The instance of the object must be somehow valid, otherwise you could not even call StartDebuffitself or am i missing something?

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by rickymanalo · Jul 13, 2020 at 03:13 PM

Finally made it work. The cause was my incorrect implementation of the various Singletons I made

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

Answer by Tripleganger · Jul 09, 2020 at 09:50 AM

Hi! Unfortunately, you can only pass one parameter when dealing with coroutines.

Also, as a general tip, if possible, try to assign your Components instead of .GetComponent; it is more computationally expensive than most people think.

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 rickymanalo · Jul 09, 2020 at 11:02 AM 0
Share

Oh, that sucks. But will an object array be acceptable? I saw a solution like that where you put the variables you want to pass to the IEnumerator then retrieve those variables using their respective index. I tried it but it still seems to cause an NP$$anonymous$$ I think I get why GetComponent() would be expensive. Thanks for the info, will try them later.

avatar image Tripleganger · Jul 09, 2020 at 12:21 PM 0
Share

Yes, you can totally do that! Here's an example.

 void YourFunction()
 {
 string myString = "Hello";
 int myInt = 13;
 float myFloat = 3.14f;
 object[] myObjects = new object[3]{myString, myInt, myFloat};
 StartCoroutine($$anonymous$$yCoroutine, myObjects);
 } 
 
 private IEnumerator $$anonymous$$yCoroutine(myParameters)
 {
 //Stuff - you'd get myString as myParameters[0], and so on.
 yield return null;
 }
 

I hope this helps.

avatar image rickymanalo · Jul 09, 2020 at 02:01 PM 0
Share

Based on your first suggestion, I tried the one where you put stuff on a object[] while still doing GetComponent() inside StartDebuff. Unity is still throwing NPE and a bunch more mysterious one like Identifier expected so I ditch it. The next thing I did was to not use GetComponent inside StartDebuff and pass the actual values to it. Just to be sure, I added checks if the variables that I would pass is null then log the value it isn't before I call StartDebuff. What I got are enemy (EnemyController) and enemy (HealthHelper). But for some reason, the line that calls StartDebuffnow throws a NP$$anonymous$$ I'm really confused.

avatar image
0

Answer by Slimer37 · Jul 09, 2020 at 12:31 AM

All I can think of is maybe one of the scripts (either the one that's a parameter or the one running the coroutine) was destroyed, hence the null reference. I have no other ideas. A little tip, though: you can use multiple cases for a single block.

      switch(skill.debuffType){
          case Skill.DebuffType.Poison:
          case Skill.DebuffType.Bleed:
          case Skill.DebuffType.Burn:
              StartCoroutine( DamagePerSecondDebuff(targetHpHelp, skill.buffDebuffValue, skill.buffDebuffDuration) );
              break;
 
      // or you could just use an 'if'
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 rickymanalo · Jul 09, 2020 at 08:51 AM 0
Share

I saw something like that but vscode didn't like it for some reason, or my vscode is just being slow to recognize that it was valid. The GameObject is not going to be destroyed because I only destroy it after the duration of the skill. I call StartDebuff in the Start() of the GameObject. Could that be a reason for the NPE?

switch looks more elegant though lol

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

143 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

Related Questions

Coroutine in Extension Method 1 Answer

Convert Component to Actual Type C# to call a coroutine 0 Answers

Coroutine set up but doesn't seem to be working, what am i doing wrong? 1 Answer

2D Animation does not start 1 Answer

Simple question about OnMouseButtonAsUp 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