So I want to switch over to client rendering instead of having everything done on the server. Now I thought about how to do it by storing the CFrame on the server and having the actual enemy appear on the client. The only problem is actually how to store the CFrame on the server and then send it to the client every time it updates to move the enemy to that CFrame. So if anyone can help on this, I would really appreciate it!
um roblox automatically replicates and renders it on the client
I already know this but what im trying to achieve is to not have the actual enemy model on the server and only the client to not make that much lag. So what I would have to do is store the CFrame on the server and somehow update that on the client when it updates.
So you want the to get the cframe of the enemy from the server but not keep the enemy model on the server?
I feel like this is an unnecessary optimization (it might not be an optimization at all). But anyway if you want to send CFrame values to the client easily you can use the built in CFrameValue and put it in a replicated container and it will automatically replicate. Then you can listen to CFrameValue.Changed on the client.
Most tower defense games use some kind of client rendering where the actual enemy is on the client but not on the server and idk what to really do in terms if I have to do anything on the server. But I could try what you said and see if it helps.
Usually tower defense enemies are pretty determinstics like projectiles.
You only need to know the time it spawns and the current time to know the location of the enemy.
So you can do something like this
I will try to look into this and see what I can do with it.
Ok I tried looking around in this post but I am stuck all because I need my enemies to be stopped or changing speed sometimes (mostly bosses). I didn’t put any of the code that was in there but this is my code. Lerping seems to be quite laggy on the server side but it perfectly stops and changes enemy speed. This is the module script if you couldn’t tell.
Code:
local ServerStorage = game:GetService("ServerStorage")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local events = ReplicatedStorage:WaitForChild("Events")
local mob = {}
function mob.LerpTo(newMob, target, XZOffset)
local targetPos = Vector3.new(target.Position.X,target.Position.Y + newMob.Stats.YOffset.Value,target.Position.Z)
local alpha = 0
local startCFrame = newMob.HumanoidRootPart.Position
local loop
local loopBool = false
local distance = (newMob.HumanoidRootPart.Position - targetPos).Magnitude
loopBool = true
loop = RunService.Heartbeat:Connect(function(deltaTime)
if newMob and newMob:FindFirstChild("Stats") then
local speed = newMob.Stats.Speed.Value
local relativeSpeed = distance / speed
local goalCFrame = startCFrame:Lerp(targetPos, alpha)
newMob.HumanoidRootPart.Position = goalCFrame
alpha += deltaTime / relativeSpeed
if alpha >= 1 then
loop:Disconnect()
loopBool = false
end
else
loop:Disconnect()
loopBool = false
end
end)
repeat task.wait()
until loopBool == false
newMob.HumanoidRootPart.CFrame = target.CFrame * CFrame.new(0,newMob.Stats.YOffset.Value,0)
end
function mob.Move(newMob, sb, pathNum, map, XZOffset)
local humanoidRootPart = newMob:FindFirstChild("HumanoidRootPart")
local waypoints = map:FindFirstChild("Waypoints"..pathNum)
local newPos
if sb == nil or game.Players:FindFirstChild(sb.Name) then
for waypoint=2, #waypoints:GetChildren() do
if newMob and newMob:FindFirstChild("MovingTo") then
newMob.MovingTo.Value = waypoint
newPos = waypoints[waypoint]
mob.LerpTo(newMob, newPos, XZOffset)
end
end
end
if newMob:FindFirstChild("MovingTo") and newMob.MovingTo.Value ~= 0 then
if map.Base:FindFirstChild("Humanoid") then
map.Base.Humanoid:TakeDamage(newMob.Stats.Health)
elseif map.Base:FindFirstChild("Health") and map.Base:FindFirstChild("MaxHealth") then
map.Base.Health.Value -= newMob.Stats.Health.Value
end
end
newMob:Destroy()
end
function mob.Spawn(name, spawnloc, quantity, spawnedBy, map)
local mobExists = ServerStorage.Mobs:FindFirstChild(name)
if mobExists and workspace.Info.GameRunning.Value == true then
for i=1, quantity do
task.wait(0.5)
local paths = map.Paths.Value
if spawnedBy ~= nil and not game.Players:FindFirstChild(spawnedBy.Name) then
paths = 1
end
for v=1, paths do
local newMob = mobExists:Clone()
local XZOffset = Random.new():NextNumber(-0.5,0.5)
local YOffset = newMob.Stats.YOffset.Value
if spawnedBy == nil then
newMob.HumanoidRootPart.CFrame = map:FindFirstChild("Waypoints"..v)["1"].CFrame + Vector3.new(0,YOffset,0)
else
local mobName = newMob.Name
newMob.Name = spawnedBy.Name .. "'s " .. mobName
if spawnloc == nil then
newMob.HumanoidRootPart.CFrame = map:FindFirstChild("Waypoints"..v)["1"].CFrame + Vector3.new(0,YOffset,0)
else
newMob.HumanoidRootPart.CFrame = spawnloc
end
end
newMob.Parent = workspace.Mobs
local movingTo = Instance.new("IntValue")
movingTo.Name = "MovingTo"
movingTo.Parent = newMob
local pathValue = Instance.new("IntValue")
pathValue.Name = "OnPath"
if spawnedBy == nil or game.Players:FindFirstChild(spawnedBy.Name) then
pathValue.Value = v
end
pathValue.Parent = newMob
if newMob:FindFirstChild("IsBoss") then
events.NewBossBar:FireAllClients(newMob)
end
for p, object in ipairs(newMob:GetDescendants()) do
if object:IsA("BasePart") then
object.CollisionGroup = "Mob"
end
end
newMob.Stats.Health:GetPropertyChangedSignal("Value"):Connect(function()
if newMob.Stats.Health.Value <= 0 then
task.wait(0.1)
if not newMob:FindFirstChild("DieAnim") then
newMob:Destroy()
end
end
end)
coroutine.wrap(mob.Move)(newMob, spawnedBy, v, map, XZOffset)
end
end
else
end
end
events.SpawnEnemy.Event:Connect(function(enemyName, spawnln, amount, spawnedByEnemy, mapName)
mob.Spawn(enemyName, spawnln, amount, spawnedByEnemy, mapName)
end)
return mob