I am using a camera system for my game. When a player equips a tool, the camera system will enable. When they unequip the tool, it will change back to the default Roblox camera system. However, I noticed when a player dies with the tool equipped, and never unequips it after death, the camera will stay where the player died. I am relatively new to coding and I can’t seem to figure out a fix.
(LocalScript in the tool)
local OTS_CAMERA_SYSTEM = require(game.ReplicatedStorage.Modules["OTS Camera System"])
script.Parent.Equipped:Connect(function(mouse)
OTS_CAMERA_SYSTEM:Enable()
OTS_CAMERA_SYSTEM:SetCharacterAlignment(true)
end)
script.Parent.Unequipped:Connect(function()
OTS_CAMERA_SYSTEM:Disable()
end)
(ModuleScript in ReplicatedStorage)
local CLASS = {}
--// SERVICES //--
local PLAYERS_SERVICE = game:GetService("Players")
local RUN_SERVICE = game:GetService("RunService")
local USER_INPUT_SERVICE = game:GetService("UserInputService")
--// CONSTANTS //--
local LOCAL_PLAYER = PLAYERS_SERVICE.LocalPlayer
local MOUSE = LOCAL_PLAYER:GetMouse()
local UPDATE_UNIQUE_KEY = "OTS_CAMERA_SYSTEM_UPDATE"
--// VARIABLES //--
--// CONSTRUCTOR //--
function CLASS.new()
--// Events //--
local activeCameraSettingsChangedEvent = Instance.new("BindableEvent")
local characterAlignmentChangedEvent = Instance.new("BindableEvent")
local mouseStepChangedEvent = Instance.new("BindableEvent")
local shoulderDirectionChangedEvent = Instance.new("BindableEvent")
local enabledEvent = Instance.new("BindableEvent")
local disabledEvent = Instance.new("BindableEvent")
----
local dataTable = setmetatable(
{
--// Properties //--
SavedCameraSettings = nil,
SavedMouseBehavior = nil,
ActiveCameraSettings = nil,
HorizontalAngle = 0,
VerticalAngle = 0,
ShoulderDirection = 1,
----
--// Flags //--
IsCharacterAligned = false,
IsMouseSteppedIn = false,
IsEnabled = false,
----
--// Events //--
ActiveCameraSettingsChangedEvent = activeCameraSettingsChangedEvent,
ActiveCameraSettingsChanged = activeCameraSettingsChangedEvent.Event,
CharacterAlignmentChangedEvent = characterAlignmentChangedEvent,
CharacterAlignmentChanged = characterAlignmentChangedEvent.Event,
MouseStepChangedEvent = mouseStepChangedEvent,
MouseStepChanged = mouseStepChangedEvent.Event,
ShoulderDirectionChangedEvent = shoulderDirectionChangedEvent,
ShoulderDirectionChanged = shoulderDirectionChangedEvent.Event,
EnabledEvent = enabledEvent,
Enabled = enabledEvent.Event,
DisabledEvent = disabledEvent,
Disabled = disabledEvent.Event,
----
--// Configurations //--
VerticalAngleLimits = NumberRange.new(-75, 75),
----
--// Camera Settings //--
CameraSettings = {
DefaultShoulder = {
FieldOfView = 70,
Offset = Vector3.new(2, 2, 7),
Sensitivity = 10,
LerpSpeed = 1
},
ZoomedShoulder = {
FieldOfView = 65 ,
Offset = Vector3.new(2, 2, 4),
Sensitivity = 5.5,
LerpSpeed = 1
}
}
----
},
CLASS
)
local proxyTable = setmetatable(
{
},
{
__index = function(self, index)
return dataTable[index]
end,
__newindex = function(self, index, newValue)
dataTable[index] = newValue
end
}
)
return proxyTable
end
--// FUNCTIONS //--
local function Lerp(x, y, a)
return x + (y - x) * a
end
--// METHODS //--
--// //--
function CLASS:SetActiveCameraSettings(cameraSettings)
assert(cameraSettings ~= nil, "OTS Camera System Argument Error: Argument 1 nil or missing")
assert(typeof(cameraSettings) == "string", "OTS Camera System Argument Error: string expected, got " .. typeof(cameraSettings))
assert(self.CameraSettings[cameraSettings] ~= nil, "OTS Camera System Argument Error: Attempt to set unrecognized camera settings " .. cameraSettings)
if (self.IsEnabled == false) then
warn("OTS Camera System Logic Warning: Attempt to change active camera settings without enabling OTS camera system")
return
end
self.ActiveCameraSettings = cameraSettings
self.ActiveCameraSettingsChangedEvent:Fire(cameraSettings)
end
function CLASS:SetCharacterAlignment(aligned)
assert(aligned ~= nil, "OTS Camera System Argument Error: Argument 1 nil or missing")
assert(typeof(aligned) == "boolean", "OTS Camera System Argument Error: boolean expected, got " .. typeof(aligned))
if (self.IsEnabled == false) then
warn("OTS Camera System Logic Warning: Attempt to change character alignment without enabling OTS camera system")
return
end
self.IsCharacterAligned = aligned
self.CharacterAlignmentChangedEvent:Fire(aligned)
end
function CLASS:SetMouseStep(steppedIn)
assert(steppedIn ~= nil, "OTS Camera System Argument Error: Argument 1 nil or missing")
assert(typeof(steppedIn) == "boolean", "OTS Camera System Argument Error: boolean expected, got " .. typeof(steppedIn))
if (self.IsEnabled == false) then
warn("OTS Camera System Logic Warning: Attempt to change mouse step without enabling OTS camera system")
return
end
self.IsMouseSteppedIn = steppedIn
self.MouseStepChangedEvent:Fire(steppedIn)
if (steppedIn == true) then
USER_INPUT_SERVICE.MouseBehavior = Enum.MouseBehavior.LockCenter
else
USER_INPUT_SERVICE.MouseBehavior = Enum.MouseBehavior.Default
end
end
function CLASS:SetShoulderDirection(shoulderDirection)
assert(shoulderDirection ~= nil, "OTS Camera System Argument Error: Argument 1 nil or missing")
assert(typeof(shoulderDirection) == "number", "OTS Camera System Argument Error: number expected, got " .. typeof(shoulderDirection))
assert(math.abs(shoulderDirection) == 1, "OTS Camera System Argument Error: Attempt to set unrecognized shoulder direction " .. shoulderDirection)
if (self.IsEnabled == false) then
warn("OTS Camera System Logic Warning: Attempt to change shoulder direction without enabling OTS camera system")
return
end
self.ShoulderDirection = shoulderDirection
self.ShoulderDirectionChangedEvent:Fire(shoulderDirection)
end
----
--// //--
function CLASS:SaveCameraSettings()
local currentCamera = workspace.CurrentCamera
self.SavedCameraSettings = {
FieldOfView = currentCamera.FieldOfView,
CameraSubject = currentCamera.CameraSubject,
CameraType = currentCamera.CameraType
}
end
function CLASS:LoadCameraSettings()
local currentCamera = workspace.CurrentCamera
for setting, value in pairs(self.SavedCameraSettings) do
currentCamera[setting] = value
end
end
----
--// //--
function CLASS:Update()
local currentCamera = workspace.CurrentCamera
local activeCameraSettings = self.CameraSettings[self.ActiveCameraSettings]
--// Address mouse behavior and camera type //--
if (self.IsMouseSteppedIn == true) then
USER_INPUT_SERVICE.MouseBehavior = Enum.MouseBehavior.LockCenter
else
USER_INPUT_SERVICE.MouseBehavior = Enum.MouseBehavior.Default
end
currentCamera.CameraType = Enum.CameraType.Scriptable
---
--// Address mouse input //--
local mouseDelta = USER_INPUT_SERVICE:GetMouseDelta() * activeCameraSettings.Sensitivity
self.HorizontalAngle -= mouseDelta.X/currentCamera.ViewportSize.X
self.VerticalAngle -= mouseDelta.Y/currentCamera.ViewportSize.Y
self.VerticalAngle = math.rad(math.clamp(math.deg(self.VerticalAngle), self.VerticalAngleLimits.Min, self.VerticalAngleLimits.Max))
----
local character = LOCAL_PLAYER.Character
local humanoidRootPart = (character ~= nil) and (character:FindFirstChild("HumanoidRootPart"))
if (humanoidRootPart ~= nil) then
--// Lerp field of view //--
currentCamera.FieldOfView = Lerp(
currentCamera.FieldOfView,
activeCameraSettings.FieldOfView,
activeCameraSettings.LerpSpeed
)
----
--// Address shoulder direction //--
local offset = activeCameraSettings.Offset
offset = Vector3.new(offset.X * self.ShoulderDirection, offset.Y, offset.Z)
----
--// Calculate new camera cframe //--
local newCameraCFrame = CFrame.new(humanoidRootPart.Position) *
CFrame.Angles(0, self.HorizontalAngle, 0) *
CFrame.Angles(self.VerticalAngle, 0, 0) *
CFrame.new(offset)
newCameraCFrame = currentCamera.CFrame:Lerp(newCameraCFrame, activeCameraSettings.LerpSpeed)
----
--// Raycast for obstructions //--
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {character}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(
humanoidRootPart.Position,
newCameraCFrame.p - humanoidRootPart.Position,
raycastParams
)
----
--// Address obstructions if any //--
if (raycastResult ~= nil) then
local obstructionDisplacement = (raycastResult.Position - humanoidRootPart.Position)
local obstructionPosition = humanoidRootPart.Position + (obstructionDisplacement.Unit * (obstructionDisplacement.Magnitude - 0.1))
local x,y,z,r00,r01,r02,r10,r11,r12,r20,r21,r22 = newCameraCFrame:components()
newCameraCFrame = CFrame.new(obstructionPosition.x, obstructionPosition.y, obstructionPosition.z, r00, r01, r02, r10, r11, r12, r20, r21, r22)
end
----
--// Address character alignment //--
if (self.IsCharacterAligned == true) then
local newHumanoidRootPartCFrame = CFrame.new(humanoidRootPart.Position) *
CFrame.Angles(0, self.HorizontalAngle, 0)
humanoidRootPart.CFrame = humanoidRootPart.CFrame:Lerp(newHumanoidRootPartCFrame, activeCameraSettings.LerpSpeed/2)
end
----
currentCamera.CFrame = newCameraCFrame
else
self:Disable()
end
end
function CLASS:ConfigureStateForEnabled()
self:SaveCameraSettings()
self.SavedMouseBehavior = USER_INPUT_SERVICE.MouseBehavior
self:SetActiveCameraSettings("DefaultShoulder")
self:SetCharacterAlignment(false)
self:SetMouseStep(true)
self:SetShoulderDirection(1)
--// Calculate angles //--
local cameraCFrame = workspace.CurrentCamera.CFrame
local x, y, z = cameraCFrame:ToOrientation()
local horizontalAngle = y
local verticalAngle = x
----
self.HorizontalAngle = horizontalAngle
self.VerticalAngle = verticalAngle
end
function CLASS:ConfigureStateForDisabled()
self:LoadCameraSettings()
USER_INPUT_SERVICE.MouseBehavior = self.SavedMouseBehavior
self:SetActiveCameraSettings("DefaultShoulder")
self:SetCharacterAlignment(false)
self:SetMouseStep(false)
self:SetShoulderDirection(1)
self.HorizontalAngle = 0
self.VerticalAngle = 0
end
function CLASS:Enable()
assert(self.IsEnabled == false, "OTS Camera System Logic Error: Attempt to enable without disabling")
self.IsEnabled = true
self.EnabledEvent:Fire()
self:ConfigureStateForEnabled()
RUN_SERVICE:BindToRenderStep(
UPDATE_UNIQUE_KEY,
Enum.RenderPriority.Camera.Value - 10,
function()
if (self.IsEnabled == true) then
self:Update()
end
end
)
end
function CLASS:Disable()
assert(self.IsEnabled == true, "OTS Camera System Logic Error: Attempt to disable without enabling")
self:ConfigureStateForDisabled()
self.IsEnabled = false
self.DisabledEvent:Fire()
RUN_SERVICE:UnbindFromRenderStep(UPDATE_UNIQUE_KEY)
end
----
--// INSTRUCTIONS //--
CLASS.__index = CLASS
local singleton = CLASS.new()
USER_INPUT_SERVICE.InputBegan:Connect(function(inputObject, gameProcessedEvent)
if (gameProcessedEvent == false) and (singleton.IsEnabled == true) then
if (inputObject.KeyCode == Enum.KeyCode.Q) then
singleton:SetShoulderDirection(1)
elseif (inputObject.KeyCode == Enum.KeyCode.E) then
singleton:SetShoulderDirection(1)
end
if (inputObject.UserInputType == Enum.UserInputType.MouseButton2) then
singleton:SetActiveCameraSettings("ZoomedShoulder")
end
if (inputObject.KeyCode == Enum.KeyCode.Equals) then
if (singleton.IsEnabled == true) then
singleton:SetMouseStep(not singleton.IsMouseSteppedIn)
end
end
end
end)
USER_INPUT_SERVICE.InputEnded:Connect(function(inputObject, gameProcessedEvent)
if (gameProcessedEvent == false) and (singleton.IsEnabled == true) then
if (inputObject.UserInputType == Enum.UserInputType.MouseButton2) then
singleton:SetActiveCameraSettings("DefaultShoulder")
end
end
end)
return singleton