Speed based lerp?

I couldn’t find fix!

I tried doing thing, but I have problem

I’m trying to do client-render for tower defense, but my only problem is that I have no idea how to make it move on server
I did one thing, but it doesn’t work well

1. The speed is based off distance (Well obviously why), which make it slow down as it comes nearby the waypoint

  1. It stopping for a while when it reaches waypoint, then continues

On video:
Green part where it actually currently is
Gray part is where it will be for player

Problem Video Link: (If you cant watch, it is uploading or I did something wrong)

Code:

function class:Move(delta) -- Heartbeat loops gives delta!
	local CurrentMobPath = self.TargetPath -- path name
	CurrentMobPath = shared.Path.Paths[CurrentMobPath] -- path data
	
	if not CurrentMobPath then
		warn("Mob path not found!", self.TargetPath)
		return
	end
	
	local TargetWaypointInstance = CurrentMobPath.Waypoints[self.TargetWaypoint] -- A part!
	if not TargetWaypointInstance then return end
	
	-- self.Position is a CFrame
	local distance = (self.Position.Position - TargetWaypointInstance.Position).Magnitude
	
	local Speed = self.Speed or 1
	local relateSpeed = (distance / Speed) -- Nothing to do with this I think
	
	local goalCFrame = self.Position:Lerp(TargetWaypointInstance.CFrame, math.min(1, self.Alpha))
	self.Position = goalCFrame
	
	if debugging then
		local LookAt = CFrame.lookAt(self.Position.Position, TargetWaypointInstance.Position)
		
		tweenservice:Create(self.DebugPart2, TweenInfo.new(0.2, Enum.EasingStyle.Sine), {CFrame = LookAt}):Play()
		tweenservice:Create(self.DebugPart, TweenInfo.new(0.2, Enum.EasingStyle.Sine), {CFrame = LookAt}):Play()
		self.DebugPart2.CFrame = LookAt
	end
	
	self.Alpha += (delta / relateSpeed)
	if self.Alpha >= 1 then -- Surely problem in this for it stopping for a while, cuz if I change this, it stops for a less period of time
		self.Alpha = 0
		self.TargetWaypoint += 1
		if self.TargetWaypoint > #CurrentMobPath.Waypoints then
			self:Destroy()
			return
		end
	end
	
	if self.Health <= 0 then
		self:Destroy()
		return
	end
	
end
1 Like

I’m confused on what your problem is. Are you trying to make the enemies travel paths of varying lengths at a constant time?

1 Like
  1. The speed is based off distance (Well obviously why), which make it slow down as it comes nearby the waypoint
  2. It stopping for a while when it reaches waypoint, then continues

It does not actually slows down when it comes near, the problem is 2nd one
(Watch a video)

I don’t see any issues in your video

Watch as the parts reach waypoints, they stop there for a few seconds (shouldn’t happen)

Maybe the problem is with how I use the waypoint index, but I don’t think so

Not in it, added some prints and it starts going to other one as it prints that it reached

If my hypothesis is correct, relateSpeed is the culprit. relateSpeed is the time it should take to travel a certain distance given a velocity (T=D/V). You’re interpolating the position of the enemy over this time, so the value should be constant. In your case, you’re shifting the goalpost of your alpha value as the enemy gets ever-closer to its target waypoint, and as the distance gets smaller, the relateSpeed value becomes even smaller. This leads to smaller and smaller adjustments to your alpha value, which can explain the decrease in speed as the enemy approaches the target waypoint

TL;DR: Calculate relateSpeed once per interpolation between waypoints

TL;DR: Calculate relateSpeed once per interpolation between waypoints

Whatt?
what interpolation

Did you not know? “Lerp” is short for “linear interpolation”. Interpolation is the process of deriving an unknown number between two known numbers. In terms of mathematical functions, it’s about travelling the domain and revealing the function’s range within that domain. To sum it up, recalculate relateSpeed each time you set a new target waypoint. To make this easier, make relateSpeed a property of your object (self). You should rename this property to “targetTime”

I think its already being recalculated every time, the function is being called by heartbeat loop which gives delta time to the function

