Corona Timer and memory issue - lua

Say I am using timer in my game for example
timer.performWithDelay(1000, function() end, 1)
Is it necessary that I should assign this to an local variable and cancel after its use i.e,
local timerVar = timer.performWithDelay(1000, function() end, 1)
timer.cancel(timerVar)
timerVar = nil
Help me with this .....

If you don't expect the timer to be cancelled, you don't have to store it's reference. But I also recommend to not use anonymous function in timer. It's harder to debug then, because you'll not know the name of a function if it's throw an error.

the cancel() method is for stopping and removing the timer before it finishes. There's no need to call it after the timer is done.

i think you try this below.
local timerVar = timer.performWithDelay(1000, function(e)
timer.cancel(e.source)
e.source = nil
end, 1)

Related

How to detect when an animation has ended roblox?

I have a script designed to make an npc in my game do the default roblox idle animation but once Animation2 starts, it doesn't end, how can I fix this?
local idle1 = script.idle.Animation1
local idle2 = script.idle.Animation2
local animator = script.Parent.Humanoid.Animator
local LoadedIdle1 = animator:LoadAnimation(idle1)
local LoadedIdle2 = animator:LoadAnimation(idle2)
local function PlayAnimation()
local roll
local animation
roll = math.random(1, 10)
if roll == 1 then
animation = LoadedIdle2
LoadedIdle2:Play()
else
animation = LoadedIdle1
LoadedIdle1:Play()
end
animation.KeyframeReached:Connect(PlayAnimation)
end
PlayAnimation()
I tried adding animation.Ended:Connect(PlayAnimation) but that didn't fix it.
According to the documentation, there are a few events that an AnimationTrack will fire at different times.
KeyframeReached, which fires every time playback of an AnimationTrack reaches a Keyframe that does not have the default name - "Keyframe."
Stopped, which fires whenever the AnimationTrack finishes playing.
Ended, which fires when the AnimationTrack is completely done moving anything in the world. The animation has finished playing, the "fade out" is finished, and the subject is in a neutral pose.
DidLoop, which fires whenever a looped AnimationTrack completes a loop, on the next update.
It sounds like you want the Stopped event.
local function PlayAnimation()
local roll = math.random(1, 10)
local animation = if roll == 1 then LoadedIdle2 else LoadedIdle1
animation:Play()
animation.Stopped:Wait()
PlayAnimation()
end

Click detector event is not functioning

I have made this code; what I want is so when the part is clicked, it does the function fadeWaitShow, but it does not seem to be working. I tried putting it in a loop but it would just do the function again and again by itself. Help, if you can and thanks! (Code is below)
local click = script.Parent.ClickDetector
local function fade()
script.Parent.CanCollide = false
script.Parent.Transparency = 0.5
end
local function show()
script.Parent.CanCollide = true
script.Parent.Transparency = 0
end
local function fadeWaitShow ()
fade()
wait(1)
show()
end
click.MouseClick:Connect(fadeWaitShow())
Thanks!
In your MouseClick connection, you are calling the function instead of passing the function handle to the connection. This results in the code evaluating the line as click.MouseClick:Connect().
So to fix this, don't call the function.
click.MouseClick:Connect(fadeWaitShow)

Trigger timer callback

I have a stateful DoFn where I batch elements for a while and then use a timer to trigger a batch flush. Something like:
class BatchToPubSub(DoFn):
HEAP_STATE_SPEC = ReadModifyWriteStateSpec("events_heap", CDCEventHeapCoder())
TIMER = TimerSpec("timer", TimeDomain.WATERMARK)
BATCH_SIZE = 512
def process(
self,
element,
events_heap_state=DoFn.StateParam(HEAP_STATE_SPEC),
timer=DoFn.TimerParam(TIMER),
t=DoFn.TimestampParam,
):
_, event = element
events_heap = events_heap_state.read() or CDCEventHeap()
events_heap.push(event)
self.incoming_count.inc()
events_heap_state.write(events_heap)
if len(events_heap) >= self.BATCH_SIZE:
timer.set(time.time()) # here I want to force timer callback
# self.expire(...) manual call to callback
else:
timer.set(t + Duration(seconds=ALLOWED_LATENESS))
What is the best approach to trigger the callback by setting the timer? I've noticed that if set the timer to the current timestamp, the callback never gets triggered.
The other way of doing this is to manually call the callback and I'm fine with this, but I am thinking if it's better to make the timer trigger it?
Update add code for timer spec and state spec.

