Better ways to “Tween” Align Position value? (Diep.io Movement System)

Hello there! I’ve been trying to recreate the game Diep.io in roblox mainly for fun and because an Old Roblox Diep.io broke (due to roblox updates I’m assuming)

I’m currently changing from depreciated BodyPosition to AlignPosition and decided to improve the current movement system I have.


This is the current movement I have



And this is the new movement system I’m working on


I want it to be like the real diep.io movement system

Example of the real movement system

and so far it works by tweening the position value of the Align Position. However my concern is the efficiency of the code below

repeat					
	if plr ~= nil then
		local BasePosWithoutY = Vector3.new(Base.Position.X,SpawnedYValue,Base.Position.Z)
		if LastSavedMoveMagnitude == 0 then -- if the player is moving for the first time the speed should be faster
			local TweenInformation = TweenInfo.new(1,Enum.EasingStyle.Linear,Enum.EasingDirection.Out)
			local TweenGoal = {Position = BasePosWithoutY + (plr.Character.Humanoid.MoveDirection*50)}
			local TweenGo = TweenService:Create(BodyP,TweenInformation,TweenGoal)
			TweenGo:Play()			
		else
			local TweenInformation = TweenInfo.new(2,Enum.EasingStyle.Linear,Enum.EasingDirection.Out)
			local TweenGoal = {Position = BasePosWithoutY + (plr.Character.Humanoid.MoveDirection*50)}
			local TweenGo = TweenService:Create(BodyP,TweenInformation,TweenGoal)
			TweenGo:Play()
		end
		task.wait()
    end
until CurrentMoveDirection ~= plr.Character.Humanoid.MoveDirection or plr.Character.Humanoid.MoveDirection.Magnitude == 0 or plr == nil
if plr ~= nil then
	LastSavedMoveMagnitude = plr.Character.Humanoid.MoveDirection.Magnitude
end

My main concern is that every task.wait() we are stopping the tween and starting a new one which i feel like is not efficient but so far has only been the solution to recreate the movement system.

So is this code fine or is there better ways to do this?

2 Likes

Are you doing this in a local script or server script? if inside a local script you can use RenderStepped to manipulate by CFrame instead of tweens

Doesnt alignposition have a property to adjust the rate of change? I would personally use lerps if rigidity is enabled.

Its a server script and i use tweens to make the tank slowly speed up as shown in the “Example of real game movement system”

Ive messed around with align position properties and they dont give me the result i want.
Also rigidity is disabled

Body position can probably replicate that really well if you get a power and dampening that you like.

I’ve mention at the top of my post that I’m moving from BodyPosition to alignPositon because BodyPosition is DEPRECATED

It’s a different approach to what you’re doing with tweens but you should try springs! https://github.com/Fraktality/Spring/blob/master/Spring.lua

They’re great for smoothing movement like this. The basic idea is you set the goal of the spring to be the position you want to “tween” towards, then you update the spring and set the object position to the springs current position. Using a damping value greater than 1 should give you that nice slow down behavior too.

The code demo is in StarterPlayerScripts:
springs demo.rbxl (34.9 KB)

If you wanted to have this smooth “joystick” / directional movement instead of the direct position then you would just have the spring solve for that direction vector instead of the final position goal vector. Apply that solved spring as velocity to your character and you should still get a similar effect.

2 Likes

This is indeed very interesting but unfortunately, I cannot configure it to work the way I want it to. Currently when standing still it causes my tank to infinitely float upwards and it also doesn’t provide the smooth motion as expected


the code below is what i used to test this method

local playersService = game:GetService("Players")
local runService = game:GetService("RunService")

local player = playersService[script.Parent.Name]

local part = script.Parent.Base

local positionSpring = require(script.Springs).new(5, 2, part.Position)
local humanoid = workspace[script.Parent.Name].Humanoid



runService.Heartbeat:Connect(function(dt)
	-- set the speed spring to the new mouse position
	positionSpring:SetGoal(part.Position + Vector3.new(humanoid.MoveDirection.X,0,humanoid.MoveDirection.Z)*20)

	-- update the spring and set the debut part
	local pos = positionSpring:Update(dt)

	part.CFrame = CFrame.new(pos)	
end)

This might be more camera desync than an issue with the springs. Instead of runService.Heartbeat try runService:BindToRenderStep() with the order value being before the camera enum Enum.RenderPriority.Camera.Value - 1

If it’s still choppy after that then it might be an issue elsewhere.

For the floating issue you can just clamp the Y height of the spring goal you’re setting. If you needed something a little more dynamic for height finding you could always raycast to find it too.

local HEIGHT = 5

-- in the loop
local origin = Vector3.new(part.Position.X, HEIGHT, part.Position.Z)
local offset = humanoid.MoveDirection * Vector3.new(20, 0, 20)

positionSpring:SetGoal(origin + offset)

Error : argument 3 missing or nil

local playersService = game:GetService("Players")
local runService = game:GetService("RunService")

local player = playersService[script.Parent.Name]

local part = script.Parent.Base

local height = part.Position.Y
local positionSpring = require(script.Springs).new(5, 2, part.Position)
local humanoid = workspace[script.Parent.Name].Humanoid


function spring()
	--
	local origin = Vector3.new(part.Position.X,height,part.Position.Z)
	local offset = humanoid.MoveDirection * Vector3.new(20,0,20)
	--
	--
	-- set the speed spring to the new mouse position
	positionSpring:SetGoal(origin + offset)

	-- update the spring and set the debut part
	local pos = positionSpring:Update()

	part.CFrame = CFrame.new(pos)
end

runService:BindToRenderStep("spring",Enum.RenderPriority.Camera.Value - 1)


i dunno if you figured this out yet, but you’re supposed to set your spring function as the third argument in your BindToRenderStep function.

like so:

runService:BindToRenderStep("spring", Enum.RenderPriority.Camera.Value - 1, spring)