How can you pass a Monobehaviour inside an instance of a non Monobehaviour class? I found this link where TonyLi mentions that you can pass a Monobehaviour to start and stop coroutines inside a instance of a class, but he does not show how you can do that. He does this theEvent.StartEvent(myMonoBehaviour); but he does not show where he gets myMonobehaviour from. I looked around on the internet but I cannot seem to find how.
Here is what I am trying to do. I want to run a coroutine inside an instance of a class. I also want to be able to stop the coroutine inside the instance of the class. I want to do it this way so that I don't have any objects in my scene that have large managers and also so that I can reuse the code for any object that I want to pingpong in this way. The code moves a Gameobject in one direction then takes a break and moves it in the other direction and takes a break again etc. But I cannot start the coroutine from outside the class.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[RequireComponent (typeof(Image))]
public class SpecialBar : MonoBehaviour {
public float rangeX;
public float breakTime;
public float step;
float startProgress = 0.5f;
PingPongGameObject pingPonger;
Color[] teamColors = new Color[]{new Color(255,136,0),new Color(0,170,255)};
void Start()
{
for(int i = 0; i < teamColors.Length; ++i)
{
teamColors[i] = StaticFunctions.NormalizeColor (teamColors[i]);
}
pingPonger = new PingPongGameObject (gameObject.transform.position,
new Vector3(rangeX,0.0f,0.0f),
gameObject,
startProgress,
breakTime,
step
);
}
}
The second class is where my coroutine is in.
public class PingPongGameObject
{
float step;
Vector3 center;
Vector3 range;
GameObject ball;
float progress;
float breakTime;
Vector3 endPos;
Vector3 oppositePosition;
public PingPongGameObject(Vector3 _center, Vector3 _range, GameObject _ball, float _startProgress, float _breakTime, float _step)
{
center = _center;
range = _range;
ball = _ball;
progress = _startProgress;
breakTime = _breakTime;
step = _step;
endPos = center - range;
oppositePosition = center + range;
// This is where I want to start the coroutine
}
public IEnumerator PingPong()
{
while (progress < 1) {
progress += Time.deltaTime * step;
Vector3 newPos = Vector3.Lerp (oppositePosition, endPos, progress);
ball.transform.position = newPos;
yield return null;
}
Vector3 temp = endPos;
endPos = oppositePosition;
oppositePosition = temp;
progress = 0;
yield return new WaitForSeconds (breakTime);
yield return null;
}
public float Step
{
set{step = value;}
}
public void StopCoroutine()
{
// This is where I want to stop the coroutine
}
}
You need an instance of some MonoBehaviour in order to run a coroutine.
You cannot start a coroutine function from a script that has its GameObject de-activated. The StartCoroutine function is a function under the MonoBehaviour class. When you have to start a coroutine on a deactivated GameObject, you need a reference to a MonoBehaviour object that has an active GameObject.
Coroutines are also stopped when the MonoBehaviour is destroyed or if the GameObject the MonoBehaviour is attached to is disabled. Coroutines are not stopped when a MonoBehaviour is disabled. An example of StartCoroutine: using UnityEngine; using System.
A coroutine is a function that allows pausing its execution and resuming from the same point after a condition is met. We can say, a coroutine is a special type of function used in unity to stop the execution until some certain condition is met and continues from where it had left off.
TonyLi mentions that you can pass a Monobehaviour to start and stop coroutines inside a instance of a class, but he does not show how you can do that. He does this
You are can do that with the this
keyword. The this keyword will get the current instance of MonoBehaviour
.
In this example there's a tree, which happens to have a component MonoScript
:
That particular instance of MonoScript
can if it wants (since it's a c# program) instantiate a general c# class, NonMonoScript
:
Class to pass MonoBehaviour
from:
public class MonoScript : MonoBehaviour
{
void Start()
{
NonMonoScript nonMonoScript = new NonMonoScript();
//Pass MonoBehaviour to non MonoBehaviour class
nonMonoScript.monoParser(this);
}
}
Class that receives pass MonoBehaviour
instance:
public class NonMonoScript
{
public void monoParser(MonoBehaviour mono)
{
//We can now use StartCoroutine from MonoBehaviour in a non MonoBehaviour script
mono.StartCoroutine(testFunction());
//And also use StopCoroutine function
mono.StopCoroutine(testFunction());
}
IEnumerator testFunction()
{
yield return new WaitForSeconds(3f);
Debug.Log("Test!");
}
}
You can also store the mono
reference from the monoParser
function in a local variable to be re-used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With