- Home /
Really strange behaviour on really simple script (Creating Ticking System)
I'm creating a ticks system for unity, and I'm breaking my head with something super weird in a super simple code.
1 - What do I want? Create a system that calls updates on other systems defined by a number of updates per second, even if it can cause lag in case the number of updates per second is very large.
2 - Based on this I created 2 scripts (Tickator.cs and Tickated.cs), in which the Tickator will be responsible for calculating how many ticks have passed to update the systems that are tickable.
//Tickator.cs
using UnityEngine;
[DefaultExecutionOrder(0)]
public class Tickator : MonoBehaviour
{
[Range(0, 240)] public uint TicksPerSecond;
public int TotalTicks;
public Tickated TickatedClass;
private float _t;
private void Update()
{
_t += Time.deltaTime * TicksPerSecond;
int elapsedTicks = (int) _t;
if (elapsedTicks > 0)
{
for (int i = 0; i < elapsedTicks; i++)
{
DoTick();
}
_t %= 1;
}
}
private void LateUpdate()
{
if (TotalTicks != TickatedClass.Ticks)
{
Debug.LogError("count of ticks on Tickator is different from count of ticks in Tickated!");
Debug.Break();
}
}
private void DoTick()
{
TotalTicks++;
TickatedClass.Tick();
}
}
//Tickated.cs
using UnityEngine;
public class Tickated : MonoBehaviour
{
public int Ticks;
public void Tick()
{
Ticks++;
}
}
3 - I added 2 debug variables one in each script to have control of how many ticks were ticked. And a Debug.Break () that will pause the editor and throw an error when the ticks between Tickator and Tickated are different (they should never be).
4 - I put both in a gameobject and assign TIckated to the field TickatedClass
5 - If I hit play everything works perfectly, the amount of ticks between ticker and ticked never changes (perfect).
6 - While in play mode, if I hit pause, then change the value of TicksPerSecond and return to play, the amount of ticks between tickator and tickated never changes (also perfect).
7 - But if I change this value while in playmode soon the amount of ticks between tickator and tickated changes (Whyyy)!
8 - What is more strange is, I created a class that changed the TicksPerSecond value of the Tickator that I called Setter.cs, when I change the value through it, updating the TicksPerSecond value of the Tickator through the MonoBehaviour Update event, the error does not occur. The same happens if I change the value through the game by Sliders or InputFields.
//Setter.cs
using UnityEngine;
[DefaultExecutionOrder(-1000)]
public class Setter : MonoBehaviour
{
[Range(0, 240)] public uint Value;
public Tickator m_Tickator;
private void Update()
{
m_Tickator.TicksPerSecond = Value;
}
}
9 - I also tried changing the order of execution between Tickator.cs and Setter.cs using DefaultExecutionOrder, to see if the same error happened, but it did not happen ...
Git Repository or Unity Package Zip
Can someone help me understand what's going on? Thanks in advance,
I don't think I'm understanding what you're trying to do. It sounds like what you're trying to make is a delegate event that gets called by a timer.
I'm trying to make a system that updates other systems, in which I can set the amount of updates per second.
i see you are using delta time in your script... this is a time mesurement. when you make your cast from float to int after using deltatime you totally kill the accuracy. delta time is typically a number from zero to one and when you cast it it will round down to the nearest whole number.
so anyways if you say you are only using your tick system to be in scync with ever changing frames per second than you should be using all whole numbers or ints in update.
if you are concerned about timers relating to accurate time then you should be using delta time or some other timed c# carotene.
you cant mix both. thats why everyone is asking what and why you are doing what you are doing. most times in game development it is standard to use time ins$$anonymous$$d of FPS for triggers because FPS changes depending on the device. using frames is just as possible but we are asking what you are doing because we are not sure what you are doing is the right apporoach. one way or another your code looks very long just to be organizing different triggers
Answer by hameed-ullah-jan · Apr 02, 2019 at 05:57 AM
Update function works with Frames/Seconds, if you want a time controlled kind of update function, you can simply use fixed update and you can control that time from the Fixed timesteps (Edit->Project settings->Time), by default fixed update is called every 0.02 seconds, you can change this value.
Answer by toddisarockstar · Apr 02, 2019 at 06:05 AM
public int[] frameCounters;
public int[] counts;
void Start () {
frameCounters = new int[] {204,824,2456,10000,10202};
counts = new int[frameCounters.Length];
}
// Update is called once per frame
// Change to FixedUpdate for time counting
void Update () {
int i = counts.Length;
while(i>0){i--;
counts[i]++;
if(counts[i]>=frameCounters[i]){
print("counter number:"+ i+ " has reached:"+counts[i]+" frames");
counts[i]=0;
} }}
Answer by Gustavo-Santos · Apr 02, 2019 at 09:57 AM
The thing is, how is it possible that the count of ticks in the Tickator could be different from the count of ticks in Tickated? Because both are iterated in the same method...