Know When Position Has Changed Without Using Loops or Heartbeat?

I think my last post was too wordy for people so I’ll just ask a simple question in the title. I want to be able to detect when a part’s position has changed without using loops. One of the potential solutions to creating an RTS I thought of was calculating distances when a unit moves, but the problem is that I need to be able to continue recalculating distances while the unit is still moving.

I’m not sure how to go about this because all the solutions I’ve come up with have either used a loop or used heartbeat to check. I’ve tried doing a “while unit is still moving, do calculations” thing but it lags badly when I try to up the scale to 400 units. Also, it’s annoying that changed and the signal events don’t detect physics based changes like position.

Any ideas?

Use instance:GetPropertyChangedSignal("property name"):Connect(your callback)

1 Like

You sure that works?

Of course. You can do like

humRootPart:GetPropertyChangedSignal("Position"):Connect(function()
    local newPos = humRootPart.Position
    -- your stuff
end)

Alright I forgot, the character’s property doesnt change. But you can use Heartbeat and that’s the only way to save your memory. You can run it on a separate thread.

1 Like

You mean something like this?

local rs = game:GetService("RunService")

for i = 1, numUnits do
	local p = game.ServerStorage.char:Clone()
	p.Parent = folder
	p:SetPrimaryPartCFrame(CFrame.new(math.random(-100, 100), 10, math.random(-100,100)))
	tList[p] = nil
	p.Humanoid.Running:Connect(function(speed)
		print("SPEED",speed)
		if speed <= 0.5 then
			if table.find(movingList, p) then
				local index = table.find(movingList, p)
				table.remove(movingList, index)
			end
		else
			if not table.find(movingList, p) then
				table.insert(movingList, p)
			end
		end
	end)
end

rs.Heartbeat:Connect(function(dt)
	for _, p in ipairs(movingList) do
		for _, t in ipairs(folder:GetChildren()) do
			local dist = (t.PrimaryPart.Position - p.PrimaryPart.Position).magnitude
		end
	end
	print(dt, "time elapsed", #movingList, "moving")
end)
1 Like
local part = script.Parent

part:GetPropertyChangedSignal("Position"):Connect(function()
	--execute code
end)

Doesn’t work. tathanh27 already suggested it and I tried it. Physics based changes like position aren’t registered by the changed signal, same problem with using .Changed

You should be using RunService.Stepped for this, not Heartbeat. Stepped doesn’t fire if the game (and thus physics) is paused.

The good news is that detecting movement is a form of distance comparison, not measurement, which can be a fairly cheap operation if done properly. Check out this fast distance comparison algorithm which may help you.

1 Like