- Home /
Instancing class automatically?
I dont know how to ask it but.
I have this "utility script"
using UnityEngine;
using System.Collections;
using System;
public class Xutil {
bool wait_bool;
float wait_time;
public bool Wait(float Interval )
{
wait_time += Time.deltaTime;
if( wait_time > Interval )
{
wait_bool = true;
}
else
{
wait_bool = false;
}
return wait_bool;
}
}
Ok , now, I want to call the function "Wait" on my other scripts , simply by doing : Xutil.Wait(5);
Right now it doesen't work unless I create a new instance anytime i want to use it. But that's not what I am looking for, simply because I am looking to call the function very often in my scripts.
What I am looking for is a sort of script that will automatically instance itself when called. Something like how the Mathf.Lerp works.
If I try and make it static, it works only if is called once, again not what I need.
So how do I create and instance an utility function without having to define a new one every single time?
If anyone can shed some light around here , I would appreciate it greatly!
Thank you.
Answer by Bunny83 · Aug 17, 2016 at 04:07 PM
You seem to have some difficulties to understand the fundamental difference between methods / functions / code and "state". Variables represent state as they store something for a certain period of time.
There are methods which are "stateless" and there are some which have some sort of internal state. Non static class methods always have state as they always belong to one particular class instance. Static methods can also have state, but they can only access static variables.
Your wait method does require state. You basically have those options:
If your method is static you could use a static variable. However this will limit you to one wait time. So you can't wait for two different times simultaneously. This is also a bad idea since "global state == evil".
If your method is static you could pass the required state via ref parameter. So the state isn't bound to the method / class but is provided from outside. A ref parameter can be changed inside the method. This allows as many "wait times" as you want since it only depends on the variable you pass to the method. Each time you want to use the wait method you have to have a seperate persistant variable (not a local var).
If your method is non static (so an instance method) you have to create a new instance of your class for each seperate timer you want to run in parallel.
If you fear the garbage that a class instance creates you could also use a "mutating struct". Mutating struct are also considered bad since it's easy to use them wrong.
I'm also not really sure how you would want to use your utility method. if you want to wait for a certain time you actually need:
something that starts the timer
something that check the timer each frame if it has expired
and maybe something that allows the timer to stop.
Your internal state (the "wait_time" variable) is initially "0". But you don't provide any way to reset it in order to start over. Further more once wait_time has crossed the Interval it will return true every frame.
Lerp (since you used it as comparison) doesn't have any state. It just calculates the return value based on the passed parameters. It literally is implemented like this:
public static float Lerp(float a, float b, float t)
{
return a + (b - a) * Mathf.Clamp01(t);
}
and Clamp01 is implemented like this:
public static float Clamp01(float value)
{
if (value < 0f)
{
return 0f;
}
if (value > 1f)
{
return 1f;
}
return value;
}
Both methods don't use any external variables inside the method. When Lerp is used correctly you have to keep the state yourself: the "t" value. Each time you call lerp you have to pass it along.
I don't see any advantanges of your utility function as it effectively executes two lines of code and both require state variables. You could do:
public static bool Wait(float Interval, ref float currentTime)
{
currentTime += Time.deltaTime;
return currentTime > Interval;
}
Here the user of that method has to keep the state variable somewhere else so you can do
float timer_state = 0;
void Update()
{
if (Xutil.Wait(10f, ref timer_state))
{
// This will be executed after 10 seconds every frame.
}
}
To "reset" the timer you have to set timer_state back to 0. However this isn't really easier than
float timer_state = 0;
void Update()
{
timer_state += Time.deltaTime;
if (timer_state > 10f)
{
// This will be executed after 10 seconds every frame.
}
}
Which does exactly the same and is more clear to read and easier to adapt to your needs.
Maybe you want something like my CoroutineHelper class? It's implemented as a singleton MonoBehaviour class which is used as host for as many coroutines as you like. I've created a utility class that can be used to "schedule" certain tasks without the need of implementing a coroutine yourself. It also can be used inside any class, also classes that are not derived from MonoBehaviour.
For example when the following is executed once it will start a coroutine that runs the anonymous method after 5 seconds:
Run.After(5f, ()=> {
Debug.Log("You see this 5 seconds later");
});
Unity's coroutine system is also a way to introduce state. Each coroutine is actually a statemachine. Each time you call StartCoroutine Unity creates a "Coroutine" class instance which holds all the information needed.
Though i'm not sure what your final goal is, so i'm not sure if this helps you. To me it seems you already have difficulties even define how you want to use your method.
I cant thank you enough for the extremely well detailed answer.
It finally feels clear now, and I learnt many new things just from this answer only.
Thanks again for the time!
Answer by DougMcFarlane · Aug 17, 2016 at 05:50 PM
You would use a static method for doing those types of calls. Your specific example however would be more difficult to get working since you can't normally wait for some result later (timing) before your function returns. For this you would need to use coroutines.
But Unity has a built in method to pause your code and wait for a predetermined number of seconds. It uses coroutines to accomplish this, but it is required in order to have code behave in this manner.
WaitForSeconds: https://docs.unity3d.com/ScriptReference/WaitForSeconds.html
Your answer
![](https://koobas.hobune.stream/wayback/20220612091015im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Getting NullReferenceException when creating class instance using List 1 Answer
A Variable that can hold different class Objects 1 Answer
C# Utility Class 1 Answer