Lua Roblox API: How can I debounce a player/character that runs into a box

Background:
Bear minimal objects. Just a player and a part (rectangular prism) that's floating in the air and anchored.
I honestly don't understand what is happening under the hood so its hard to figure out. Without debounce, upon event firing, the callback function is invoked by connect() or the event handler (not sure), and, without debouncing, the function is invoked multiple times as print statements are repeated on the output box. So, with a variable (of type boolean) that stores a debounce flag, that solves it. I then try to "un-debounce" when the player's model is outside out of the box's model. But, I don't know how to do that properly.
Here's my code attempt:
local box = game.Workspace.BoxModel;
local debounce = false;
local function onTouchedDebounced()
if (debounce == false)
then
debounce = true;
print("Hello! onTouchedDebounced() has run.");
box.Touched:Connect(onTouchedDebounced));
end
end
local function onTouchedUndebounced()
if (debounce == true)
then
print("Hello! onTouchedUndebounced() has run.");
debounce = false;
end
end
box.Touched:Connect(onTouchedDebounced);
box.TouchEnded:Connect(onTouchedUndebounced);
The heart of what you're doing is sound : start blocking after the first event, and unblock some time later. If this were with button presses or mouse-clicks, your solution would work fine. This is complicated by the Touched event, as it fires with any part that touches it, and a player's character could have multiple touch points.
The Touched and TouchEndeded events give you a reference to the instance that has touched the part.
If the goal is to only fire the box event once per player or once while anyone is touching it, you can keep a dictionary of parts that are currently touching the box. When a part touches, you increment a counter. When a part stops, you decrement it. You only remove the debounced flag once all touch points have been removed.
local box = game.Workspace.BoxModel
local playersTouching = {} --<string playerName, int totalParts>
local function onTouchedDebounced(otherPart)
-- check that the thing that touched is a player
local playerModel = otherPart.Parent
if not playerModel:IsA("Model") then
warn(otherPart.Name .. " isn't a child of a character. Exiting")
return
end
-- check whether this player is already touching the box
local playerName = playerModel.Name
local total = playersTouching[playerName]
if total and total > 0 then
warn(playerName .. " is already touching the box")
playersTouching[playerName] = total + 1
return
end
-- handle a new player touching the box
playersTouching[playerName] = 1
-- Do a thing here that you only want to happen once per event...
print(string.format("Hello! onTouchedDebounced() has ran with %s and %s", playerName, otherPart.Name))
end
local function onTouchedUndebounced(otherPart)
-- decrement the counter for this player
local playerName = otherPart.Parent.Name
if playersTouching[playerName] == nil then
return
end
local newTotal = playersTouching[playerName] - 1
playersTouching[playerName] = newTotal
-- if the total is back down to zero, clear the debounce flag
if newTotal == 0 then
playersTouching[playerName] = nil
print(string.format("Hello! onTouchedUndebounced() has ran and %s has no more touching parts", playerName))
end
end
box.Touched:Connect(onTouchedDebounced)
box.TouchEnded:Connect(onTouchedUndebounced)

Actionscript settimeout not working

The Timer always jumps right into the function instead of waiting 2000 milliseconds
stop();
var hey:Number= 2000;
function exercise(frame) {
trace("sup");
this.gotoAndStop(frame);
}
setTimeout(exercise(2),hey);
trace(hey);
The setTimeout function (ie. not a Timer) takes the following parameters:
public function setTimeout(closure:Function, delay:Number, ... arguments):uint
Try:
// Save the return value so you can clear it later, otherwise your app for leak memory
var myTimeOut:uint = setTimeout(exercise, hey, 2);
trace(hey);
// the timeout closure object will not be garage collected if you do not clear it
clearTimeout(myTimeOut);
If you are doing this over and over, consider creating a Timer and setting/reseting the repeat count to 1 and then you can just restart the timer when need.

Resources