How to make this lerp isntead?

Hello, I am trying to make my enemy move without Move:To because I have heard lerp is way better. How would I implement that in my code?

function mob.Move(mob, map)
	local humanoid = mob:WaitForChild("Humanoid")
	local waypoints = map.Waypoints

	for waypoint =1, #waypoints:GetChildren() do
		mob.MovingTo.Value = waypoint
		humanoid:MoveTo(waypoints[waypoint].Position)
		humanoid.MoveToFinished:Wait()
	end

	if humanoid.Health > 0 then
		HPInt.Value -= humanoid.Health
	end
	
	mob:Destroy()
end

bump, cause its been 3 hours and yeah

MoveTo and lerp are 2 completely different things so ill try by best to explain them to you and why there is no such thing as one being better then the other

a humanoid is a complex object the MoveTo function tells the humanoid that you want it to move to a position and the humanoid will walk to that position taking into consideration collisions gravity walkspeed and more

the lerp function is used to interpolated between two values

here is what the lerp function does

local function Lerp(value1, value2, alpha)
    return value1 + (value2 - value1) * alpha
end

print(Lerp(1, 2, 0.7)) -- 1.7

so what this is doing is moving one value towards another value by a percentage
so if we did Lerp(10, 20, 0.5)
that will return a value of 15 because 0.5 = 50% so we are interpolated the value 10 50% towards 20 and thats 15

Roblox provides Lerp functions for many data types CFrame, Vector3, Vector2 and Color3

so if we have two colors

local color1 = Color.fromRGB(255, 0, 0) -- red
local color2 = Color.fromRGB(0, 0, 255) -- blue
local color3 = color1:Lerp(color2, 0.5) -- move red 50% closer towards blue to make purple

so we can use lerp to move objects towards other object like this

local part = ...
local targetPart = ...
while true do
	part.Position = part.Position:Lerp(targetPart.Position, 0.5) -- move part 50% closer to targetPart
	task.wait() -- wait 1 frame
end

so at frame 1 lets say part is at a position of 0 and target part is at a position of 10
part will move 50% closer now part is at 5
one frame later part will move 50% closer again and that will be 7.5
then one frame later another 50% and now its at 8.75
then one frame later another 50% and now its at 9.375

so as you can see the part is moving towards the target part 50% every frame but is never able to reach the target because 50% is never 100%

so don’t use lerp just because someone said its better

so if your not going to take advantage of humanoids then you should not use them at all

take a look at this post of how to not use humanoids and have lots of characters

3 Likes

Thank you for you long and wonderful explanation! :slight_smile: This really helped me a lot. The thing is I want to take advantage of humanoids and I heard that lerp can increase performance and make it more efficient with multiple humanoids. Thats why I wanted to convert it to lerp.

If you were to use Lerp, it may look something like this:

function mob.Move(mob, map)
	local humanoid = mob:WaitForChild("Humanoid")
    local hrp = mob:WaitForChild("HumanoidRootPart")
	local waypoints = map.Waypoints:GetChildren()

	for waypoint =1, #waypoints do
		mob.MovingTo.Value = waypoint

        local currentPosition = nil
        local goingToPosition = waypoints[waypoint].Position

        --< Making sure the loop doesn't break at the beginning
        if waypoint = 1 then
           currentPosition = hrp.Position
        else
           currentPosition = waypoints[waypoint - 1].Position
        end

		for i = 0, 1, 0.01 do
           --< finding the "i" between currentPosition & goingToPosition
           hrp.CFrame = CFrame.new(currentPosition:Lerp(goingToPosition, i))
           task.wait()
        end

	end

	if humanoid.Health > 0 then
		HPInt.Value -= humanoid.Health
	end
	
	mob:Destroy()
end

Think of Lerp as finding a point between a line. In this case, the line is between currentPosition and goingToPosition, and using i to find a point between that line.

1 Like

if you look at my 500_enemys_running_at_60_fps.rbxl project

instead of lerp what i’m doing is

