Over the Shoulder Camera on tool Activate

Ive been trying to make it when a player activates a tool their camera keeps the current direction its pointing in.
Goes over their shoulder and the torso then points in the same position as the camera.
From there the camera and torso both follow mouse position

Ive copied roblox’s base code and played around with it:
https://developer.roblox.com/en-us/articles/Camera-manipulation

I realized that the cameraFocus variable is where the problem lies.
When I activate the tool the camera turns towards -10000 z axis. Instead of where the players current camera is facing.

I tried replacing it with the Cameras current look vector but it didnt work making the camera go wonky

If anyone could help explain if the problem is with the cameraFocus variable, and how to fix it.

Thanks

What happens if you offset the CFrame (Rotation) by 10000?

It points in the opposite direction, but the camera will zoom in all the way to where you can no longer see the character

I get it now, seems like you replicated from the script in developer hub, Which offsets the camera’s CFrame by a lot.

Is it this line here?

	local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(cameraOffset.X, cameraOffset.Y, -10000))

Try correcting it to:

local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(cameraOffset.X, cameraOffset.Y, 0))

Or remove the line itself.

Is this the result you expected?

robloxapp-20210723-0900215.wmv (2.1 MB)

Make an invisible accessory/tool where you want the camera to focus and make it focus on it. Because the player moves with that accessory/tool it will keep its focus on the player from the angle you set it to be. I find this way to be easier than starting to calculate.

What they meant is activating not equip although I think that is possible.

When setting that last value to zero it will just remove the whole offset effect

And no in the video the part thats missing is that when the player activates tool, their torso should swing around to face away from the camera.

A great example is how the players camera and torso react in mad city when you equip a weapon

Can I see the current script you have? I can try to fix it.

The issue is the -10000 z value. When the tool is activated and the function below runs it points them at the -10000 z direction of world.

After this initial turn at -10000 the script works as intended, with the mouse locked to center, torso following the mouse, and camera staying offset

When changing the value to 0 it completely removes the camera offset.

And when making it +10000 the camera goes bananas

Im trying to make it as soon as the player activates tool it makes player face toward camera (not -10000).

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetSerivce("RunService")
local ContextActionService = game:GetService("ContextActionService")

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

local Character = Player.Character
local Humanoid = Character.Humanoid
local RootPart = Character.HumanoidRootPart

local Camera = game.Workspace.CurrentCamera
local DefaultCFrame = CameraOffSet = Vector3.new(2,2.05,8)

local function OnToolActivated()
    RunService:BindToRenderStep("MouseLock", Enum.RenderPriority.Last.Value+1, function()
        UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
    end)

    Humanoid.AutoRotate = false

    local cameraAngleX = 0
    local cameraAngleY = 0

    local function playerInput(actionName, inputState, inputObject)
        if inputState == Enum.UserInputState.Change then
            cameraAngleX -= inputObject.Delta.X
            cameraAngleY = math.clamp(cameraAngleY - inputObject.Delta.Y * 0.4, -75, 75)
        end
    end

    ContextActionService:BindAction("PlayerInput",playerInput,false,Enum.UserInputType.MouseMovement,Enum.UserInputType.Touch)

    RunService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value,function() 
        local startCFrame = CFrame.new(RootPart.CFrame.Position)*CFrame.Angles(0,math.rad(cameraAngleX),0)*CFrame.Angles(math.rad(cameraAngleY),0,0)
        local cameraCFrame = startCFrame:PointToWorldSpace(CameraOffSet)
		local cameraFocus = startCFrame:PointToWorldSpace(Vector3.new(CameraOffSet.X,CameraOffSet.Y,-10000))
        Camera.CFrame = CFrame.lookAt(cameraCFrame,cameraFocus)

        local lookingCFrame = CFrame.lookAt(RootPart.Position, Camera.CFrame:PointToWorldSpace(Vector3.new(0,0,-100000)))
        RootPart.CFrame = CFrame.fromMatrix(RootPart.Position, lookingCFrame.XVector, RootPart.CFrame.YVector)
    end)
end

Quick Note: How could you get the character like that? The existing character is in workspace!

Ah was a typo, in my game script I reference the character elsewhere

I just copy/pasted the relevant portion of the code (onActivate) and filled in the variables

This is my fixed script, It even comes with it’s own deactivated event!

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local ContextActionService = game:GetService("ContextActionService")

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

Player.CharacterAdded:Connect(function(plr)
	if plr ~= nil then
		local Character = plr
		Humanoid = Character:WaitForChild("Humanoid")
		RootPart = Character:WaitForChild("HumanoidRootPart")
	end
end)

local Camera = game.Workspace.CurrentCamera
local CameraOffSet = Vector3.new(2,2.05,8)

local function OnToolActivated()
	RunService:BindToRenderStep("MouseLock", Enum.RenderPriority.Last.Value+1, function()
		UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
	end)
	
	Humanoid.AutoRotate = false

	local cameraAngleX = 0
	local cameraAngleY = 0

	local function playerInput(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Change then
			cameraAngleX -= inputObject.Delta.X
			cameraAngleY = math.clamp(cameraAngleY - inputObject.Delta.Y * 0.4, -75, 75)
		end
	end

	ContextActionService:BindAction("PlayerInput",playerInput,false,Enum.UserInputType.MouseMovement,Enum.UserInputType.Touch)

	RunService:BindToRenderStep("CameraUpdate", Enum.RenderPriority.Camera.Value,function() 
		local startCFrame = CFrame.new(RootPart.CFrame.Position)*CFrame.Angles(0,math.rad(cameraAngleX),0)*CFrame.Angles(math.rad(cameraAngleY),0,0)
		local cameraCFrame = startCFrame:PointToWorldSpace(CameraOffSet)
		local cameraFocus = startCFrame:PointToWorldSpace(Vector3.new(CameraOffSet.X,CameraOffSet.Y,-10000))
		Camera.CFrame = CFrame.lookAt(cameraCFrame,cameraFocus)
		
		RootPart.CFrame = CFrame.fromMatrix(RootPart.Position, Camera.CFrame.XVector, RootPart.CFrame.YVector)
	end)
end

local function OnToolDeactivated()
	RunService:UnbindFromRenderStep("MouseLock")
	ContextActionService:UnbindAction("PlayerInput")
	RunService:UnbindFromRenderStep("CameraUpdate")
	
	Humanoid.AutoRotate = true
end

script.Parent.Activated:Connect(OnToolActivated)
script.Parent.Deactivated:Connect(OnToolDeactivated)

What I did is that, instead of CFrame.lookat(), I made the rotation based on the camera XVector, nothing else was changed and I added RunService Unbind functions and ContextActionService UnbindAction functions for the deactivated part.

It still has the original issue.

In this image the yellow is at -10000

and as im facing the red wall if i activate the tool, left click

It swings me to face the yellow wall instead of the red. Same if i face any direction it will force me to look at the yellow all

Well I tried everything but nothing seems to work at all.

Ah yah same! Thanks for taking the time to help, if I figure it out ill update this post

This is what I know (for now):

  1. If the Camera’s CFrame of the CFrame.lookat() is greater than the Camera’s Focus, then it would increase how far it should be from the player, making the camera not be like shift lock at all.
    What it would look like? Let’s see:


    As we can see, it may look normal but it’s actually making the camera move like a ring when the player itself moves the camera.

  2. Hm, the first result doesn’t look very good, What about making the Camera CFrame the same as the Camera Focus? Let’s see:

Well those results didn’t work, even if we mirror their effects… Welp this result is the only one that looks like shiftlock except the z-axis rotation ain’t good: