Yield 2.0 [An alternative to wait]

Edit*

Yield 2.0 is only useful if you intend to connect a function to an event that constantly fires, if you’re looking for a simple wait() alternative, I recommend this module https://www.roblox.com/library/5123343290/simple-wait, it’s composed of 11 lines and, to replace wait, just do

local wait = require(location to module)
Why I made Yield 2.0

A short while ago, I came across a post by Kampfkarren advising against the use of wait() when possible. I was also experimenting with wait() and experienced some problems when wait() was used often, it would throttle when called multiple times and would yield seconds instead of a few hundred milliseconds so, I thought it would be a nice idea to make a custom implementation of wait through the use of bindable events instead.

How Yield 2.0 works
Overview

When a Yield 2.0 object is created, a loop will be initialised unless the object is part of a pool (a pool is essentially a loop that runs within a coroutine and, fires individual events when the difference in time is greater than or equal to the target wait time of an individual object). You may want to use a pool to reduce the number active coroutines resulting in unpleasant consequences such as lag. If an object is polymorphic, you can change the target wait time.

How to use yield 2.0

Once you’ve required the module, you’ll need to call the function

Yield.new(Time, Polymorphic, Key, PoolKey)
Returns Event [RBXScriptSignal], Object [Table], Key [String]

Arguments/Parameters

Time is measured in seconds.

Polymorphic (Optional) is a boolean and, if set to true, will allow you to change the yield time.

Key (Optional) This can be (almost) any value if you don’t intend on using a pool; if you do, it’s recommended you use a string since, due to the nature of bindable events, any arguments/parameters passed through are serialised.

PoolKey (Optional) is the pool your object is going to “use”.

Returned

An event will be returned which will be fired when delta time is greater than or equal to the variable Time. (delta is commonly used to refer to change in)

An object will be returned which is pretty useful if you want to change the variable Time.

A key will be returned whether you passed one through or didn’t pass one through, if a key isn’t passed through, one will be created.

Using the returned event

Now that we’ve got our event, we can simple do

 Event:Wait() 

Changing the yield time of our event

If you want to change the yield time of your event, you can call the method

Object:ChangeYieldTime(Time)

The variable Object is returned when we first create our object using Yield.Create()
Note: The variable Polymorphic will have to be set to true.

Creating a pool

Each time you create an object, a coroutine is created assuming you’re not using a pool, if you’re going to be using multiple events, it’s recommended that you use a pool instead to reduce lag due to lots of running coroutines. A pool (in this case) is essentially a single loop/coroutine that fires individual events based off the time that has surpassed for each individual object.

To create a pool, you can call the function

Yield.CreatePool(PoolKey)
Returns Key [Userdata]

A pool key isn’t required, if one isn’t passed through, one will be created and returned.

Now that we’ve created a pool, we can pass it through the function Yield.Create() when we create an object as the fourth argument/parameter.

Removing an object

If you don’t want to use an event/object anymore, you can call the function

Yield.Remove(Key) 

The variable Key is the key associated with our event/object.

Removing a pool

If you’ve created a pool but, you no longer need it, you can call the function

Yield.RemovePool(PoolKey)
Other functions
Return an object
Yield.ReturnObject(Key)
Return an event
Yield.ReturnEvent()

Example 1

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Yield = require(ReplicatedStorage :WaitForChild("Yield"))
local Event = Yield.New(0.1)

while true do -- Alternatively, you could connect a function to the event
    ...
    Event:Wait()
end

Example 2

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Yield = require(ReplicatedStorage :WaitForChild("Yield"))
local Pool = Yield.CreatePool()
local Event, Object, Key = Yield.New(0.1, true, nil, Pool)

Event:Connect(function(Delta) -- Delta (difference in time) is passed as an argument/paramter
    ...
end)

Object:ChangeYieldTime(0.2)
Yield.Remove(Key)
Yield.RemovePool(Pool)

Event = nil
Object = nil
Key = nil
...

https://www.roblox.com/library/5113996128/Yield-2-0

Notes:
The module uses the event RunService.Heartbeat.
Delta time is passed through as an argument/parameter when an event is fired.

16 Likes

Why do you need to put the events in an Events folder? Why not just store them in memory (which you’re already doing)

FWIW You should probably add some more comments that explain what parts of the code are doing (the source is a bit messy), and you may want to consider using a styleguide since there’s a few inconsistencies with your coding style.

2 Likes

Thanks for the feedback, I’ll make sure to rewrite it so it’s more consistent and will comment it when possible, I’m currently taking a break from Roblox hence the late reply.

2 Likes