So I've been working on a game where you control a ball, and I've had a serious problem for several months now. I've been ignoring it so I can finish the overall gameplay for the game, but now that I'm done with the gameplay I can't continue because of this.
Script for ball movement:
local player = game.Players.LocalPlayer local mouse = player:GetMouse() local left = false local right = false local up = false local down = false local bVel = nil local rDown = false local xVel = 0 local zVel = 0 local functions = require(Workspace.CoreFunctions) local runService = game:GetService("RunService") --Don't call "Enum.KeyCode" everytime a key is pressed local keyCode = Enum.KeyCode --[[ 0.1 - 0.5 = Heavy Friction; 0.5 - 0.9 Low Friction]] local friction = .9 game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false) game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false) --game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false) game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat, false) --game.StarterGui:SetCore("TopbarEnabled",true) local keys = game:GetService("UserInputService") local step = game:GetService("RunService") --[[ player.CharacterAdded:connect(function() wait() player.Character:WaitForChild("Torso").Anchored = true --player.Character.Parent = game.Lighting for i,v in pairs(game.Workspace:GetChildren())do if v.Name == "Ball" then if v:FindFirstChild('Owner') then if v.Owner.Value == player.Name then ball = v bVel = ball.BodyVelocity end end end end end) ]] wait(.5) local ball = functions.findBall(player) keys.InputBegan:connect(function(key) if player.PlayerGui.ChatHolder.ChatBar.Visible == false and player.PlayerGui.Spectating.Value == false then k = key.KeyCode if k == keyCode.Left or k == keyCode.A then left = true elseif k == keyCode.Right or k == keyCode.D then right = true elseif k == keyCode.Up or k == keyCode.W then up = true elseif k == keyCode.Down or k == keyCode.S then down = true end end end) keys.InputEnded:connect(function(key) k = key.KeyCode keyDown = false if k == keyCode.Left or k == keyCode.A then left = false elseif k == keyCode.Right or k == keyCode.D then right = false elseif k == keyCode.Up or k == keyCode.W then up = false elseif k == keyCode.Down or k == keyCode.S then down = false end end) while ball == nil do wait() end function onRenderStep() xVel = xVel * friction zVel = zVel * friction ball.BodyVelocity.velocity = Vector3.new(xVel,0,zVel) if left then zVel = zVel - 5 end if right then zVel = zVel + 5 end if up then xVel = xVel + 5 end if down then xVel = xVel - 5 end end runService:BindToRenderStep("Controls",Enum.RenderPriority.Camera.Value, onRenderStep)
Script for camera movement:
local player = game.Players.LocalPlayer --local ball = nil local functions = require(Workspace.CoreFunctions) local specBall = nil local runService = game:GetService("RunService") --[[ player.CharacterAdded:connect(function() wait() for i,v in pairs(game.Workspace:GetChildren())do if v.Name == "Ball" then if v:FindFirstChild('Owner') then if v.Owner.Value == player.Name then ball = v end end end end end) ]] wait(.5) local ball = functions.findBall(player) local pos = nil while ball == nil do wait() end local cam = game.Workspace.CurrentCamera cam.CameraType = "Scriptable" --Camera subject is useless here --cam.CameraSubject = ball cam.CoordinateFrame = CFrame.new(ball.Position + Vector3.new(0,50,0)) local target = script:WaitForChild("CamTarget") --[[ runService.RenderStepped:connect(function() if target.Value == "ball" then local campos = cam.CoordinateFrame.p:Lerp(ball.Position + Vector3.new(0,50,0),0.10) cam.CoordinateFrame = CFrame.new(campos,ball.Position) elseif target.Value ~= "ball" then if specBall == nil then specBall = functions.findBall(game.Players:FindFirstChild(target.Value)) end cam:Interpolate(specBall.CFrame*CFrame.Angles(12,210,31),specBall.CFrame, .3) cam.CoordinateFrame = CFrame.new(specBall.Position + Vector3.new(0,50,0)) end end) ]] local offset = Vector3.new(0,50,0) function onRenderStep() if target.Value == "ball" then --[[ pos = CFrame.new(ball.Position) + Vector3.new(0,50,0) cam:Interpolate(ball.CFrame, ball.CFrame,.2) cam.CoordinateFrame = pos ]] local ballPos = ball.Position local camPos = (ballPos) + offset cam.CoordinateFrame = CFrame.new(camPos,ballPos) elseif target.Value ~= "ball" then if specBall == nil then specBall = functions.findBall(game.Players:FindFirstChild(target.Value)) end cam:Interpolate(specBall.CFrame*CFrame.Angles(12,210,31),specBall.CFrame, .3) cam.CoordinateFrame = CFrame.new(specBall.Position + Vector3.new(0,50,0)) end end runService:BindToRenderStep("Camera",Enum.RenderPriority.Camera.Value, onRenderStep)
As you can see in the scripts I'm using RenderStepped for the movement, and HeartBeat for the camera(The camera won't interpolate correctly with RenderStepped). The camera will run smoothly if you're by yourself(about 80% of the time) but if you are playing with someone else and you get near them during the "match" the lag skyrockets. If you can't tell why this is happening based on the code can you at least tell me why you think this might be happening. I'm very desperate and will take any and all advice right now. The kind of lag that happens is sort of "input lag", where when you press down on a key the response is a little slower, and at the same time there is what I think is camera movement lag. The camera starts to be slightly behind the ball and kind of bounces.
Here's the place: Freeze Tag
tl:dr PLEASE HELP ME WITH THIS. I AM SO DESPERATE
This was edited on 3/10/16
It looks like you want the Camera to hover 50 studs above the target. If so...
The "angle" of the CFrame doesn't matter when you're using :Interpolate() -- only its position is used.
You're calling :Interpolate() 30 times a second (heartbeat runs at approximately 30 hz), when you should preferrably only call it once.
Since the object (the ball/target/whatever) moves, you probably shouldn't be using :Interpolate() at all. It would be preferrable to set the Camera's CoordinateFrame
every frame (RenderStepped).
Anyway, here's my version of your second script, with your comments removed and my comments added.
local player = game.Players.LocalPlayer local functions = require(game.Workspace.CoreFunctions) local specBall = nil local runService = game:GetService("RunService") wait(.5) local ball = functions.findBall(player) while ball == nil do wait() ball = functions.findBall(player) -- you may want to retry looking for the ball every wait() end local cam = game.Workspace.CurrentCamera cam.CameraType = "Scriptable" --cam.CameraSubject = ball -- CameraSubject (along with Focus) is useless when the CameraType is set to "Scriptable." cam.CoordinateFrame = CFrame.new(ball.Position + Vector3.new(0,50,0), ball.Position) -- fixed. This way, the camera starts 50 studs above the ball, looking at the ball already --cam.Focus = CFrame.new(ball.Position) -- ditto local target = script:WaitForChild("CamTarget") local CurrentTarget = target.Value == "ball" and ball or functions.findBall(game.Players:FindFirstChild(target.Value)) -- sets the camera's "focus" for the first time target.Changed:connect(function(val) -- update the camera's "focus" when the target is changed CurrentTarget = val == "ball" and ball or functions.findBall(game.Players:FindFirstChild(val)) end) function UpdateCamera(dt) -- dt is a commmon programming idiom for "Delta Time", the time elapsed between the last frame and the current frame. It's not useful in this case, however. if not CurrentTarget then return end -- make sure CurrentTarget is actually there or else the script will error local campos = cam.CoordinateFrame.p:Lerp(CurrentTarget.Position + Vector3.new(0, 50, 0), 0.10) -- every frame, the camera is a tenth of the way closer to the target. -- Since RenderStepped is 60 hz, the transition should be smooth and would take less than a second. cam.CoordinateFrame = CFrame.new(campos, CurrentTarget.Position) -- sets the camera's CoordinateFrame end runService.RenderStepped:connect(UpdateCamera) -- alternatively, you can use :BindToRenderStepped()