Yes. That is the problem. Your relateSpeed variable should only be calculated once each time a new waypoint is set. You’re recalculating this value each time the function is called

oooohhh I see now

let me try what you told

I guess you told me to recalculate it each time a new waypoint is set

It broke everything I think

Basically the alpha goes up slow now
I made it go to next at 0.1, but it has other problem which is also shown in the video (near the end)

I decided to make waypoints closer, and I saw that problem is because of the far distance between waypoints

Your video is heavily corrupted; I cannot see the new script. As far as I can tell, you are still not calculating targetTime correctly

It does calculates only when it gets to the new waypoint, I can see that by the prints

(I really have no idea why its corrupted)

Please send the latest version of your script

function class:GetTargetTime()
	local CurrentMobPath = self.TargetPath -- path name
	CurrentMobPath = shared.Path.Paths[CurrentMobPath] -- path data

	if not CurrentMobPath then
		warn("Mob path not found!", self.TargetPath)
		return
	end

	local TargetWaypointInstance = CurrentMobPath.Waypoints[self.TargetWaypoint] -- A part!
	if not TargetWaypointInstance then return end
	
	local distance = (self.Position.Position - TargetWaypointInstance.Position).Magnitude
	local Speed = self.Speed or 1
	
	local relateSpeed = distance / Speed
	self.targetTime = relateSpeed
	self.lastWaypointTargetTime = self.TargetWaypoint
end

function class:Move(delta) -- Heartbeat loops gives delta!
	local CurrentMobPath = self.TargetPath -- path name
	CurrentMobPath = shared.Path.Paths[CurrentMobPath] -- path data
	
	if not CurrentMobPath then
		warn("Mob path not found!", self.TargetPath)
		return
	end
	
	local TargetWaypointInstance = CurrentMobPath.Waypoints[self.TargetWaypoint] -- A part!
	if not TargetWaypointInstance then return end
	
	-- self.Position is a CFrame
	local distance = (self.Position.Position - TargetWaypointInstance.Position).Magnitude
	
	local Speed = self.Speed or 1
	if not self.targetTime then
		self:GetTargetTime()
	else
		if self.lastWaypointTargetTime ~= self.TargetWaypoint then
			self:GetTargetTime()
			print("Set new target time!")
		end
	end
	
	local goalCFrame = self.Position:Lerp(TargetWaypointInstance.CFrame, math.min(1, self.Alpha))
	self.Position = goalCFrame
	
	if debugging then
		local LookAt = CFrame.lookAt(self.Position.Position, TargetWaypointInstance.Position)
		
		tweenservice:Create(self.DebugPart2, TweenInfo.new(0.2, Enum.EasingStyle.Sine), {CFrame = LookAt}):Play()
		tweenservice:Create(self.DebugPart, TweenInfo.new(0.2, Enum.EasingStyle.Sine), {CFrame = LookAt}):Play()
		self.DebugPart2.CFrame = LookAt
	end
	
	self.Alpha += (delta / self.targetTime)
	if self.Alpha >= 0.1 then
		self.TargetWaypoint += 1
		self.Alpha = 0
		print("Adjusted waypoint!")
		
		if self.TargetWaypoint > #CurrentMobPath.Waypoints then
			self:Destroy()
			return
		end
	end
	
	if self.Health <= 0 then
		self:Destroy()
		return
	end
	
end
function class.start()
	--local con1
	--con1 = game:GetService("RunService").Heartbeat:Connect(function(delta)
	--	for _, self in pairs(class.Collection) do
	--		self:Move(delta)
	--	end
	--end)
	
	local newMob = class.new("Mob1")
	local new
	new = game:GetService("RunService").Heartbeat:Connect(function(delta)
		newMob:Move(delta)
	end)
end

Return your self.Alpha >= 1 check

At the start of the video where its not corrupted yet, you can see what happens with it

But basically, it increments alpha too low so the “mob” stays here for long time

Ah. I think I’ve spotted the issue. Do not interpolate between the current position and the target position. Interpolate between the previous waypoint’s position and the target position