I’m attempting to make an over-shoulder camera system that, upon equipping a tool, will forcibly orient their character’s root part in the direction the player’s camera is facing. While I have the OTS camera logic working (sort of), I’m getting an odd effect when the player does equip a tool.
I’ve tried using the following code, with varying results. The most common result, however, is that the player’s character either is side-on to the camera, or is facing towards it, instead of what I’m trying to go for. It’s incredibly inconsistent.
The script (collapsed for convenience)
Note: this script is (obviously) unfinished, there’s still some optimizations to do
-- Services
local RunService = game:GetService("RunService")
local PlrService = game:GetService("Players")
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")
-- Primary Values
local Player = PlrService.LocalPlayer
local MyHumanoid:Humanoid = nil
local MyRootPart:BasePart = nil
-- Secondary Values
local CurrentCamera = workspace.CurrentCamera
local CameraOffset = Vector3.new(1.65, 1.8, 4.7)
local CameraAngleX = 0
local CameraAngleY = 0
local ToolCounter = 0
local HasTool = false
-- Functions
function Refocus(actionName, inputState, inputObject)
-- Lock and hide mouse icon on input began
if inputState == Enum.UserInputState.Begin and HasTool == true and ToolCounter > 0 then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
end
end
function ItemAdded(NewItem:Instance)
-- Enable OTS camera mode if player is holding tools
if NewItem:IsA("Tool") then
ToolCounter += 1
if HasTool == false and ToolCounter > 0 then
HasTool = true
MyRootPart.CFrame = CFrame.lookAt(MyRootPart.Position,MyRootPart.Position+CurrentCamera.CFrame.LookVector)
while CurrentCamera.CameraType ~= Enum.CameraType.Scriptable do
CurrentCamera.CameraType = Enum.CameraType.Scriptable
end
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
MyHumanoid.AutoRotate = false
end
end
end
function ItemRemoved(OldItem:Instance)
-- Disable OTS camera mode if player is no longer holding tools
if OldItem:IsA("Tool") then
ToolCounter -= 1
wait()
if ToolCounter <= 0 then
HasTool = false
while CurrentCamera.CameraType ~= Enum.CameraType.Custom do
CurrentCamera.CameraType = Enum.CameraType.Custom
end
UserInputService.MouseBehavior = Enum.MouseBehavior.Default
MyHumanoid.AutoRotate = true
end
end
end
function CharacterAdded(NewCharacter:Model)
MyHumanoid = NewCharacter:WaitForChild("Humanoid")
MyRootPart = NewCharacter:WaitForChild("HumanoidRootPart")
CameraAngleX = 0
CameraAngleY = 0
local function playerInput(actionName, inputState, inputObject)
-- Calculate camera/player rotation on input change
if inputState == Enum.UserInputState.Change then
CameraAngleX = CameraAngleX - inputObject.Delta.X
-- Reduce vertical mouse/touch sensitivity and clamp vertical axis
CameraAngleY = math.clamp(CameraAngleY-inputObject.Delta.Y*0.4, -75, 75)
if HasTool == true and CurrentCamera.CameraType == Enum.CameraType.Scriptable then
-- Rotate root part CFrame by X delta
MyRootPart.CFrame = MyRootPart.CFrame * CFrame.Angles(0, math.rad(-inputObject.Delta.X), 0)
end
end
end
ContextActionService:BindAction("PlayerInput", playerInput, false, Enum.UserInputType.MouseMovement, Enum.UserInputType.Touch)
RunService.RenderStepped:Connect(function()
if HasTool == false or CurrentCamera.CameraType ~= Enum.CameraType.Scriptable then return false end
local startCFrame = CFrame.new((MyRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
local cameraCFrame = startCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, CameraOffset.Z))
local cameraFocus = startCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, -10000))
CurrentCamera.CFrame = CFrame.new(cameraCFrame.Position, cameraFocus.Position)
end)
NewCharacter.ChildAdded:Connect(ItemAdded)
NewCharacter.ChildRemoved:Connect(ItemRemoved)
end
-- Primary Connections
Player.CharacterAdded:Connect(CharacterAdded)
ContextActionService:BindAction("FocusControl", Refocus, false, Enum.UserInputType.Focus)
Anyone have some pointers for how to accomplish this task properly? I’ve tried using Camera:ViewportPointToRay()
as well with no desired results there either.
EDIT: Changed some Lua comments on the script because I noticed typos in them here and there. The script itself remains functionally the same.