A dumb SetTimer() question.

Discussions about Coding and Scripting
Post Reply
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

A dumb SetTimer() question.

Post by MrLoathsome »

Situation: Have the timer skipping some processing under certain conditions. Want the timer to skip multiple times as fast as
possible if those conditions are are true each time.

Have it all working fine, but have 1 issue.

I cannot find anywhere, after multiple searches, any specific info stating what the minimum valid value for inRate is.
(Find nothing but lots of info telling me everything I already know about the function, except min. valid Timer value....)

Want to set this as low as is safe.

Currently using this:

Code: Select all

SetTimer(0.01250, True);
That is just based on my best guess of what will work without issues.

Anybody know a number?
blarg
User avatar
Barbie
Godlike
Posts: 2807
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: A dumb SetTimer() question.

Post by Barbie »

Anybody know a number?
Not me without having a look at the engines' source code, but a guess: the minimum value is the delta time between two ticks and therefore depends on hardware speed. Why don't you use the Tick() function for it?
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
Higor
Godlike
Posts: 1866
Joined: Sun Mar 04, 2012 6:47 pm

Re: A dumb SetTimer() question.

Post by Higor »

Make out whatever you want from it, from my point of view it looks like a timer that doesn't care about tickrate.
But any rate less or equal to 0 will mean no timer.

Code: Select all

void AActor::execSetTimer( FFrame& Stack, RESULT_DECL )
{
	P_GET_FLOAT(NewTimerRate);
	P_GET_UBOOL(bLoop);
	P_FINISH;

	TimerCounter = 0.0;
	TimerRate = NewTimerRate;
	bTimerLoop = bLoop;
}
Meanwhile...
Animation is processed, then script Tick, then State, then Timer, then Physics.

Code: Select all

		// Update the actor's script state code.
		ProcessState( DeltaSeconds );

		// Update timers.
		if( TimerRate>0.0 && (TimerCounter+=DeltaSeconds)>=TimerRate )
		{
			// Normalize the timer count.
			INT TimerTicksPassed = 1;
			if( TimerRate > 0.0 )
			{
				TimerTicksPassed     = (int)(TimerCounter/TimerRate);
				TimerCounter -= TimerRate * TimerTicksPassed;
				if( TimerTicksPassed && !bTimerLoop )
				{
					// Only want a one-shot timer message.
					TimerTicksPassed = 1;
					TimerRate = 0.0;
				}
			}

			// Call timer routine with count of timer events that have passed.
			eventTimer();
		}
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: A dumb SetTimer() question.

Post by MrLoathsome »

@ Barbie:

In this particular case, there is no reason to mess with tick() at all.

I try to avoid that if possible for anything if not needed, just for performance, but will of course do things in tick if it is appropriate.
This is not for a weapon/monster/effect or other pawn of that nature however....

@Higor.