model.PrimaryPart.CFrame += direction * moveAmount

so what this does it moves the model in a direction with a amount and that can also be a method to move characters around

you will also notice I’m not using humanoids but animation controllers because there is not much point using a humanoid if your not going to be using MoveTo

1 Like

Here is my whole code if you need it:

local ServerStorage = game:GetService("ServerStorage")

local PhysicsService = game:GetService("PhysicsService")
local ServerStorage = game:GetService("ServerStorage")
local replicatedStorage = game:GetService("ReplicatedStorage")
local sharedValues = replicatedStorage:WaitForChild("SharedValues")
local HPInt = sharedValues:WaitForChild("HP")
local mob = {}

function mob.Move(mob, map)
	local humanoid = mob:WaitForChild("Humanoid")
	local hrp = mob:WaitForChild("HumanoidRootPart")
	local waypoints = map.Waypoints:GetChildren()

	for waypoint =1, #waypoints do
		mob.MovingTo.Value = waypoint

		local currentPosition = nil
		local goingToPosition = waypoints[waypoint].Position

		--< Making sure the loop doesn't break at the beginning
		if waypoint == 1 then
			currentPosition = hrp.Position
		else
			currentPosition = waypoints[waypoint - 1].Position
		end

		for i = 0, 1, 0.01 do
			--< finding the "i" between currentPosition & goingToPosition
			hrp.CFrame = CFrame.new(currentPosition:Lerp(goingToPosition, i))
			task.wait()
		end

	end

	if humanoid.Health > 0 then
		HPInt.Value -= humanoid.Health
	end

	mob:Destroy()
end
function mob.Spawn(name, quantity, map)
	local mobExists = ServerStorage.Mobs:FindFirstChild(name)

	if mobExists then
		for i =1, quantity do
			task.wait(0.5)
			local newMob = mobExists:Clone()
			newMob.HumanoidRootPart.CFrame = map.Start.CFrame
			newMob.Parent = workspace.Mobs
			newMob.HumanoidRootPart:SetNetworkOwner(nil)

			local movingTo = Instance.new("IntValue")
			movingTo.Name = "MovingTo"
			movingTo.Parent = newMob

			for i, object in ipairs(newMob:GetDescendants()) do
				if object:IsA("BasePart") then
					PhysicsService:SetPartCollisionGroup(object, "Mob")
				end
			end

			newMob.Humanoid.Died:Connect(function()
				task.wait(0.1)
				newMob:Destroy()
			end)
			coroutine.wrap(mob.Move)(newMob, map)
		end

	else
		warn("Requested mob does not exist:", name)
	end
end


return mob

But This is what is happening:
Its supposed to start at the green (btw)

I understand, the thing is I am going to need the Humanoid as I am going to make it lose health and such later on so a Humanoid is something I need to do that.

could you not use things like Instance Attributes | Roblox Creator Documentation for things like health

model:SetAttribute("Health", 100)

model:GetAttributeChangedSignal("Health"):Connect(function()
	local health = model:GetAttribute("Health")
	print("Health:", health)
end)

local health = model:GetAttribute("Health")
model:SetAttribute("Health", health - 10)

because even if your not using the moveto function the humanoid is still doing calculations when its standing there idle

and if your going to go to the trouble of not using moveto then things like health are a lot more simple to do verses not using moveto

1 Like

I actually forgot about attributes and your right, I can make it so it uses attribute for health instead. Another concern tho is

Would this work with waypoints?

yes it will here are some demos some of these demos use waypoints

SpawnEnemys.rbxl (36.7 KB)
Server_keeping_track_of_enemy_positions.rbxl (33.9 KB)
spawn_enemys_without_a_loop.rbxl (35.0 KB)
500_enemys_running_at_60_fps.rbxl (36.2 KB)
FollowPath.rbxl (42.9 K)

and this video might help you make the characters client sided so you use less network

and you might also want to use parallel scripting this video might help

this will allow you to use multiple threads to move the characters and will improve performance

1 Like