How do I make a moving camera based on the mouse position

I was wondering how you would make something similar to the camera affect in Vesteria.

Thank you.

8 Likes

Firstly, I know I’m spoon-feeding, but that’s because I want to. It saves us both time :wink:.

What you need to know is an origin CFrame for the camera - the CFrame which will be the starting point and pointing towards the menu’s background scene, and you’ll need a float for both X and Y within the range [-0.5, 0.5] used to indicate the mouse’s position on the screen where all the way to the left on the X axis would be -0.5 and all the way to the right would be 0.5.

Why? I’ll show you right away…

--[[

	:Enable() -- Enables the menu camera

	:Disable() -- Disables the menu camera

--]]

local MenuCamera = {
	Camera = workspace.CurrentCamera;
	CF0 = workspace.CameraPart.CFrame; -- origin CFrame based on an invisible Part instance which is used to easily position the camera in Studio

	-- These max values determine how much the camera will rotate based on the mouse's position
	MaxXRotation = 10; -- Degrees, accounts for both negative and positive directions.
	MaxYRotation = 10; -- Degrees, accounts for both negative and positive directions
}

local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()

function MenuCamera.Enable(self)
	if self.Connection then
		self.Connection:Disconnect() -- Disconnect from the Mouse.Move event, if exists
	end
	
	self.Camera.CameraType = Enum.CameraType.Scriptable -- Set the CameraType to scriptable
	
	local function MouseMove()
		local XFloat = -0.5 + Mouse.X / self.Camera.ViewportSize.X
		local YFloat = -0.5 + Mouse.Y / self.Camera.ViewportSize.Y
		
		local CF = self.CF0 * CFrame.fromOrientation(
			math.rad(self.MaxYRotation * -YFloat)
			, math.rad(self.MaxXRotation * -XFloat)
			, 0
		)
		
		self.Camera.CFrame = CF
	end
	
	self.Connection = Mouse.Move:Connect(MouseMove)
	
	MouseMove()
end

function MenuCamera.Disable(self)
	if self.Connection then
		self.Connection:Disconnect() -- Disconnect from the Mouse.Move event, if exists
	end
	
	self.Camera.CameraType = Enum.CameraType.Custom -- Set the CameraType back to default
end

return MenuCamera

This is a module, you can think of it as a class actually, required by a local script, wherever you need it.

17 Likes

Holy crap, thanks for the detailed description. I’ll check that out right away.

I have 2 quick questions. What do I return for “Self”, and where should the scripts be placed.

Edit: Nevermind, got both of those figured out, although I’m getting this error.
image

	if self.Connection then
		self.Connection:Disconnect() -- Disconnect from the Mouse.Move event, if exists
	end

Do you know how to fix it?

Fun fact: don’t use . as calling the function. Instead, use : because for example, if you use MenuCamera:Enable, a keyword called self will automatically be inserted inside the scope, so you don’t have to create an argument called self, the code will handle this.

Hey, yes, it’s because you didn’t use the API I provided at the top and probably did what @ItzMeZeus_IGotHacked mentioned - . to call a function instead of the provided example where you use : as self would automatically pass through as an argument so self would not be nil.

I noticed you marked your own reply to my post as the solution, is that fair?

1 Like

Oops. I didn’t mean to. I though it made it your post.

Hey! I’m sorry for reviving this old topic, but I don’t really know how to make it work. It doesn’t give any errors or anything, just doesn’t work (camera stays as normal). Also tried doing :Enable() but doesn’t seem to work either.

Local script:

Thank you for reading!

Hey, :Enable()/:Disable() would be correct usage. I see two problems here:

  1. The module should be part of ReplicatedStorage or similar, or the script of which it’s being required for structural reasons.
  2. I’m assuming this piece of code is in a localscript in StarterCharacterScripts, which means that player.CharacterAdded will never fire, thus :Enable() will never be called. Try StarterPlayerScripts.

Correct me if I’m wrong though

1 Like

Still not working (also tried :Enable instead of .Enable)

  1. Moved module script to ReplicatedStorage.

  2. Moved LocalScript to StarterPlayerScripts.

image

Thank you for replying!

Here’s fixed version if you want.
Remember to name your camera part: “CameraPart”

--[[

	:Enable() -- Enables the menu camera

	:Disable() -- Disables the menu camera

--]]

local MenuCamera = {
	Camera = workspace.CurrentCamera;
	CF0 = workspace.CameraPart.CFrame; -- origin CFrame based on an invisible Part instance which is used to easily position the camera in Studio

	-- These max values determine how much the camera will rotate based on the mouse's position
	MaxXRotation = 10; -- Degrees, accounts for both negative and positive directions.
	MaxYRotation = 10; -- Degrees, accounts for both negative and positive directions
}

local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()

function MenuCamera.new()
	local self = setmetatable(MenuCamera, {})
	--//
	return self
end

function MenuCamera:Enable()
	if self.Connection then
		self.Connection:Disconnect() -- Disconnect from the Mouse.Move event, if exists
	end

	self.Camera.CameraType = Enum.CameraType.Scriptable -- Set the CameraType to scriptable

	local function MouseMove()
		local XFloat = -0.5 + Mouse.X / self.Camera.ViewportSize.X
		local YFloat = -0.5 + Mouse.Y / self.Camera.ViewportSize.Y

		local CF = self.CF0 * CFrame.fromOrientation(
			math.rad(self.MaxYRotation * -YFloat)
			, math.rad(self.MaxXRotation * -XFloat)
			, 0
		)

		self.Camera.CFrame = CF
	end

	self.Connection = Mouse.Move:Connect(MouseMove)

	MouseMove()
end

function MenuCamera:Disable()
	if self.Connection then
		self.Connection:Disconnect() -- Disconnect from the Mouse.Move event, if exists
	end

	self.Camera.CameraType = Enum.CameraType.Custom -- Set the CameraType back to default
end

return MenuCamera

How to use:

local Module = require(script.Cam)

Module = Module.new()
Module:Enable()
3 Likes