Is There A Consistent Method That's Not Fixed/Update() or OnGUI() in Unity? - unity3d

So, I'm working on a unity project and I find myself with functions that don't need to be called 33 times per second or every 0.02 seconds. I'm not sure how often then GUI renders. Is there a method like the aforementioned that takes place maybe.. four times per second?
Because if not, I'd have to make one and that seems like it in itself will cost resources.

You can create the method that has to be executed X times per second, and call it using InvokeRepeating.
Something like this:
InvokeRepeating("methodName", 0.0, 1.0/X);
You could call this one in the Start() function.
//Example (executing "methodName" 4 times per second).
void Start(){
InvokeRepeating("methodName", 0.0, 0.25f);
}

for this cases you can use a corrutine
this method can help you
void Start(){
StartCoroutine(yourMethod());
}
IEnumerator yourMethod()
{
while(true){
// do something every 4 seconds
yield return new WaitForSeconds(4);
}
}
important
every method that you create with IEnumerator must to be called inside the Coroutine();
yield return new WaitForSeconds(4) put this method to wait for 4 seconds.

Related

How do I flip the gameobject at every Dotween loop?

transform
.DOPath(path, animDuration, pathType, pathMode, 10).SetLoops(-1, LoopType.Yoyo)
.SetEase(ease);
This is my simple dotween code to follow path. After every yoyo I want my object to flip or change direction towards its next path waypoint. Is there any dotween way of doing this?
DoTween has OnStepComplete().
DOTween:
Sets a callback that will be fired each time the tween completes a single loop cycle (meaning that, if you set your loops to 3, OnStepComplete will be called 3 times, contrary to OnComplete which will be called only once at the very end). More...
void Start()
{
transform
.DOPath(path, animDuration, pathType, pathMode, 10)
.SetLoops(-1, LoopType.Yoyo)
.SetEase(ease).OnStepComplete(FlipScpite);
}
private void FlipScpite()
{
_spriteRenderer.flipX = !_spriteRenderer.flipX;
}

UNITY | Update or InvokeRepeating?

I use many timers in my Unity project, they done like this:
void Update()
{
timer -= Time.deltaTime;
if(timer < 0)
{
DoSomething();
}
}
And in every google link they looks like this.
But today i found (im newbie) InvokeRepeating(); method.
So here is updated timer
int timer = 60;
void Start()
{
InvokeRepeating("Timer", 1f, 1f);
}
void Timer()
{
timer -= 1;
}
So why people change timers in Update()?
And which method less inpact on performance?
Depends!
As usual in programming there are most of the time multiple valid solutions for a problem.
In my eyes the bigest difference is that InvokeRepeating is also working on inactive GameObjects or disabled Components while Update is only called while the object is active and the component enabled.
Note, however, that your current examples do different things. To make them equivalent it should look like either
void Start()
{
timer = 1f;
}
void Update()
{
timer -= Time.deltaTime;
if(timer < 0)
{
timer = 1f;
DoSomething();
}
}
or
void Start()
{
InvokeRepeating(nameof(DoSomething), 1f, 1f);
}
Btw: A third basically equivalent solution would be a Coroutine (which is basically a temporary Update method - in fact the MoveNext call gets executed right after the Update would)
// Yes, Start can be an IEnumertaor and is in this case internally implicitly started as Coroutine!
IEnumerator Start()
{
while(true)
{
yield return new WaitForSeconds(1f);
DoSeomthing();
}
}
As mentioned by Kuruchy: There is also a difference in behavior related to the timeScale.
Update: since it uses Time.deltaTime to decrease the timer it will be affected by the time scale
→ in order to avoid this you would need to use Time.unscaledDeltaTime instead. But afaik still if setting Time.timeScale = 0; then Update isn't called at all.
Coroutine: Similar to update the WaitForSeconds is also timeScale dependent.
→ in roder to avoid this you would need to use WaitForSecondsRealitme but afaik even then setting Time.timeScale = 0; would lead to the routine not getting called at all.
InvokeRepeating: Fromt he docs I can only see that
This does not work if you set the time scale to 0.
not sure how it reacts to the timescale though but I would actually guess the same. Though, here there is no real work around like for the other two.
Performance wise you most probably don't even have to care! I guess it would be over-optimizing.
However my guess would be that Update is actually slightly faster since there you already know the method reference while when using InvokeRepeating you are passing it as a string which is additionally error prone and means that internally Unity has to find that method first.
Without going into too much detail is because of the performance.
The Update() method is invoked internally by Unity and they've done a pretty good job in optimizing it.
InvokeRepeating is much slower in comparison. First of all because the initial method invocation is using the Reflection to find the method you want to start and it's respective calls also take more time than Update. And you want to avoid using Reflection in your code as much as possible.
Here is nice, short article in which the tests were performed between these two methods - http://www.kittehface.com/2017/09/unity-performance-with-invokerepeating.html

