Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
2

How do I prevent a scriptable camera from being laggy? Please Help

Asked by 8 years ago

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

1
Any chance that the lag is not caused by the camera? XAXA 1569 — 8y
0
I don't think it's the camera's fault, it's just that the camera just starts falling behind for some reason. I think there might be something else causing that. SolarFloss 40 — 8y

1 answer

Log in to vote
1
Answered by
XAXA 1569 Moderation Voter
8 years ago

It looks like you want the Camera to hover 50 studs above the target. If so...

  1. The "angle" of the CFrame doesn't matter when you're using :Interpolate() -- only its position is used.

  2. You're calling :Interpolate() 30 times a second (heartbeat runs at approximately 30 hz), when you should preferrably only call it once.

  3. 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()
0
Alright. I'll try it out and get back to you. Thank you so much though. SolarFloss 40 — 8y
0
Okay so I tried out what you said and it didn't work, but I did change some things. I'm keeping the interpolate, but I got rid of the renderStepped. I was thinking that using a renderStepped for calling the interpolation was a bit much. So now it's "while wait(.05) do". It looks like that got rid of some of the choppyness. I noticed that if I disable the camera script while there was lag so the ca SolarFloss 40 — 8y
0
Did my script not run at all or did it just not solve your lag problem? XAXA 1569 — 8y
0
It did run but it acted a little weird if the ball is moving too fast. The camera would completely "flip" kinda. The lag was still there though SolarFloss 40 — 8y
View all comments (4 more)
0
I understand. Thanks for getting back to me. XAXA 1569 — 8y
0
Try this instead (remove the campos variable since it's unnecessary, replace line 30 from my original script): cam.CoordinateFrame = CFrame.new(CurrentTarget.Position + Vector3.new(0, 50, 0), CurrentTarget.Position) XAXA 1569 — 8y
1
Oh sorry I didn't see your message. I don't think I'm going to try it, but only because I've come to the conclusion that the lag isn't from the camera. Thanks for everything though. I have implemented some of the things that you suggested. SolarFloss 40 — 8y
0
ok, thanks. XAXA 1569 — 8y
Ad

Answer this question