2

EDIT: The answer that solves this problem is indeed in the answer of the post whose duplicate is this one. If you have the same problem as in the title, please refer to the other post.

I made a simple rig that moves stuff over time like this:

 Transform from;
 Transform to;
 float overTime;
 IUIAnimationEvent chain;
 public delegate void UIchain();
 public event UIchain NEXT_FUNCTION;
 public MoveAction(Transform from, Transform to, float overTime, IUIAnimationEvent chain)
 {
     this.from = from;
     this.to = to;
     this.overTime = overTime;
     this.chain = chain;
 }
 public void Move()
 {
     MonoBehaviour _lead = new MonoBehaviour();
     if (moveRoutine != null)
     {
         _lead.StopCoroutine(moveRoutine);
     }
     moveRoutine = _Move(from, to, overTime);
     _lead.StartCoroutine(moveRoutine);
 }
 IEnumerator _Move(Transform from, Transform to, float overTime)
 {
     Vector2 original = from.position;
     float timer = 0.0f;
     while (timer < overTime)
     {
         float step = Vector2.Distance(original, to.position) * (Time.deltaTime / overTime);
         from.position = Vector2.MoveTowards(from.position, to.position, step);
         timer += Time.deltaTime;
         yield return null;
     }
     if(NEXT_FUNCTION != null)
     {
         NEXT_FUNCTION();
     }
 }

However, to make it work like I wish, I have to instantiate them, so they can't be a MonoBehaviour. Notice what I did with the _lead variable. I made it so I could start coroutines like any other. If my class is NOT a MonoBehaviour, how to start a coroutine from it?

Or if that isn't possible, how to instantiate classes that ARE MonoBehaviour? I noticed the _use AddComponent instead, but the classes are not components. They are used by another component and will not be put on a GameObject from the inspector.

agiro
  • 2,018
  • 2
  • 30
  • 62

2 Answers2

1

Coroutines must be bound to a MonoBehaviour. Or in other words, you will need at least one MonoBehaviour to start a coroutine. And sadly, you cannot instantiate a MonoBehaviour:

var mono = new MonoBehaviour(); // will not work

There is a workaround that I can think of right now. You write your coroutine as usual and then you start it from another class that inherits from MonoBehaviour. That is, a function only needs to return IEnumerator in order to be started as Coroutine.

If another is started, the already started coroutine is stopped and a new one is called

If you want to do it inside a non-MonoBehaviour class I'm afraid it will not be possible.

Remember: You will need at least one MonoBehaviour to start a coroutine.

I will call what you want to achieve: a Coroutine Management feature and my understanding is that you want to include that feature inside your non-MonoBehaviour class. But thanks to my Remember quote above you cannot do it right now.

But including it in-side a .dll might be possible as a .dll can contain many classes. And you can use Access Modifiers to enforce your rules (the internal modifier is my favorite).

If I were you I would treat Coroutine Management as a separate problem and would build a .dll to handle them separately so that it would not mess up with my game-play business.

Cù Đức Hiếu
  • 5,569
  • 4
  • 27
  • 35
  • Thanks for the input. Generally that would work but I implemented the `void Move()` for the coroutine explicitely so that _only **one** `Move()` can effect one UI component at a time. If another is started, the already started coroutine is stopped and a new one is called._ – agiro Feb 07 '17 at 13:25
  • @agiro "If another is started, the already started coroutine is stopped and a new one is called" Please, ask this as a new question. – Programmer Feb 07 '17 at 13:28
  • @Programmer I already added that, now only one can effect one object, as I wanted, it wasn't a question, I can't start from another class because of it. – agiro Feb 07 '17 at 13:31
  • @agiro Ok. Got it. Glad your problem is solved. – Programmer Feb 07 '17 at 13:38
  • I have updated my answer. Hope it can shed some light on your problem. – Cù Đức Hiếu Feb 07 '17 at 13:47
0

You can't start coroutines from a class that is not a MonoBehaviour as the method StartCoroutine() is part of this class. Just create a new GameObject and then add your class as a Component on it

You can instantiate your class that inherit from MonoBehaviour (for this example MyClass) like this:

GameObject baseObject = new GameObject();
baseObject.AddComponent<MyClass>();

See singleton pattern for example

Ludovic Feltz
  • 11,416
  • 4
  • 47
  • 63
  • I plan to compile my functions like `Move()` or `RotateToGiven()` to .dll-s, and have a `script` on each of my `UI elements` that have to be animated and just get that from my main Ui manager and all should be fine. Doable? I'm concerned with the .dll part – agiro Feb 07 '17 at 13:23
  • 1
    You can. I keep trying to explain this. You must **not** drive your scrip from `MonoBehaviour`. You need a reference of it from any GameObject. – Programmer Feb 07 '17 at 13:23
  • 1
    @agiro So the cù-Đức-hiếu's solution should work fine – Ludovic Feltz Feb 07 '17 at 13:25
  • @Programmer The question is how to start a coroutine from a class that is not a `MonoBehaviour`. Can you? – Ludovic Feltz Feb 07 '17 at 13:26
  • Yes, @Programmer is indeed trying hard, but I'm ignorant atm :) The reason is that I have in mind what I _want_ but the _how_ is another thing. – agiro Feb 07 '17 at 13:27
  • @Ludovic Programmer have already answered to many of my questions about this UI anim feature I try to implement. It's about the .dll compilation I think. – agiro Feb 07 '17 at 13:28
  • 1
    @agiro My reply was to Ludovic not you. To Ludovic, yes you can. You need to pass in a reference of **any** MonoBehaviour in the scene. That reference can then be used to start and stop coroutines. Take a look at the duplicated answer if you don't still get it. – Programmer Feb 07 '17 at 13:35
  • @Programmer I get it now, i upvoted your answer ;) How can you know so many things, i see you on almost every post ^^ – Ludovic Feltz Feb 07 '17 at 13:38
  • @Programmer I didn't know that (the start of a coroutine). Good one. – agiro Feb 07 '17 at 13:40
  • 1
    lol not every post. Some of Unity questions. Happy coding! – Programmer Feb 07 '17 at 13:41
  • 1
    @Programmer So we will meet again :) Happy coding ;) – Ludovic Feltz Feb 07 '17 at 13:46
  • 1
    @Programmer Your solution was indeed fine and given that this indeed was a duplicate post. The code works now, I can chain my animations the way I please. Kudos! – agiro Feb 07 '17 at 14:10