yield return new WaitForSeconds not working

I have 2 instances of this IEnumerator on 2 scripts. Both are private, but one is working, the other isn't.
This is the first one that is working:
private IEnumerator EndGame()
{
yield return new WaitForSeconds(3);
SceneManager.LoadScene("Menu", LoadSceneMode.Single);
}
This is the second one that isn't working:
private IEnumerator EndGame()
{
yield return new WaitForSeconds(3);
SceneManager.LoadScene("Menu", LoadSceneMode.Single);
}
They're exactly the same. I can call the IEnumerator (proven by a Debug.Log), but in one case it waits for 3 seconds, and in the other one it stops at the return statement and doesn't continue. I also tried renaming the Coroutine that wasn't working and making them both private just in case you can't have Coroutines with the same name, but that also didn't work. My time scale is constantly remaining at 1 and the object that I called the Coroutine from doesn't get destroyed.
One weird thing that does happen is the object that I call the Coroutine from does get destroyed, but after the 3 seconds is up (The highlighted player is the one calling the Coroutine, and the same thing happens on both players):

Trying to program a timer to do something when it reaches 5 seconds

I can't seem to figure out what to do here. I'm creating a learn to type game where if the user doesn't get the word correct in 5 seconds, they lose a life.
Either this could be implemented by counting down to 0 from 5, or counting up to 5.
I tried using the stopwatch for c# system diagnostics, which works for everything except I can't figure out how to check when it hits 5 seconds. It is a time object you cant compare it to an int.
you have two options here.
You can check the time in the Update function with Time.time or Time.deltaTime, or you can use a Coroutine with the new WaitForSeconds(5) object.
It could be as simple as:
float time;
void Update()
{
time += Time.deltaTime;
if(time > 5)
{
LoseALife();
}
}
If you need to restart the timer each time you complete a word you might have an aditional method like:
public void RestartTimer()
{
time = 0;
}
This would make the timer go back to 0 any moment you need it.

Time Delay for a process in Unity 3D

I have to give the delay for the process to happen, which I am calling in the Update function.
I have tried CoUpdate workaround also. Here is my code:-
function Start()
{
StartCoroutine("CoStart");
}
function CoStart() : IEnumerator
{
while(true)
{
yield CoUpdate();
}
}
function CoUpdate()
{
//I have placed the code of the Update().
//And called the wait function wherever needed.
}
function wait()
{
checkOnce=1; //Whenever the character is moved.
yield WaitForSeconds(2); //Delay of 2 seconds.
}
I have to move an object when a third person controller(which is another object) moves out of a boundary. I have included "yield" in my code. But, the problem happening is: The object which was moving when I gave the code for in the Update(), is moving, but isn't stopping. And it is moving up and down. I don't know what is happening! Can someone help? Please, thanks.
I am not entirely clear what you are trying to accomplish, but I can show you how to set up a Time Delay for a coroutine. For this example lets work with a simple cool down, much like you set up in your example. Assuming you want to continuously do something every 2 seconds while your game is running a slight modification can be made to your code.
function Start()
{
StartCoroutine(CoStart);
}
function CoStart() : IEnumerator
{
while(true)
{
//.. place your logic here
// function will sleep for two seconds before starting this loop again
yield WaitForSeconds(2);
}
}
You can also calculate a wait time using some other logic
function Start()
{
StartCoroutine(CoStart);
}
function CoStart() : IEnumerator
{
while(true)
{
//.. place your logic here
// function will sleep for two seconds before starting this loop again
yield WaitForSeconds(CalculateWait());
}
}
function CalculateWait() : float
{
// use some logic here to determine the amount of time to wait for the
// next CoStart cycle to start
return someFloat;
}
If I have missed the mark entirely then please update the question with a more detail about what you are attempting to accomplish.
I am not 100% sure that I understand you question but if you want to start one object to move when the other is out of bound then just make a reference in the first object to the second object and when the first object is out of bounds (check for this in Update of the first object) call some public function StartMove on the second object.
I wouldn't suggest CoRoutines. It can sometimes crash your computer. Just define a variable and decrement it. Example:
private float seconds = 5;
then do anywhere you want to delay:
seconds -= 1 * Time.deltaTime;
if(seconds <= 0) {your code to run}
This will make a delay of 5 seconds. You can change 5 to any value to change the number of seconds. Also you can speed up the decrement by changing the value of 1. (This is mostly useful when you want to sync 2 delayed actions, by using the same variable)
Hope this helps. Happy coding :)