-
What do you want to achieve?
I have used someone else Over the Shoulder camera module (as I am not great at camera manipulation) but I have added in my own code to have a target lock on system which works really well. However, when I unlock from a target I want the camera CFrame to remain where it is but then the player can move their camera freely. -
What is the issue?
https://gyazo.com/177b07f313190561a085537ab4c98798
As you can see when I unlock from the target it returns to it’s previous CFrame before locking on to a target. Which during gameplay can be very jarring. I am unsure on how to resolve this. -
What solutions have you tried so far?
I have tried a couple things like setting up a variable that stores the camera CFrame when unlocking from the target and that didn’t work. The code below isn’t the full CameraModule script but just the main 3 functions that control the camera and lock on function.
-- Main function which modifies the Camera
local function updateCamera()
local currentCamera = workspace.CurrentCamera
local activeCameraSettings = OTS_Cam.CameraSettings[CameraMode]
currentCamera.CameraType = Enum.CameraType.Scriptable
--// Moves camera based on Input //--
local inputDelta = getDelta()
OTS_Cam.HorizontalAngle -= inputDelta.X/currentCamera.ViewportSize.X
OTS_Cam.VerticalAngle -= inputDelta.Y/currentCamera.ViewportSize.Y
OTS_Cam.VerticalAngle = math.rad(math.clamp(math.deg(OTS_Cam.VerticalAngle), VERTICAL_ANGLE_LIMITS.Min, VERTICAL_ANGLE_LIMITS.Max))
----
local humanoidRootPart = Character ~= nil and Character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then -- Disable if Player dies
currentCamera.FieldOfView = Lerp(
currentCamera.FieldOfView,
activeCameraSettings.Field_Of_View,
activeCameraSettings.Lerp_Speed
)
--// Address shoulder direction //--
local offset = activeCameraSettings.Offset
offset = Vector3.new(offset.X * OTS_Cam.ShoulderDirection, offset.Y, offset.Z)
----
--// Calculate new camera cframe //--
local newCameraCFrame = CFrame.new(humanoidRootPart.Position) *
CFrame.Angles(0, OTS_Cam.HorizontalAngle, 0) *
CFrame.Angles(OTS_Cam.VerticalAngle, 0, 0) *
CFrame.new(offset)
newCameraCFrame = currentCamera.CFrame:Lerp(newCameraCFrame, activeCameraSettings.Lerp_Speed)
----
--// 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:GetComponents()
newCameraCFrame = CFrame.new(obstructionPosition.x, obstructionPosition.y, obstructionPosition.z, r00, r01, r02, r10, r11, r12, r20, r21, r22)
end
----
--// Address character alignment //--
if OTS_Cam.IsCharacterAligned == true then
local newHumanoidRootPartCFrame = CFrame.new(humanoidRootPart.Position) *
CFrame.Angles(0, OTS_Cam.HorizontalAngle, 0)
humanoidRootPart.CFrame = humanoidRootPart.CFrame:Lerp(newHumanoidRootPartCFrame, activeCameraSettings.Lerp_Speed/2)
end
----
currentCamera.CFrame = currentCamera.CFrame:Lerp(newCameraCFrame, activeCameraSettings.Lerp_Speed)
else
OTS_Cam.Disable()
CameraWasEnabled = true
end
end
function lockOnToTarget()
local humanoidRootPart = Character:FindFirstChild("HumanoidRootPart", true)
local combatSystem = Character:FindFirstChild("CombatSystem", true)
local currentCamera = workspace.CurrentCamera
local activeCameraSettings = OTS_Cam.CameraSettings[CameraMode]
if (humanoidRootPart and combatSystem) then
local target = combatSystem.CombatProperties:FindFirstChild("Target")
--// Address shoulder direction //--
local offset = activeCameraSettings.Offset
offset = Vector3.new(offset.X * OTS_Cam.ShoulderDirection, offset.Y, offset.Z)
----
local cameraCFrame = CFrame.new(humanoidRootPart.Position, target.Value.PrimaryPart.Position) * CFrame.new(offset.X, offset.Y, offset.Z)
local newCameraCFrame = currentCamera.CFrame:Lerp(cameraCFrame, activeCameraSettings.Lerp_Speed)
--// Raycast for obstructions //--
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Character}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
local raycastResult = workspace:Raycast(
humanoidRootPart.Position,
newCameraCFrame.Position - 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:GetComponents()
newCameraCFrame = CFrame.new(obstructionPosition.x, obstructionPosition.y, obstructionPosition.z, r00, r01, r02, r10, r11, r12, r20, r21, r22)
end
----
--// Address character alignment //--
if OTS_Cam.IsCharacterAligned == true then
local newHumanoidRootPartCFrame = CFrame.lookAt(humanoidRootPart.Position, target.Value.PrimaryPart.Position)
humanoidRootPart.CFrame = humanoidRootPart.CFrame:Lerp(newHumanoidRootPartCFrame, activeCameraSettings.Lerp_Speed/2)
end
----
currentCamera.CameraType = Enum.CameraType.Scriptable
currentCamera.CFrame = currentCamera.CFrame:Lerp(CFrame.new(newCameraCFrame.Position, target.Value.PrimaryPart.Position), activeCameraSettings.Lerp_Speed)
end
end
function OTS_Cam.Enable()
OTS_Cam.IsEnabled = true
CameraWasEnabled = true
configureStateForEnabled()
RunService:BindToRenderStep(
"OTS_CAMERA",
Enum.RenderPriority.Camera.Value - 10,
function()
if OTS_Cam.IsEnabled == true then
local combatSystem = Character:FindFirstChild("CombatSystem")
if (combatSystem) then
local target = combatSystem.CombatProperties:FindFirstChild("Target")
local humanoidRootPart = Character:FindFirstChild("HumanoidRootPart", true)
if (target and target.Value) then
if ((humanoidRootPart.Position - target.Value.PrimaryPart.Position).Magnitude < 30 and target.Value.Humanoid.Health > 0 and Character.Humanoid.Health > 0) then
lockOnToTarget()
else
updateTargetEvent:FireServer(nil)
OTS_Cam.SetCharacterAlignment(false)
end
else
updateCamera()
end
end
end
end
)
end
----