I’m here wondering how I would go about making a 1d/number spring, because the tutorials explaining it don’t put it into a context I can understand.
I kinda understand how you would go about making the spring, create a table with the damping (and some other variables than control spring behaviour), with a current point and a target point.
Then every frame some sort of math is done which causes it create a spring effect.
Lets say spring.c
is the current value, and spring.t
is the target value, and you set spring.c
to 1
and set spring.t
to 0
, you would expect a spring like behaviour such as;
however, lets say the spring.t
value is not always going to be 0
, and may be updated randomly, it might be a bit harder to do.
I came up with some test code, but i’m not exactly sure how you may go about implementing the actual spring math.
I’m hoping with basic understanding of how to do it 1 dimension (numbers) I may be able to replicate this to the second, or third dimension with angles included.
My test code:
local function create(c, d, r, k)
--probably not everything here is correct, just did what i thought the code may look like
local s = {}
--pretty sure theres three variables that control the spring behaviour
s.d = d
s.r = r
s.k = k
--set current, target, (and velocity/accelleration i think???)
s.c = c
s.t = c
s.v = 0
s.update = function()
--do something to calculate the "c" value (where i need the help)
end
return s
end
--create the spring
local spring = create(10, 0.5, 0.5, 0.5)
--update the spring every frame
game:GetService("RunService").RenderStepped:Connect(function()
spring.update()
print(spring.s) --show the spring value each frame
end)
--test data, setting the springs target value
spring.t = 0
--let the first update occur
wait(5)
--100 "sample updates"
for i = 1, 100 do
spring.t = math.random(-50, 50) --setting the target value
wait(math.random(50, 500)/100) --anywhere between half a second to 5 seconds
end
Pretty sure the spring variables how much it tries to pull it towards the target (like pulling to it less means it would take more time for the number to reach the target, and how tight it is (whether the rebound goes large or small distance, and something else i can’t remember.
I just don’t understand the spring math to it and since the explanations to it (which seemed to be very in depth) didn’t put it into a context I understand (programming), its become a stopping point for my programming (which I need to do alot of catch up in the next 6 months to meet personal targets).
Thank you to anyone who can put this into a context I can understand.
EDIT :
I came up with an equation that would work in my case (I think)
y = (c-t) * cos(B * x) * (e^(A * x)) + t
As shown by desmos, this is the graph produced:
where t would change the c value would try and reach that value by doing what is shown in the graph.
As far from what I know, A is the amplitude, or extremity of the graph and B is how fast is oscillates after (frequency/hz)
Hope this helps figure out my problem
EDIT #2:
Figured out non-iterative spring. Would like to know how to do it iteratively though.
My code:
--defining the parts to move
local target = workspace.Target
local current = workspace.Current
--function to create the spring
local function create(c, A, B)
local s = {}
--A for amplitude, B for frequency
s.A = A
s.B = B
--c is the starting value, t is the target value, and s is the current value
s.c = c
s.t = c
s.s = c
--update the spring using time
s.update = function(x)
s.s = (s.c - s.t) * math.cos(s.B * x) * math.exp(-s.A * x) + s.t
end
return s
end
--creating the spring
local spring = create(0, 0.95, 8)
--setting the time
local d = 0
game:GetService("RunService").RenderStepped:Connect(function(s)
--adds all the frame times together
d = d + s
--update the spring
spring.update(d)
print(spring.s)
--update part positions to visualize the spring
target.Position = Vector3.new(spring.t, 0, 1.05)
current.Position = Vector3.new(spring.s, 0, 1.1)
end)
--wait before updating
wait(1)
--set time to 0 before updating (important)
d = 0
--set the starting value as the current value
spring.c = spring.s
--set the target value
spring.t = 2
wait(5)
d = 0
spring.c = spring.s
spring.t = 0