yeah i know about that. So should i send the tween through remote event?
Send the tween details through the remote event, like how long the tween takes and what enemy to tween. Then, on the client, tween the character.
If you ever need help, feel free to ask.
so the client moves the enemies. So does the client send a remote event back to delete the enemy when it reaches the end?
No, just add a wait on the server and make sure to set the position on the server every time the tween finishes (just wait until the tween should end, no need for further client communication).
so⌠the remote function cant send the model?
heres the code:
ReplicatedStorage.moveenemies.OnClientInvoke = function(model,distance,goal)
print("clientmodel: ".. tostring(model:GetFullName()))
print("clientdistance: "..tostring(distance))
print("clientgoal: "..tostring(goal))
local tweeninfo = TweenInfo.new(distance,Enum.EasingStyle.Linear)
local tween = TweenService:Create(model.HumanoidRootPart,tweeninfo,goal)
tween:Play()
tween.Completed:Wait()
end
for i,v in pairs(Players:GetPlayers()) do
moveremote:InvokeClient(v,model, distance / enemySpeed ,movementgoal)
end
Use a RemoteEvent instead and use :FireAllClients.
Okay, I got the remote function working⌠turns out the model wasnât loading fast enough. Itâs still a bit laggy tho.
Actually Iâll switch to remote events. I just realized that remote functions are extremely insecure. My one concern is that the client could lag badly, and the server might just teleport the enemy to the next node, before the client finishes the tween. Also, could you explain your time scaling code, because the main reason I skipped tweens is that I thought scaling the time would take too long.
Itâs basic physics. Distance / Speed = Time
So you can just wait the amount to time you send over.
How would I go about changing the enemy speeds while the enemyâs are moving? Because thatâs one of the last things the humanoid system had that the tweeting system didnât I thought about sending another remote to cancel the tween, but I couldnât reliably find the tween that the client was using for an specific enemy. A little help here? @Katrist
Tweens automatically are cancelled when another tween (of the same properties) is played onto the object. You donât have to manually do :Cancel
.
wait but how would i cancel the task.wait()
teleport on the server? should i try putting everything in a coroutine and cancel that?
Smart idea. You can also use task.spawn and task.cancel because it may be easier to work with.
i tried doing the coroutine method, and the client cant tween the enemy properly. It tries to go to the first node, and the server teleports it back to the node its supposed to be. And than it works fine.
--!native
local module = {}
local ServerStorage = game:GetService("ServerStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local PhysicsService = game:GetService("PhysicsService")
local moveremote = ReplicatedStorage:WaitForChild("tweenenemy")
local Players = game:GetService("Players")
module.spawn = function(name:string, waypointfolder:Folder, exit, spawns:CFrame, boss:BoolValue)
local offset = math.random(-1,1)
local model: Model = ServerStorage.Enemies:FindFirstChild(name):Clone()
model:PivotTo(spawns + Vector3.new(offset,0,0))
if boss then
ReplicatedStorage.AddHealthBar:FireAllClients(name,model.Health.Value,model.Health.Value)
end
--for _,parts:BasePart in pairs(model) do
-- if parts:IsA("BasePart") then
-- parts.CollisionGroup = "Enemies"
-- end
--end
model.Parent = Workspace:FindFirstChild(ReplicatedStorage.Map.Value).enemies
--local health = model.health
--health:GetPropertyChangedSignal("Value"):Connect(function()
-- if health.Value == 0 then
-- model:Destroy()
-- end
--end)
model.PrimaryPart:SetNetworkOwner(nil)
local enemySpeed = model.speed.value
--model.speed:GetPropertyChangedSignl("Value"):Connect(function()
-- enemySpeed = model.speed.Value
--end)
local orientation, size = model:GetBoundingBox()
for index = 1, #waypointfolder:GetChildren() do
local node = waypointfolder[index]
local finished = false
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local movethread = coroutine.create(function()
local movementgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance / enemySpeed,movementgoal)
task.wait(distance/enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
finished = true
end)
coroutine.resume(movethread)
local speed:IntValue = model:WaitForChild("speed")
speed:GetPropertyChangedSignal("Value"):Connect(function()
local changedthread = nil
print("recalculating tween")
coroutine.close(movethread)
enemySpeed = model.speed.value
distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
print("newspeed: "..tostring(enemySpeed).." ".."newdistance: "..tostring(distance).." ".."newtime: ".." "..tostring(distance / enemySpeed))
changedthread = coroutine.create(function()
print("updating tweens")
local movementgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance / enemySpeed,movementgoal)
task.wait(distance/enemySpeed)
model.PrimaryPart.CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
finished = true
end)
print(coroutine.status(changedthread))
coroutine.resume(changedthread)
end)
repeat task.wait() until finished == true
local rotationgoal = {
CFrame = CFrame.lookAlong(model.PrimaryPart.Position, node.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,0.05,rotationgoal)
task.wait(0.06)
if not model then
break
end
model.PrimaryPart.CFrame = CFrame.lookAlong(model.PrimaryPart.Position, node.CFrame.LookVector)
end
if model then
local node = exit
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local movmentgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance/ enemySpeed,movmentgoal)
task.wait(distance/enemySpeed)
ReplicatedStorage.BaseHealth.Value = math.clamp(ReplicatedStorage.BaseHealth.Value - model.Health.Value,0,ReplicatedStorage.MaxBaseHealth.Value)
model:Destroy()
end
end
return module
type or paste code here
hers a video:
you can see the enemy glitching around and then teleporting back.
You forgot to recalculate the distance. You also forget to disconnect the :GetPropertyChangedSignal
event.
Code:
--!native
local module = {}
local ServerStorage = game:GetService("ServerStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local PhysicsService = game:GetService("PhysicsService")
local moveremote = ReplicatedStorage:WaitForChild("tweenenemy")
local Players = game:GetService("Players")
module.spawn = function(name:string, waypointfolder:Folder, exit, spawns:CFrame, boss:BoolValue)
local offset = math.random(-1,1)
local model: Model = ServerStorage.Enemies[name]:Clone()
model:PivotTo(spawns + Vector3.new(offset,0,0))
if boss then
ReplicatedStorage.AddHealthBar:FireAllClients(name,model.Health.Value,model.Health.Value)
end
--for _,parts:BasePart in pairs(model) do
-- if parts:IsA("BasePart") then
-- parts.CollisionGroup = "Enemies"
-- end
--end
model.Parent = Workspace:FindFirstChild(ReplicatedStorage.Map.Value).enemies
--local health = model.health
--health:GetPropertyChangedSignal("Value"):Connect(function()
-- if health.Value == 0 then
-- model:Destroy()
-- end
--end)
model.PrimaryPart:SetNetworkOwner(nil)
local speed:IntValue = model:WaitForChild("speed")
--model.speed:GetPropertyChangedSignl("Value"):Connect(function()
-- enemySpeed = model.speed.Value
--end)
local orientation, size = model:GetBoundingBox()
for index = 1, #waypointfolder:GetChildren() do
local node = waypointfolder[index]
local finished = false
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local enemySpeed = speed.Value
local movethread = task.spawn(function()
local movementgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance / enemySpeed,movementgoal)
task.wait(distance/enemySpeed)
model.PrimaryPart.CFrame = movementgoal.CFrame
finished = true
end)
local speedChanged = nil
speedChanged = speed.Changed:Connect(function(enemySpeed)
if movethread then
task.cancel(movethread)
movethread = nil
end
distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
print("newspeed: "..tostring(enemySpeed).." ".."newdistance: "..tostring(distance).." ".."newtime: ".." "..tostring(distance / enemySpeed))
movethread = task.spawn(function()
print("updating tweens")
local movementgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance / enemySpeed,movementgoal)
task.wait(distance/enemySpeed)
model.PrimaryPart.CFrame = movementgoal.CFrame
finished = true
end)
end)
repeat task.wait() until finished == true
speedChanged:Disconnect()
local rotationgoal = {
CFrame = CFrame.lookAlong(model.PrimaryPart.Position, node.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,0.05,rotationgoal)
task.wait(0.06)
if not model then
break
end
model.PrimaryPart.CFrame = rotationgoal.CFrame
end
if model then
local node = exit
local distance = (node.Position + Vector3.new(offset, size.Y / 2, 0) - model.PrimaryPart.Position).Magnitude
local movmentgoal = {
CFrame = CFrame.lookAlong(node.Position + Vector3.new(offset, size.Y / 2, 0), model.PrimaryPart.CFrame.LookVector)
}
ReplicatedStorage.tweenenemy:FireAllClients(model,distance/ enemySpeed,movmentgoal)
task.wait(distance/enemySpeed)
ReplicatedStorage.BaseHealth.Value = math.clamp(ReplicatedStorage.BaseHealth.Value - model.Health.Value,0,ReplicatedStorage.MaxBaseHealth.Value)
model:Destroy()
end
end
return module
erm⌠the enemy that has itâs speed changed still glitches around
Could you try my edited script? If it doesnât work, another video would help in debugging the problem.
Yeah I used the edited script. The exact same thing happened, where you can see the enemyâs glitching around.
You can also see the enemyâs glitching around and acting up if u watch the video I sent u
at 0:26 in the video, if you look at the path near the entrance, you can see the enemy being glitchy
Does it print the newSpeed correctly?