Hey Developers!
Hey guys, I made a very interesting, (To me at least) Funny, working camera system. And I have chosen to open-source it in case any of you wish to use it inside of one of your games.
About the camera system:
The camera system is a very smooth tweening camera that follows your players head. I didn’t like the roblox’s form of the camera for a special puzzle game I’m making, so I decided to make a new one and happend to stubble across what I bring to you today.
Features:
- Zoom (Keybinds, R & T)
- LookLeft or LookRight (Keybinds, Q & E)
- Smooth follow
- Adjusted First Person (Realistic-ish, still funky.)
NOTICE!
The code isn’t made for anything serious, It’s a little unstable (first-person wise) and is mainly focused on being enjoyed in cool / testable games. If you wish for it to be configured for something serious please send me a message!
Setup:
Your setup should look something like this:
- The value I added (Active) it so you can chose weather or not to use the mouse feature, just toggle the active value on or off.
The location of the camera should be under your starter character scripts, or “Custom_Rig” if you happen to be using one. (Not recommended, will configure if you guys need it.)
Here is the file for installation if you don’t feel like looking over the code:
cam.rbxm (3.4 KB)
Visible features/Video:
Requested to view what the camera system has to offer, I have put it on a stream-able. Please provide feedback in the comments on anything you’d like changed, I’m available to do so.
New update log:
- Camera lock for first person. (Simply aim where you want it to lock to, then zoom all the way in.)
- Accessories cleanup. Suggested by: uhi_o
- Easier usage for everyone, forum post cleanup.
Soon to be updated:
- Shake effects
- Dampening on certain animations. (For first person.)
- Cleaner first person movement overall.
- Camera Type values adjustable by module/bool values. (Overall update)
Source code:
-- Assets:
local Locked = false
self = script.Parent
-- Services
local RunService = game:GetService("RunService")
local TS = game:GetService("TweenService")
local UIS = game:GetService("UserInputService")
-- Camera
local Camera = workspace.CurrentCamera
Camera.CameraType = Enum.CameraType.Scriptable
-- Camera Tween
local function TweenTo(Pos)
if Locked == false then
TS:Create(Camera,TweenInfo.new(2,Enum.EasingStyle.Quint,Enum.EasingDirection.Out),{CFrame = Pos * CFrame.Angles(270,math.rad(2),0)}):Play()
elseif Locked == true then
TS:Create(Camera,TweenInfo.new(.1,Enum.EasingStyle.Quint,Enum.EasingDirection.Out),{CFrame = Pos * CFrame.Angles(270,math.rad(2),0)}):Play()
end
end
-- Values
local lookRight = false
local lookLeft = false
local Default = true -- If they want to stop looking right or left.
local Zooming = true -- If they want zooming enabled.
local Y = 5
local X = 15
-- Main function
UIS.InputBegan:Connect(function(io, IsTyping)
if IsTyping then return end
-- Left:
if io.KeyCode == Enum.KeyCode.Q and lookLeft == false and lookRight == false and Locked == false then
Default = false
lookLeft = true
lookRight = false
RunService.RenderStepped:Connect(function()
if lookLeft == true and lookRight == true then
lookRight = false
TweenTo(self.Head.CFrame * CFrame.new(-5,Y,X))
elseif lookLeft == true and lookRight == false then
TweenTo(self.Head.CFrame * CFrame.new(-5,Y,X))
end
end)
elseif io.KeyCode == Enum.KeyCode.Q and lookLeft == true and lookRight == false and Locked == false then
Default = true
lookLeft = false
RunService.RenderStepped:Connect(function()
if lookLeft == false and lookRight == false then
TweenTo(self.Head.CFrame * CFrame.new(0,Y,X))
end
end)
end
-- Right:
if io.KeyCode == Enum.KeyCode.E and lookRight == false and lookLeft == false and Locked == false then
Default = false
lookLeft = false
lookRight = true
RunService.RenderStepped:Connect(function()
if lookRight == true and lookLeft == true then
lookLeft = false
TweenTo(self.Head.CFrame * CFrame.new(5,Y,X))
elseif lookRight == true and lookLeft == false then
TweenTo(self.Head.CFrame * CFrame.new(5,Y,X))
end
end)
elseif io.KeyCode == Enum.KeyCode.E and lookRight == true and lookLeft == false and Locked == false then
Default = true
lookRight = false
RunService.RenderStepped:Connect(function()
if lookRight == false and lookLeft == false then
TweenTo(self.Head.CFrame * CFrame.new(0,Y,X))
end
end)
end
-- Zoom:
if io.KeyCode == Enum.KeyCode.R then
if X <= 45 and Y <= 15 then
X = X + 15
Y = Y + 5
if X > 0 and X <= 15 and Y > 0 and Y <= 5 then
print(
"Unlocked!"
)
Locked = false
end
end
elseif io.KeyCode == Enum.KeyCode.T then
if X >= 15 and Y >= 5 then
X = X - 15
Y = Y - 5
if X == 0 and Y == 0 then
warn(
"Locked!"
)
Locked = true
end
end
end
end)
-- Mouse Settings:
RunService.RenderStepped:Connect(function()
warn(
script.Active.Value,
Locked
)
if (script.Active.Value) and not (Locked) then
require(script.Mouse).FollowMouse()
end
end)
-- Default:
RunService.RenderStepped:Connect(function()
if Default == true then
TweenTo(self.Head.CFrame * CFrame.new(0,Y,X))
end
end)
-- Accessories:
RunService.RenderStepped:Connect(function()
for _, v in pairs(self:GetChildren())do
if X == 0 and Y == 0 then
if v.Name == 'Head' then
v.LocalTransparencyModifier = 1
v.CanCollide = false
end
else
if v:IsA'Part' or v:IsA'UnionOperation' or v:IsA'MeshPart' then
v.LocalTransparencyModifier = 0
v.CanCollide = false
end
end
if v:IsA'Accessory' and X == 0 and Y == 0 then
v:FindFirstChild('Handle').LocalTransparencyModifier = 1
v:FindFirstChild('Handle').CanCollide = false
end
if v:IsA'Hat' and X == 0 and Y == 0 then
v:FindFirstChild('Handle').LocalTransparencyModifier = 1
v:FindFirstChild('Handle').CanCollide = false
end
end
end)
Follow-up module:
local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local PlayerMouse = Player:GetMouse()
local Camera = workspace.CurrentCamera
local Character = Player.Character or Player.CharacterAdded:Wait()
local Head = Character:WaitForChild("Head")
local Neck = Head:WaitForChild("Neck")
local Torso = Character:WaitForChild("UpperTorso")
local Waist = Torso:WaitForChild("Waist")
local Humanoid = Character:WaitForChild("Humanoid")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local NeckOriginC0 = Neck.C0
local WaistOriginC0 = Waist.C0
Neck.MaxVelocity = 1/3
module.FollowMouse = function()
local CameraCFrame = Camera.CoordinateFrame
if Character:FindFirstChild("UpperTorso") and Character:FindFirstChild("Head") then
local TorsoLookVector = Torso.CFrame.lookVector
local HeadPosition = Head.CFrame.p
if Neck and Waist then
if Camera.CameraSubject:IsDescendantOf(Character) or Camera.CameraSubject:IsDescendantOf(Player) then
local Point = PlayerMouse.Hit.p
local Distance = (Head.CFrame.p - Point).magnitude
local Difference = Head.CFrame.Y - Point.Y
Neck.C0 = Neck.C0:lerp(NeckOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 1, 0), 0.5 / 2)
Waist.C0 = Waist.C0:lerp(WaistOriginC0 * CFrame.Angles(-(math.atan(Difference / Distance) * 0.5), (((HeadPosition - Point).Unit):Cross(TorsoLookVector)).Y * 0.5, 0), 0.5 / 2)
end
end
end
end
return module
Make sure to name the followup module “Mouse” and put it under your “Camera” script inside the character! And add a bool value called “Active” to toggle on weather or not to follow the mouse! Without the value, the script will not run!
(Should probably update that…)
Thanks for so much engagement on my first official topic! And I hope to continue to get more positive feedback and critique on my code and what to improve. Thank you everyone!
~Scriptuyter