Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

Why are there discrepancies in the position of my elevator?

Asked by
Klamman 220 Moderation Voter
8 years ago

I have the following code:

f1.ClickDetector.MouseClick:connect(function()
if base.Position.Y > 0 then
    repeat  
    base.CFrame = base.CFrame - Vector3.new(0, .1, 0)
    f1.CFrame = f1.CFrame - Vector3.new(0, .1, 0)
    f2.CFrame = f2.CFrame - Vector3.new(0, .1, 0)
    f3.CFrame = f3.CFrame - Vector3.new(0, .1, 0)
    f4.CFrame = f4.CFrame - Vector3.new(0, .1, 0)
    wait(.1)
    until base.Position.Y <= 0
else end
end)

f2.ClickDetector.MouseClick:connect(function()
    if base.Position.Y > 10 then
    repeat  
    base.CFrame = base.CFrame - Vector3.new(0, .1, 0)
    f1.CFrame = f1.CFrame - Vector3.new(0, .1, 0)
    f2.CFrame = f2.CFrame - Vector3.new(0, .1, 0)
    f3.CFrame = f3.CFrame - Vector3.new(0, .1, 0)
    f4.CFrame = f4.CFrame - Vector3.new(0, .1, 0)
    wait()
    until base.Position.Y <= 10
    elseif base.Position.Y < 10 then
    repeat
    base.CFrame = base.CFrame + Vector3.new(0, .1, 0)
    f1.CFrame = f1.CFrame + Vector3.new(0, .1, 0)
    f2.CFrame = f2.CFrame + Vector3.new(0, .1, 0)
    f3.CFrame = f3.CFrame + Vector3.new(0, .1, 0)
    f4.CFrame = f4.CFrame + Vector3.new(0, .1, 0)
    print(base.Position.Y)
    wait()
    until base.Position.Y >= 10
    else end
end)

However, neither performs the operation I want with accuracy. Instead of simply .1, the code adds something like .100000000001789. Why is this? Can someone explain to me why this is happening, and a possible solution? Thanks.

1 answer

Log in to vote
3
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
8 years ago

CFrames and Vector3s are internally stored as "floats" -- 32-bit floating-point numbers.

This means you have about ~24 bits, which is about around 8 significant digits. 0.1 isn't exactly representable in binary (only numbers with powers of 2 as denominator are), so you get some error when you try to use 0.1 -- you'll get something like 0.10000000?????.... Using it more and more will cause a larger and larger error.

That said, you shouldn't have to be concerned about this error normally. Further, you can't update parts to a higher precision -- internally, Vector3s and CFrames have this amount of precision.


If you're having troubles because this imprecision means you go far over the limits, e.g., to 9.9 or 10.1, you can fix this by treating the problem differently.

Instead of

while y < target do
    local move = 0.1
    y = y + move
    wait()
end

Use something like:

while y < target do
    -- THE LESSER OF how far I need to, and the maximum speed:
    local move = math.min( 0.1, target - y )
    y = y + move
    wait()
end

This also has the advantage of letting you use time deltas.

The amount of time that wait() actually pauses for can wildly vary. It's usually best (at least with small wait times) to actually use the time that has elapsed:

moveRate = 3 -- studs/second
while y < target do
    -- THE LESSER OF how far I need to, and the maximum speed:
    local move = math.min( 0.1, target - y )
    y = y + moveRate * wait()
end
Ad

Answer this question