Help With A Ball Camera Script

  1. What do you want to achieve?
    I would like to create a ball camera script. A script that allows the player to constantly look at the ball while also having the camera behind them.

Something like this:
RocketLeagueGif
Near the end of the gif the camera is changed so it’s always looking at the ball while also being behind the car.

  1. What is the issue?
    I’m not sure what math I would have to do, or how I should go about the CFraming.

I’m not asking for a script rather if I were to use RunService.RenderStepped what would the CFraming consist of or how would I make the camera follow the ball while also being behind the Character.

I’m not completely sure if this will work properly, but you can use .fromMatrix():

local camera = workspace.CurrentCamera
local ball = -- ball

local upVector = Vector3.new(0, 1, 0)

function lookAt(pos, look)
    local forwardVector = (pos - look).Unit
    local rightVector = forwardVector:Cross(upVector)
    local upVector = rightVector:Cross(forwardVector)
    return CFrame.fromMatrix(pos, rightVector, upVector)
end

camera.CFrame = lookAt(camera.CFrame.Position, ball.Position)

I’m pretty sure this will keep the camera in the same position, but just orient it so it’s looking at the ball.

2 Likes

Thanks for putting this out here, I’m going to try it out and see if theres anything I may be able to do with this any further.

I just realized that this will make the camera look at the ball even if it’s in the air (above the character’s height by a certain amount) which might make the character itself go out of view. You can fix this by removing the Y portion of the new CFrame.

1 Like

I tested your code and it seems a bit finicky.
This should work a bit better:

game:GetService("RunService").RenderStepped:Connect(function()
	Camera.CFrame = CFrame.new(Camera.CFrame.Position, ball.Position)
end)
1 Like

CFrame.new(pos, look) is deprecated, that’s why I used fromMatrix() instead. Also you should use :BindToRenderStep() instead, because then you can set the priority to Enum.RenderPriority.Camera.Value.

1 Like

Is it really? I guess I need to look into fromMatrix() now lol

Are you recreating rocket league? That’s a really cool game. I have an idea for how you can use this camera mechanic:

local RunService = game:GetService("RunService")
local Camera = workspace.CurrentCamera

local ball = -- ball
local priority = Enum.RenderPriority.Camera.Value
local upVector = Vector3.new(0, 1, 0)

function lookAt(pos, look)
    local forwardVector = (pos - look).Unit
    local rightVector = forwardVector:Cross(upVector)
    local upVector = rightVector:Cross(forwardVector)
    return CFrame.fromMatrix(pos, rightVector, upVector)
end

RunService:BindToRenderStep("NewCamera", priority, function()
    local onScreen, _ = Camera:WorldToViewportPoint(ball.Position)
    if not onScreen then
        lookAt(camera.CFrame.Position, ball.Position)
    end
end)

I used Camera:WorldToViewportPoint() to see if it’s on screen, and if it isn’t, move the camera to face the ball. This should make the camera work normally if the ball is already on the player’s screen.

1 Like

Sorry no. Though that would be cool, what I’m really doing is adding to my current project which is most certainly a sport game just not anything related to Rocket League.
Thanks for helping me too.