So basically there is one concept you are missing here - the touch input object is the same input object throughout the lifetime of the touch. So comparing inputobjects when they are touch objects is valid to determine if it is the same finger.
Here is a simplified version that works a lot better.
--ROBLOX wants mobile developers - thankfully there is an API for that!
local touch = {}
local uis = game:GetService("UserInputService")
local gs = game:GetService("GuiService")
local fingerTracker = {}
touch.fingers = fingerTracker
local pressed = {}
local moved = {}
local lifted = {}
local function connect(tab, func)
tab[func] = true
return function()
tab[func] = nil
end
end
local function fire(tab, ...)
for func in next, tab do
func(...)
end
end
function touch.pressed(func)
return connect(pressed, func)
end
function touch.moved(func)
return connect(moved, func)
end
function touch.lifted(func)
return connect(lifted, func)
end
local function doTouchEnded(io)
local pos = io.Position
local posx = pos.x
local posy = pos.y
local storedFingerData = fingerTracker[io]
if storedFingerData ~= nil then
local deltax = posx - storedFingerData.initx
local deltay = posy - storedFingerData.initx
fire(lifted, io, posx, posy, deltax, deltay)
fingerTracker[io] = nil
end
end
local function doTouchMoved(io)
local pos = io.Position
local posx = pos.x
local posy = pos.y
local storedFingerData = fingerTracker[io]
if storedFingerData ~= nil then
local deltax = posx - storedFingerData.initx
local deltay = posy - storedFingerData.initx
fire(moved, io, posx, posy, deltax, deltay)
end
end
uis.TouchStarted:connect(function(io)
local pos = io.Position
local posx = pos.x
local posy = pos.y
fingerTracker[io] = {initx = posx, inity = posy}
fire(pressed, io, posx, posy)
io.Changed:connect(function(prop)
if prop == "Position" then
doTouchMoved(io)
elseif prop == "UserInputState" then
if io.UserInputState == Enum.UserInputState.End or io.UserInputState == Enum.UserInputState.Cancel then
doTouchEnded(io)
end
end
end)
end)
local function releaseall()
for io,_ in next, fingerTracker do
doTouchEnded(io)
end
fingerTracker = {}
end
uis.WindowFocusReleased:connect(releaseall)
gs.MenuOpened:connect(releaseall)
return touch
Depending on what you want you don’t have to release all on menu open or windowfocus release as you will still get the end event directly from the touch object. It does appear that UIS does not work correctly with the menu opening - I’ll fix that.