I am trying to create a custom first person camera and this script seems to not be working. When I run it the Camera gets locked on I’m pretty sure the center (0,0,0) in the workspace and is stuck there.
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Camera = game.Workspace.CurrentCamera
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local CurrentPos
local NextPos
local Difference
local function Setup()
-- Set initial camera cframe
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos,CurrentPos)
end
local function Update()
-- Update camera cframe as position of HumanoidRootPart changes
if CurrentPos and Character then
NextPos = HumanoidRootPart.Position
Difference = NextPos - CurrentPos
CurrentPos = NextPos
Camera.CFrame = Camera.CFrame + Difference
end
end
Player.CharacterAdded:Connect(Setup)
game:GetService("RunService"):BindToRenderStep("Camera",Enum.RenderPriority.Camera.Value,Update)
You are waiting for the character before setting up your connection to Player.CharacterAdded. I would say you can test it by resetting your character and the camera now moves, but you never reassign the Character or HumanoidRootPart variables in your Setup function.
Just don’t wait for the character to be added when you set it at the beginning of the script, and the CharacterAdded event will fire on its own.
--[[ line 2
local Character = Player.Character or Player.CharacterAdded:Wait()
local Camera = game.Workspace.CurrentCamera
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
-- change it to this ]]
local Character
local Camera = game.Workspace.CurrentCamera
local HumanoidRootPart
--[[ line 12
local function Setup()
-- Set initial camera cframe
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos,CurrentPos)
end
-- change it to this ]]
local function Setup(char)
-- Set initial camera cframe
Character = char
HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos)
end
I’m pretty sure changing the Camera’s properties requires you to change it’s CameraType to Enum.CameraType.Scriptable first, except from that follow what @goldenstein64 says to do.
So that worked, but there is one more thing. When I try calling these functions from a module script in the Setup function the output prints correctly, but the transparency doesn’t change.
Module Script:
local module = {}
function module.HideHats(Char)
for _,v in pairs(Char:GetDescendants()) do
if v:IsA("Accessory") then
v:WaitForChild("Handle").LocalTransparencyModifier = 1
end
end
print("Hidden Hats")
return true
end
function module.HideBody(Char)
for _,v in pairs(Char:GetChildren()) do
if v:IsA("BasePart") then
v.LocalTransparencyModifier = 1
end
end
print("Hidden Body")
return true
end
return module
Setup:
local function Setup(Char)
-- Set initial camera cframe
Character = Char
HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
HideModule.HideHats(Character)
HideModule.HideBody(Character)
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos) + Vector3.new(0,2,0)
end
The output prints “Hidden Hats” and “Hidden Body” but they aren’t ‘hidden’ because I can still see them.
You have to wait until the character’s appearance is loaded before setting their transparency to 1. Regardless of rig type. Very simple event connection in theory:
-- also has a Character argument if you care
Player.CharacterAppearanceLoaded:Connect(function(Char)
HideModule.HideHats(Char)
HideModule.HideBody(Char) -- oops
end)
local function Setup(Char)
-- Set initial camera cframe
Character = Char
HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
-- just take out the HideModule stuff I guess
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos) + Vector3.new(0,2,0)
end
You can also just hide everything in the character using a function like this:
function module.HideEverything(Char)
for _,v in pairs(Char:GetDescendants()) do
if v:IsA("BasePart") then
v.LocalTransparencyModifier = 1
end
end
print("Hidden Everything")
return true
end
That is true if you are creating your own script in StarterPlayerScriptsnot called CameraScript. But if it is called that, then you don’t need to worry about the CameraType, since it replaces the module that decided the behavior behind each CameraType in the first place.
It’s good practice to call it something else though if you plan on using the other CameraTypes though.
So everything works except the hiding of the player still. I think I know why, but am not sure how to fix it. In the CharacterAppearanceLoaded function how can I define what Char is?
local Player = game.Players.LocalPlayer
local Character
local HideModule = require(script.HideModule)
local Camera = game.Workspace.CurrentCamera
Camera.CameraType = Enum.CameraType.Scriptable
local HumanoidRootPart
local CurrentPos
local NextPos
local Difference
Player.CharacterAppearanceLoaded:Connect(function(Char)
HideModule.HideLocalPlayer(Char)
end)
local function Setup(Char)
-- Set initial camera cframe
Character = Char
HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
CurrentPos = HumanoidRootPart.Position
Camera.CFrame = CFrame.new(CurrentPos) + Vector3.new(0,2,0)
end
local function Update()
-- Update camera cframe as position of HumanoidRootPart changes
if CurrentPos and Character then
NextPos = HumanoidRootPart.Position
Difference = NextPos - CurrentPos
CurrentPos = NextPos
Camera.CFrame = Camera.CFrame + Difference
end
end
Player.CharacterAdded:Connect(Setup)
game:GetService("RunService"):BindToRenderStep("Camera",Enum.RenderPriority.Camera.Value,Update)
Module:
local module = {}
function module.HideLocalPlayer(Char)
for _,v in pairs(Char:GetDescendants()) do
if v:IsA("BasePart") then
v.LocalTransparencyModifier = 1
end
end
print("Hidden Player")
return true
end
return module
EDIT: I just realized Char is a parameter of CharacterAppearanceLoaded but it still doesnt work for some reason.
You’re probably getting thwarted by a couple of things.
CharacterAppearanceLoaded may not be firing when you’re testing in studio, if your avatar’s appearance has already loaded by the time CharacterAdded fires. One thing you could do in CharacterAdded is check Player:HasAppearanceLoaded(), but be warned, this can return true before your character’s body parts are actually parented to the character Model and ready to be made invisible, so…
The more robust way is to forget about appearance loaded and just loop over whatever parts are there at CharacterAdded time (if any) and connect up a Character.DescendantAdded listener to hide any additional parts as they are added to the character. This will even take care of accessories and tools you add during gameplay, so you’ll need to make exceptions for anything you add that you actually want to see.
Secondly, if you continue adding code to this script, and something yields above where you connect to CharacterAdded (even a single wait()), it’s possible that you’ll be connecting the CharacterAdded listener after it fires, so it will never catch the event for your initial spawn-in. You can make it more robust by doing something like this:
if Player.Character then
Setup(Player.Character)
end
Player.CharacterAdded:Connect(Setup)
Notice that the connection to CharacterAdded is not in an else block. You don’t want to conditionally connect to it, because it should always be connecting to handle respawns of your character.
Thank you, I got it to work on a Local Server test and in game, but for some reason it doesn’t work in studio. Other than the studio problem it works and I have no problem testing on Local Server instead of studio.