I do indeed know how to toggle the Timer on/off just by setting the rate to 0.
(And obviously I won't argue with you regarding it being independent from Tick(), since you are correct. :tongue: )

My question is, how close to 0 can I set it before I am likely to run into problems?


*It is doing NOTHING but 2 or 3 "If" checks in this case. If the timer actually needs to start doing anything, it sets the
rate higher. That is all working fine.

I could run some tests for a bit to try and find out, or just leave it at my current best guess setting, which seems to be working fine so far.
Just a bit surprised I couldn't find this detail out anywhere. (Maybe my search queries are all borked......)
blarg
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: A dumb SetTimer() question.

Post by Wormbo »

Generally, if you use Timer with "as low interval as possible" instead of Tick, you are using a slightly more expensive event to do something you should probably be doing in Tick directly.

There's absolutely nothing wrong with using Tick, if you know what you're doing. Timer really only is advantageous if you want intervals significantly larger than the average expected frame/tick rate. If you want your timer to only do something with intervals, then do the enabling checks in Tick until you know it should be active.
User avatar
sektor2111
Godlike
Posts: 6411
Joined: Sun May 09, 2010 6:15 pm
Location: On the roof.

Re: A dumb SetTimer() question.

Post by sektor2111 »

I intend to replace Timer() with Sleep+State last time... :|
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: A dumb SetTimer() question.

Post by MrLoathsome »

This particular timer is processing an array of items. One item each pass thru.

In some cases, more processing is needed, in other cases none, and we would like to skip to the next
"active" item as fast as possible. Repeating until an array item is found that that does need processing.

This specific adjustment to the Timer rate is only to bypass "non-active" items in this array as fast as possible.
It switches to a user configurable Timer rate soon as an item is encountered that needs processing.

None of this processing happens at anywhere near the FPS/tick rate. (Usually...)
It is trying to have as little impact as possible.

**And as mentioned above, my best guess value is working great with the tests I have ran so far, but would like to
optimize this bit as much as possible.
blarg
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: A dumb SetTimer() question.

Post by Wormbo »

How about something roughly like this:

Code: Select all

var float ProcessingDelay;
var int CurrentItem;
var Stuff TheArray[SIZE];

function Tick(float DeltaTime)
{
    ProcessingDelay -= DeltaTime;
    if (ProcessingDelay > 0)
        return;

    while (CurrentItem < SIZE && !NeedsProcessing(TheArray[CurrentItem]))
        CurrentItem++;

    if (CurrentItem < SIZE)
        Process(TheArray[CurrentItem]);

    ProcessingDelay += ProcessingInterval;
}
But generally, there's no "safe" lower value. You can essentially reduce it to any value > 0 and only ever get at most a single Timer event per tick. Timer is called from native Tick whenever the native equivalent of my ProcessingDelay variable drops below zero. It may not necessarily raise above zero again if your interval is small enough, but that doesn't matter. Whenever you set a new interval, it forgets about any left-over invocations of the Timer event.
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: A dumb SetTimer() question.

Post by MrLoathsome »

Thanks for the excellent explanation there Wormbo.

That both confirms what I was thinking, and explains why I could not find an
actual Min valid value for that rate anywhere.

For this particular project I think my current timer tweaks are going to work just fine.
But I will sure reference your example there if I need to do something similar in a tick() at some point.

:tu:
blarg
User avatar
Barbie
Godlike
Posts: 2807
Joined: Fri Sep 25, 2015 9:01 pm
Location: moved without proper hashing

Re: A dumb SetTimer() question.

Post by Barbie »

As we are just talking about these "interrupt" functions Timer() and Tick(): are they "singular" in a way or has the coder make sure that the function is not called again while it is executing? Of course I can try it out but maybe someone just knows it.
"Multiple exclamation marks," he went on, shaking his head, "are a sure sign of a diseased mind." --Terry Pratchett
MrLoathsome
Inhuman
Posts: 958
Joined: Wed Mar 31, 2010 9:02 pm
Personal rank: I am quite rank.
Location: MrLoathsome fell out of the world!

Re: A dumb SetTimer() question.

Post by MrLoathsome »

As far as I am aware neither of these functions will get called before the current run thru it is finished executing.

Calling SetTimer() inside timer just sets the rate for the next time Timer() is executed.

Wormbo's example there for Tick() would let you sort of simulate a timer/delay within your Tick() function.


If I am incorrect on this, I look forward to an excellent and informative explanation as far as what is right. 8)
blarg
User avatar
Wormbo
Adept
Posts: 258
Joined: Sat Aug 24, 2013 6:04 pm
Contact:

Re: A dumb SetTimer() question.

Post by Wormbo »

UnrealScript is strictly single-threaded. Timer and Tick both are sequentially called from the actor's native Tick (UScript Tick before state code, UScript Timer after state code) and they both always are called when no other UnrealScript functions are on the call stack.
On a more global scale, the engine goes through its internal actor list and calls native AActor::Tick on each of them in turn.
Post Reply