As the title says. I am working on a game and we have a viewmodel for the hands of our avatar and it works perfectly for the first player to join the game, but if another player joins it wont work for them. It will still work for the player who initially joined, but for the other player/s it will just make their viewmodel hands float and outputs an error into the console saying, “Script 'ReplicatedStorage.Modules.ViewmodelHandler:168: attempt to index nil with ‘Color’”
Here is the script:
local ViewmodelHandler = {}
local PhysicsService = game:GetService("PhysicsService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid", 1)
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart", 1)
local LeftArm = Character:FindFirstChild("Left Arm") or Character:FindFirstChild("LeftHand")
local RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")
local Camera = Workspace.CurrentCamera
local Miscs = ReplicatedStorage:WaitForChild("Miscs")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Viewmodels = Miscs.Viewmodels
local Utilities = require(Modules.Utilities)
local Spring = Utilities.Spring
local Thread = Utilities.Thread
local Math = Utilities.Math
local ViewmodelStorage = Camera:FindFirstChild("ViewmodelStorage")
if not ViewmodelStorage then
ViewmodelStorage = Instance.new("Folder")
ViewmodelStorage.Name = "ViewmodelStorage"
ViewmodelStorage.Parent = Camera
end
local AimAlpha = script.AimAlpha
local GeneralSettings = {
CanSway = true;
CanBobble = false;
CanBreathe = true;
CanAim = true;
CanRecoil = true;
RecoilYRotMax = 16;
RecoilZPosMax = 1;
RecoilYPosMax = 0.5;
AimSwingSensitivity = 0.75;
AimAnimationWeight = 0.75;
ApplyCharacterClothing = true;
ApplyCharacterMesh = true;
}
--legends:
--[s]: speed
--[d]: damper
--[t]: target
--[p]: position
--[v]: velocity
local SpeedSpring = Spring.spring.new()
SpeedSpring.s = 16
local VelocitySpring = Spring.spring.new(Vector3.new())
VelocitySpring.s = 16
VelocitySpring.t = Vector3.new()
VelocitySpring.p = Vector3.new()
local SwaySpring = Spring.spring.new(Vector3.new())
SwaySpring.s = 10
SwaySpring.d = 0.75
local OffStates = {"Jumping", "PlatformStanding", "Ragdoll", "Seated", "FallingDown", "FreeFalling", "GettingUp", "Swimming", "Climbing"}
local OnStates = {"Running"}
local CurrentViewmodel
local CurrentConfigs
local CurrentFakeCamera
local OldCamCF
local Velocity = Vector3.new()
local Speed = 0
local Distance = 0
local RecoilPower = 0
local XRot = 0
local YRot = 0
local ZRot = 0
local YPos = 0
local ZPos = 0
local RecoilCFrame = CFrame.new()
local OffStateConnections = {}
local OnStateConnections = {}
local AimPointTable = {}
local CurrentAimPoint
local Offset
local HasAimPoints = false
local IsAiming = false
local Transparent = false
for _, state in pairs(OffStates) do
table.insert(OffStateConnections, Humanoid[state]:Connect(function()
active = false
end))
end
for _, state in pairs(OnStates) do
table.insert(OnStateConnections, Humanoid[state]:Connect(function(speed)
active = (speed > 1)
end))
end
local function ViewmodelBob(a, r, baseWalkSpeed)
local a, r = a or 1, r or 1
local d, s, v = Distance * 6.28318 * 3 / 4, Speed, -Velocity
--if s < baseWalkSpeed then
local w = Vector3.new(r * math.sin(d / 4 - 1) / 256 + r * (math.sin(d / 64) - r * v.Z / 4) / 512, r * math.cos(d / 128) / 128 - r * math.cos(d / 8) / 256, r * math.sin(d / 8) / 128 + r * v.X / 1024) * s / 20 * 6.28318
return CFrame.new(r * math.cos(d / 8 - 1) * s / 196, 1.25 * a * math.sin(d / 4) * s / 512, 0) * Math.FromAxisAngle(w)
--else
--local w = Vector3.new((r * math.sin(d / 4 - 1) / 256 + r * (math.sin(d / 64) - r * v.Z / 4) / 512) * s / 20 * 6.28318, (r * math.cos(d / 128) / 128 - r * math.cos(d / 8) / 256) * s / 20 * 6.28318, r * math.sin(d / 8) / 128 * (5 * s - 56) / 20 * 6.28318 + r * v.X / 1024)
--return CFrame.new(r * math.cos(d / 8 - 1) * (5 * s - 56) / 196, 1.25 * a * math.sin(d / 4) * s / 512, 0) * Math.FromAxisAngle(w)
--end
end
local function ViewmodelBreath(a)
local d, s = os.clock() * 6, 2 * (1.2 - a)
return CFrame.new(math.cos(d / 8) * s / 128, -math.sin(d / 4) * s / 128, math.sin(d / 16) * s / 64)
end
local function SetTextureTransparency(part, transparency)
local p = part:GetChildren()
for i = 1, #p do
local v = p[i]
if v:IsA("Texture") or v:IsA("Decal") then
v.LocalTransparencyModifier = transparency
end
end
end
local function IsFirstPerson()
return (Camera.Focus.p - Camera.CoordinateFrame.p).Magnitude <= 1
end
local function GetTool()
return Character:FindFirstChildOfClass("Tool")
end
function LoadAppearance(Viewmodel)
local Viewmodel = Viewmodel
Thread:Spawn(function()
local Loaded = Player:HasAppearanceLoaded()
while not Loaded do
Loaded = Player:HasAppearanceLoaded()
RunService.RenderStepped:Wait()
end
local HumanoidDescription = Humanoid:FindFirstChildOfClass("HumanoidDescription")
while not HumanoidDescription do
HumanoidDescription = Humanoid:FindFirstChildOfClass("HumanoidDescription")
RunService.RenderStepped:Wait()
end
if Viewmodel:FindFirstChild("Left Arm") and Viewmodel:FindFirstChild("Right Arm") then
Viewmodel["Left Arm"].Color = LeftArm.Color
Viewmodel["Right Arm"].Color = RightArm.Color
end
if GeneralSettings.ApplyCharacterClothing and not GeneralSettings.ApplyCharacterMesh then
local Shirt = Character:FindFirstChild("Shirt")
if Shirt then
Shirt:Clone().Parent = Viewmodel
end
end
if GeneralSettings.ApplyCharacterMesh then
local successful, errorMessage = pcall(function()
HumanoidDescription.ProportionScale = 0
HumanoidDescription.BodyTypeScale = 0
HumanoidDescription.HeightScale = 1
HumanoidDescription.WidthScale = 1
HumanoidDescription.DepthScale = 1
Viewmodel.Humanoid:ApplyDescription(HumanoidDescription)
end)
if not successful then
warn(errorMessage)
else
for _, Part in pairs(Viewmodel:GetDescendants()) do
if Part:IsA("Accessory") or Part:IsA("ShirtGraphic") or Part:IsA("Pants") or (Part:IsA("Weld") and Part.Name == "HeadWeld") then
Part:Destroy()
else
if not GeneralSettings.ApplyCharacterClothing and Part:IsA("Shirt") then
Part:Destroy()
end
end
end
end
end
end)
end
function ViewmodelHandler:LoadAppearance()
for _, child in pairs(CurrentViewmodel:GetDescendants()) do
if child:IsA("Shirt") and GeneralSettings.ApplyCharacterClothing and not GeneralSettings.ApplyCharacterMesh then
child:Destroy()
end
end
LoadAppearance(CurrentViewmodel)
end
function ViewmodelHandler:RecoilViewmodel(value)
RecoilPower = value
end
function ViewmodelHandler:SetAimEnabled(value, id, alignToAimPoint, tweenInfo)
IsAiming = value
if not alignToAimPoint then
IsAiming = false
end
if HasAimPoints then
CurrentAimPoint = AimPointTable[id].AimPoint
end
TweenService:Create(AimAlpha, tweenInfo, {Value = IsAiming and 1 or 0}):Play()
end
function ViewmodelHandler:SetViewmodelTransparent(Enabled)
Transparent = Enabled
end
function ViewmodelHandler.SetUpViewmodel(viewmodelName)
local Viewmodel
if ViewmodelStorage:FindFirstChild("v_"..viewmodelName) then
Viewmodel = ViewmodelStorage:FindFirstChild("v_"..viewmodelName)
else
Viewmodel = Viewmodels["v_"..viewmodelName]:Clone()
end
if Viewmodel and Viewmodel.PrimaryPart then
CurrentConfigs = require(Viewmodel:FindFirstChild("Configs"))
if Viewmodel:FindFirstChild("AimPoints") then
if #Viewmodel.AimPoints:GetChildren() > 0 then
local AimPoints = Viewmodel.AimPoints:GetChildren()
table.sort(AimPoints, function(a, b)
return tonumber(a.Name) < tonumber(b.Name)
end)
for i, v in ipairs(AimPoints) do
table.insert(AimPointTable, {
Id = i,
AimPoint = v
})
end
CurrentAimPoint = AimPointTable[1].AimPoint
Offset = nil
HasAimPoints = true
end
end
CurrentFakeCamera = Viewmodel:FindFirstChild("FakeCamera")
for _, child in pairs(Viewmodel:GetDescendants()) do
if child:IsA("Shirt") and GeneralSettings.ApplyCharacterClothing and not GeneralSettings.ApplyCharacterMesh then
child:Destroy()
end
if not IsFirstPerson() then
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = false
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = false
end
if child:IsA("BasePart") then
child.LocalTransparencyModifier = 1
SetTextureTransparency(child, 1)
end
else
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = true
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = true
end
if child:IsA("BasePart") then
child.LocalTransparencyModifier = 0
SetTextureTransparency(child, 0)
end
end
if child:IsA("BasePart") then
PhysicsService:SetPartCollisionGroup(child, "Viewmodel")
end
end
Viewmodel.PrimaryPart.Anchored = true
if Camera.CameraType == Enum.CameraType.Custom then
local Offset = CurrentConfigs and CurrentConfigs.Offset or CFrame.new(0, 0, 0)
Viewmodel.PrimaryPart.CFrame = (Camera.CoordinateFrame * CFrame.new(0, 0, (Camera.FieldOfView / 90 - 1) * 0.3)) * Offset
end
Viewmodel.Parent = ViewmodelStorage
LoadAppearance(Viewmodel)
CurrentViewmodel = Viewmodel
return Viewmodel
end
return nil
end
local function RenderViewmodel()
if CurrentViewmodel and CurrentViewmodel.PrimaryPart then
if CurrentFakeCamera then
if IsFirstPerson() then
local NewCamCF = CurrentFakeCamera.CFrame:ToObjectSpace(CurrentViewmodel.PrimaryPart.CFrame)
if OldCamCF then
--Camera.CFrame = Camera.CFrame * NewCamCF:ToObjectSpace(NewCamCF)
local _, _, Z = NewCamCF:ToOrientation()
local X, Y, _ = NewCamCF:ToObjectSpace(OldCamCF):ToEulerAnglesXYZ()
Camera.CFrame = Camera.CFrame * CFrame.Angles(X, Y, -Z)
end
OldCamCF = NewCamCF
--else
--Camera.CFrame = Camera.CFrame
end
end
for _, child in pairs(CurrentViewmodel:GetDescendants()) do
if not IsFirstPerson() then
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = false
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = false
end
if child:IsA("BasePart") then
child.LocalTransparencyModifier = 1
SetTextureTransparency(child, 1)
end
else
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = not Transparent
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = not Transparent
end
if child:IsA("UnionOperation") or child:IsA("MeshPart") or child:IsA("BasePart") then
local TransMod = Transparent and 1 or 0
child.LocalTransparencyModifier = TransMod
SetTextureTransparency(child, TransMod)
end
end
end
local Tool = GetTool()
if Tool then
for _, child in pairs(Tool:GetDescendants()) do
if not IsFirstPerson() then
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = true
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = true
end
if child:IsA("BasePart") then
child.LocalTransparencyModifier = 0
end
SetTextureTransparency(child, 0)
else
if child:IsA("Beam") or child:IsA("Trail") or child:IsA("ParticleEmitter") then
if string.match(child.Name, "CHRG_") == nil and string.match(child.Name, "SmokeTrail") == nil and string.match(child.Parent.Name, "GunMuzzlePoint") == nil then
child.Enabled = false
end
end
if child:IsA("RodConstraint") or child:IsA("RopeConstraint") or child:IsA("SpringConstraint") then
child.Visible = false
end
if child:IsA("BasePart") then
child.LocalTransparencyModifier = 1
end
SetTextureTransparency(child, 1)
end
end
end
end
end
function ViewmodelHandler:CullViewmodel(viewmodel)
if viewmodel and viewmodel.PrimaryPart then
if CurrentViewmodel == viewmodel then
CurrentViewmodel = nil
CurrentConfigs = nil
CurrentFakeCamera = nil
OldCamCF = nil
CurrentAimPoint = nil
Offset = nil
HasAimPoints = false
table.clear(AimPointTable)
AimAlpha.Value = 0
end
viewmodel.PrimaryPart.CFrame = CFrame.new(math.huge, math.huge, math.huge) * CFrame.Angles(0, 0, 0)
end
end
function ViewmodelHandler:DestroyViewmodel(viewmodel)
if viewmodel then
if CurrentViewmodel == viewmodel then
CurrentViewmodel = nil
CurrentConfigs = nil
CurrentFakeCamera = nil
OldCamCF = nil
CurrentAimPoint = nil
Offset = nil
HasAimPoints = false
table.clear(AimPointTable)
AimAlpha.Value = 0
end
viewmodel:Destroy()
end
end
Player.CharacterAdded:Connect(function(character)
Character = character
Humanoid = Character:WaitForChild("Humanoid", 1)
HumanoidRootPart = Character:WaitForChild("HumanoidRootPart", 1)
LeftArm = Character:FindFirstChild("Left Arm") or Character:FindFirstChild("LeftHand")
RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")
for i, v in pairs(OffStateConnections) do
if v then
v:Disconnect()
end
table.remove(OffStateConnections, i)
end
for i, v in pairs(OnStateConnections) do
if v then
v:Disconnect()
end
table.remove(OnStateConnections, i)
end
for _, state in pairs(OffStates) do
table.insert(OffStateConnections, Humanoid[state]:Connect(function()
active = false
end))
end
for _, state in pairs(OnStates) do
table.insert(OnStateConnections, Humanoid[state]:Connect(function(speed)
active = (speed > 1)
end))
end
end)
RunService.RenderStepped:Connect(function(dt)
if CurrentViewmodel and CurrentViewmodel.PrimaryPart and Character and Humanoid and HumanoidRootPart then
local MouseDelta = UserInputService:GetMouseDelta()
RecoilPower = RecoilPower > 0.1 and Math.Lerp(RecoilPower, 0, dt * 11) or 0
SwaySpring.t = Vector3.new(VelocitySpring.v.Z / 1024 / 32 + VelocitySpring.v.Y / 1024 / 16 + (MouseDelta.Y / 10) / 1024 * 3 / 2, VelocitySpring.v.X / 1024 / 32 + (MouseDelta.X / 10) / 1024 * 3 / 2, -(MouseDelta.X / 10) / 1024 * 3 / 2)
local RelativeVelocity = CFrame.new().VectorToObjectSpace(HumanoidRootPart.CFrame, HumanoidRootPart.Velocity)
SpeedSpring.t = (active and Humanoid.Health > 0) and (Vector3.new(1, 0, 1) * RelativeVelocity).Magnitude or 0
VelocitySpring.t = RelativeVelocity
Speed = SpeedSpring.p
Distance = Distance + dt * SpeedSpring.p
Velocity = VelocitySpring.p
YRot = Math.Lerp(YRot, GeneralSettings.RecoilYRotMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 6) + Math.Lerp(XRot, Math.Randomize(2) * RecoilPower, RecoilPower == 0 and dt * 7 or dt / 2)
XRot = Math.Lerp(XRot, Math.Randomize(1.3) * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 3)
ZRot = Math.Lerp(ZRot, Math.Randomize(5) * RecoilPower, RecoilPower == 0 and dt * 7 or dt / 3)
YPos = Math.Lerp(YPos, GeneralSettings.RecoilYPosMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 0.4)
ZPos = Math.Lerp(ZPos, GeneralSettings.RecoilZPosMax * RecoilPower, RecoilPower == 0 and dt * 7 or dt * 0.9)
RecoilCFrame = CFrame.new(0, YPos, ZPos) * CFrame.Angles(math.rad(YRot), XRot, ZRot)
local AimOffset = CFrame.new() --* CFrame.new(0, -1.5, 0)
local AimCFrame = CFrame.new()
local CF = CFrame.new()
CF = Camera.CoordinateFrame * CFrame.new(0, 0, (Camera.FieldOfView / 90 - 1) * 0.3)
if GeneralSettings.CanSway then
CF = CF * Math.FromAxisAngle(SwaySpring.v)
end
if GeneralSettings.CanBobble then
CF = CF * ViewmodelBob(0.7 - 0.3 * AimAlpha.Value, 1 - 0.8 * AimAlpha.Value, Humanoid.WalkSpeed)
end
if GeneralSettings.CanBreathe then
CF = CF * ViewmodelBreath(AimAlpha.Value)
end
if GeneralSettings.CanAim then
if IsAiming then
MouseDelta = MouseDelta * GeneralSettings.AimSwingSensitivity
end
if CurrentAimPoint then
Offset = (Offset or CFrame.new()):Lerp(CurrentViewmodel.PrimaryPart.CFrame:ToObjectSpace(CurrentAimPoint.CFrame * AimOffset):Inverse(), math.clamp(1 - GeneralSettings.AimAnimationWeight, 0, 1))
AimCFrame = AimCFrame * AimCFrame:Lerp(Offset, AimAlpha.Value)
end
end
if GeneralSettings.CanRecoil then
CF = CF * RecoilCFrame
end
local Offset = CurrentConfigs and CurrentConfigs.Offset or CFrame.new(0, 0, 0)
local Offst = Math.Interpolator(Offset)
CF = CF * Offst(1 - AimAlpha.Value)
if Camera.CameraType == Enum.CameraType.Custom then
local CamOffset = -Humanoid.CameraOffset
local ShakeX = math.clamp(CamOffset.X * 0.5, -0.25, 0.25)
local ShakyY = math.clamp(CamOffset.Y * 0.5, -0.25, 0.25)
local ShakeZ = math.clamp(CamOffset.Z * 0.5, -0.25, 0.25)
CurrentViewmodel.PrimaryPart.CFrame = CF * AimCFrame * CFrame.new(ShakeX, ShakyY, ShakeZ)
end
RenderViewmodel()
end
end)
return ViewmodelHandler
THIS IS THE PROBLEM LINE:
if Viewmodel:FindFirstChild("Left Arm") and Viewmodel:FindFirstChild("Right Arm") then
Viewmodel["Left Arm"].Color = LeftArm.Color
Viewmodel["Right Arm"].Color = RightArm.Color
end
We have already tried changing the ''FindFirstChild" to “WaitForChild”, but we didnt have any luck with that and still got the error.
Something to note, our game doesnt automatically spawn the players. The player joins to a screengui containing a team select and only spawns in when they select a team. We tried it with this system disabled and it did work, however we have no idea what is causing it not to work especially since we tried “WaitForChild” and it still didnt work, and it still doesnt explain why it works for one player, but not the others who join after them.
Does anyone have any ideas?