Make classic camera move & rotate relative to object

I want to make a camera control system that works essentially the same as the default one, but moves and rotates relative to an object (a vehicle) rather than the world.

Is there an easy way to do this whilst keeping the default camera controls - panning, zooming, etc and not having to rewrite it myself?

3 Likes

So pretty easy

Just set the CameraSubject to whatever your heart desires and have the CameraType as Enum.CameraType.Custom

1 Like

I already do that.

That makes the camera move relative to the object, but not rotate with it.

I want the camera to hold it’s relative angular offset and rotate when you turn the object.

Try using Enum.CameraType.Attach

Attach is closer but it doesn’t let the player pan the camera left and right.

Well Attach doesn’t allow you to pan left and right because its left/right pan angles are set to match the CameraSubject’s angles. You could try using Enum.CameraType.Follow then

1 Like

None of the existing CameraTypes handle my case. My question was how to best go about creating new camera behavior whilst retaining most of the old - since I only needed to make a minor change. I should’ve made my question clearer.

I decided to just fork the existing control scripts and make them reference value offsets from my own code.

3 Likes

You can somewhat easily adjust the already made core scripts to do what you’re trying to do.

Focusing on the classic camera since it’s the default:

-- last lookVector is an object space lookVector that we store and then convert as opposed to using the camera's world space lookVector
local newLookVector = self:CalculateNewLookVector(self.lastLookVector)
self.rotateInput = ZERO_VECTOR2

local lastHit = self.lastHit;
local hit = getStandingOn(humanoid) or FAKE_ORIGIN; -- fake origin is basically a fake object with CFrame = CFrame.new()
local rotation = hit.CFrame - hit.CFrame.p;

-- acount for the rotation of the previous object we were standing on
if (lastHit and lastHit ~= hit) then
	local oldRotation = lastHit.CFrame - lastHit.CFrame.p;
	newLookVector = rotation:inverse() * oldRotation * newLookVector;
end

-- adjust the look vector by the rotation of the object we are standing on
newCameraCFrame = CFrame.new(cameraFocusP - (zoom * (rotation * newLookVector)), cameraFocusP)

-- update the values for next frame
self.lastHit = hit;
self.lastLookVector = newLookVector;

This gives us the difference between this:

And what you want. This:

It also has the added benefit of working on things that aren’t vehicles of course!

You can see how the code comes together more fully here:
relative camera.rbxl (229.3 KB)

Hope this helped! Enjoy!

34 Likes

This is exactly what I needed and more. Thanks so much! :smile:

3 Likes

Bumping this thread given that camera module scripts have been updated in the last four years and the classic script is significantly different (and a lot shorter) - what would the modern equivalent of the above be?

On a side note, I’m really surprised it isn’t already built into the platform!

1 Like