Add NumberSequence:ValueAtPoint(Point, Pattern)

With the release of Attributes, NumberSequences are now able to be used for multiple different purposes. They are exceptionally useful for creating non-identical numeric loops, using the envelope property.

However, using this value type is equally as irritating. If I need to determine my point-to-value along the sequence, I either need to;

  1. create + store pre-calculated keypoints using the envelope, figure out if I’m exceeding the length of the range + loop around to a new set of keypoints.
  2. set a randomseed for the NumberSequence to use to maintain a linear path between points w/ envelopes.

1 is pretty straightforward, but is irritating when multiple scripts need access to this function. I can create a module that holds this, but I also worry about the amount of calculation
2 is a nightmare that I wouldn’t recommend. Altering the randomseed + doing all the pre-calculations again per call. Gross.

For the moment, this is the code I need to use in order to solve a point on a numbersequence.
function RunThroughNumberSequence(SequenceData)
       local Delta, Duration, Sequence = SequenceData.Delta, SequenceData.Duration, SequenceData.Sequence
   
 if Delta > Duration or #SequenceData.Points == 0 then
        table.clear(SequenceData.Points)
        for n, Keypoint in pairs(Sequence.Keypoints) do  
SequenceData.Points[n] = {Keypoint.Time, Keypoint.Value + math.random(-Keypoint.Envelope, Keypoint.Envelope)}
        end
        Delta = Duration - Delta
        Sequence.Delta = Delta
    end

    local Position = Delta/Duration
    for n, x in pairs(SequenceData.Points) do
        if x[1] <= Delta then
            local nextpoint = SequenceData.Points[n+1]
            if nextpoint and nextpoint[1] >= Delta then
                return nextpoint[2] * (Position - x[1]) / (nextpoint[1] - x[1]) + x[2]
            end
        elseif x[1] >= Delta and n == 1 then --Less than first point (Do we ever really hit this?)
            return x[2]

        elseif x[1] <= Delta and n == #SequenceData.Points then --We should have looped... what happened?                
return x[2]
        end
    end
end

It would be ideal if this could instead be called + solved externally, by using something like

NumberSequence:ValueAtPoint(Point, Pattern)

  • Point being the position between 0-1 we are searching for
  • Pattern being a numeric value we use in order to grab our value with envelopes. Using the same pattern will always return the same value-at-point. (This is essentially passing over the randomseed needed.)

What does this achieve?

  • Cuts down on the amount of data we need to store in order to work with this value type
  • No need to create + store data in order to use, just call it with a point and returns a value.
  • Function is already housed, no need to add this code in.
  • Adds some usability to the attribute value.

If this does prove to be useful, expanding it so that ColorSequence also has a similair function call would be amazing too.

29 Likes

Definitely something I would use, however I’m not a fan of this API. My preference would be for the value and envelope at a given time point to be returned rather than this API handling random number generation for me.

local value, envelope = sequence:ValueAtPoint(point)

Then I can calculate a random value by doing:

local x = value + envelope * (2 * rng - 1)
12 Likes

I don’t see any difference in what you’re doing here with whats initially given, you’re still storing an rng value. Depending on how it’s being created though, you’re still risking variation between points.

Edit:


ValueAtPoint(point)
If rng changes between “steps” along the sequence;

This is a great request. It is not trivial to implement correct usage of NumberSequences, as you can see by OP’s code. Having a proper & consistent implementation is critical so that we can distribute systems that rely on NumberSequences for others to use.

11 Likes

I don’t want some magic API to strongarm how I generate randomness over the envelope. Perhaps I’m encoding data differently and envelope means something different in my code from a random modifier for the value. You can just as easily persist random state from an initial seed by using Random.new, so passing a seed is completely unnecessary. Calculations can be cached but I’m very sure iterating random over ~6-10 points in a sequence won’t hurt your performance.

I would much prefer an API to return the value and envelope than a rigid single-usecase API that requires a randomseed and returns random numbers.


I’ve wanted this before for ColorSequences to facilitate color sliders in customization UI. Some API alike GetAtTime should be provided for both sequence types.

12 Likes

I would find this feature very useful as the current alternative approach to doing this manually isn’t as conventional as I think it should be.

:+1:

it is an inconvinience to say the least to manually write a function that wil output value at a specific point.
might later write lua functions that allow you to do so.
but yeah im definitely supporting this, there should be this method in numbersequence and color3sequence classes. it just makes it easier overall to get the value at points you wanna take care of.
i assume its not added because there is not actually much demand for it’s use case. but i dunno what roblox engineers prioritize so…

The problem here is the envelope. For a linear sequence, this is fine. But how do you handle keypoints with envelopes?

The only thing I can think of is the developer having to use a callback that defines the min and max of the envelope at that value in the sequence. As caszm mentioned a few years ago, its not as easy as giving to an RNG because not all usecases of envelopes are for a random value range.

also colorsequences should have this because enevlope isn’t a thing on them

Yeah, it blows my mind that there isn’t a less tedious method out there. I’m definitely willing to vouch for the OP’s solution!