How do I save a player's position of 5 seconds ago? (Revert script)

Hi, I need help about reverting a player position of 5 seconds ago. (I’m Spanish, sorry if I have mistakes)

My problem is saving the position

  1. What do you want to achieve? Keep it simple and clear!
    Revert player’s position of 5 seconds ago
  2. What is the issue?

I don’t know a way of how to save the position constantly then when this activates, all players goes to their position of 5 seconds ago (Real issue is about saving position, I already know how to update position of before)

  1. What solutions have you tried so far?
    All I can do is to update position EVERY 5 seconds, but it won’t work exactly since it updates every 5 seconds and not every 0.1 second or every second.

I’m not very advanced at scripting, so please make examples if you can :D.

1 Like

You can use something like this, which will update whenever the player moves. I do not know how expensive this will be though.

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
        Character.HumanoidRootPart.Changed:Connect(function()
		print(Character.HumanoidRootPart.Position) -- This will print the Vector3 value which is X/Y/Z
        end)
	end)
end)   
local OldPositions = {}

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
		while Character do
			OldPositions[tostring(Player)] = Character.PrimaryPart.Position
			wait(5)
		end
	end)
end)

function RevertPlayerPos(Player)
	local OldPos = OldPositions[tostring(Player)]
    if OldPos then
	    Player.Character:MoveTo(OldPos)
    end
end
3 Likes

You’re waiting 5 seconds, which will cause problems because if the timer is in the middle of doing something while the player is being moved, the position won’t be correct.

Well it should be fixed in the next 5 seconds anyways

He wants the position of the player 5 seconds ago?

Yes, but he said he can’t wait 5 seconds since it will not update.

small mistake

also as you edited in it shouldn’t gc after the player leaves but tbh it’s just a Vector3 value and doesn’t take up much memory

A bit unclear, do you want to update the position every 0.1 seconds or every 5 seconds?

I’m not sure if I understand. He said he wants to revert the players position to 5 seconds ago when a function is called.

Also @azahid1 the problem with signals is that if it is not properly gc’ed, they will accumulate and they will cause the game to crash (esp. true with large game servers). Read: PSA: Connections can memory leak Instances!

1 Like

Actually to revise my script, you would need to add a timestamp. So what I am going to do is use a LocalScript instead.

local start = os.time()

local Positions = {
[1] = Vector3.new(0,0,0),
[2] = Vector3.new(0,0,0),
[3] = Vector3.new(0,0,0),
[4] = Vector3.new(0,0,0),
[5] = Vector3.new(0,0,0),
}

repeat wait() until game.Player.LocalPlayer.Character
       while wait(5) do
          start = os.time()
               for i = 1,5 do
                     Positions[i].Value =  game.Players.LocalPlayer.Character.HumanoidRootPart.Position
                     wait(1)
               end 
       end 
end

function getPreviousPosition()
      local gettime = os.time()
      if gettime - start > 0 then
           return Positions[gettime-start]
      else
           return Positions[1]
      end
end

1 Like

Vector3’s do not have a .Value data property and I don’t think the code-logic will properly do what he’s asking.

Look at my reply and see what you think, I think I have what he wants.

So I don’t know how efficient cent this is but this should work. Create a table that holds every player’s position in the last 5 seconds. The table I made is going to look a little like this -

playerPositions = {

["Player"] = {
		["Time"] = "pos",
		["Time"] = "pos",
		["Time"] = "pos",
		["Time"] = "pos",
		["Time"] = "pos"
	}
}

Then lets add the Player in the table everytime someone joins, thats simple enough -

game.Players.PlayerAdded:Connect(function(player)
    table.insert(playerPositions, player)
    playerPositions[player] = {}
end)

Then on another thread we are going to constantly update every Player’s position according to that Player’s os.time() in this table. To do so we will be using a couple loops -

coroutine.resume(coroutine.create(function()
while true do
	for _,Player in pairs(game.Players:GetPlayers()) do
		local playerChar = Player.Character
		if playerChar ~= nil then
			playerPositions[Player][os.time()] = playerChar:FindFirstChild("HumanoidRootPart").Position
		end
		
		if playerPositions[Player][(os.time() - 6)] ~= nil then --Get rid of any position 6 seconds ago
			playerPositions[Player][(os.time() - 6)] = nil
		end
		print(playerPositions[Player][os.time()])
	end
	wait(1)
end
end))

Now to retrieve the Player’s position from 5 seconds ago we can do

playerPositions["PlayerName"][os.time() - 5]

For this method I am adding every position in the last 5 seconds so you could technically get the position from the last 1-5 seconds. You can probably modify this so it is only 5 seconds, but I like how it is :slight_smile: it is a bit sloppy as I am doing this on my laptop but hopefully it works.

edit: There may be better ways to achieve this without os.time() and other things but this is just my take on solving your problem.

2 Likes

I see we think alike my friend, but yeah either os.time or a ingame timer is the most efficient way so you don’t have to worry.

2 Likes

every 0.1 second or 1 second, if i make it every 5 seconds then it won’t be 5 seconds exactly

Use jody’s but swap the wait with
game:GetService("RunService").Heartbeat:wait()

After reading some replies here, I’m not sure why some seem to store multiple positions. All you need is one position- the one from 5 seconds ago. (Per player, ofc)

This method will not move players who have been in the game for less than 5 seconds, as their position 5 seconds ago does not exist.

I’m on my phone, but I’ll try to type something up. Mobile really hates formatting code, sorry.


local PlayerPositions = {}

game:GetService("Players").PlayerAdded:Connect(function(Player)
 Player.CharacterAdded:Connect(function(Char)
Char:WaitForChild("HumanoidRootPart"):GetPropertyChangedSignal("CFrame"):Connect(function()
   delay(4.98, function()
    PlayerPositions[Player] = Char.HumanoidRootPart.CFrame
   end)
  end)
 end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
 PlayerPositions[Player] = nil
end)

local function Revert()
 for plr,cf in pairs(PlayerPositions) do
  plr.Character.HumanoidRootPart.CFrame = cf
 end
end
6 Likes

The reason why we are storing multiple values is because the script OP is talking about wants to move ALL players, which means that in the function that you are using all the players will not be synced because there is little chance they will all start moving at the same time, and the whole thing with new players joining.

1 Like