Hi Devforum, today I have encountered something that I need help with!
What do you want to achieve? NFL ball camera that focuses on only ONE ball and that it stops following the selected ball when it needs to.
What is the issue? The ballcam signals/sensors doesn’t make sure of the following:
that the ballcam stops following the ball when the script says so
when the ball gets destroyed, that the ballcam still doesn’t stop following the ball
What solutions have you tried so far? I have looked into the devforum, but i just can’t find the solution??
Video of the ballcam:
The ballcam’s code:
player = game.Players.LocalPlayer
repeat wait() until player
local camera = game.Workspace.CurrentCamera
local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:FindFirstChild("HumanoidRootPart")
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local CurrentBall
local PartList = {
["WedgePart"] = true,
["Part"] = true,
["CornerWedgePart"] = true,
["MeshPart"] = true,
["TrussPart"] = true,
}
local function Toggle(Boolean, SelectedBall)
if Boolean == true then
elseif Boolean == false then
if SelectedBall == CurrentBall then
CurrentBall = nil
camera.CameraSubject = humanoid
else return end
end
if SelectedBall:IsDescendantOf(workspace) and PartList[SelectedBall.ClassName] then
CurrentBall = SelectedBall
camera.CameraSubject = SelectedBall
else
CurrentBall = nil
camera.CameraSubject = humanoid
return end
end
game.ReplicatedStorage:FindFirstChild("Events").BallCam.OnClientEvent:Connect(function(Enabled, SelectedBall)
Toggle(Enabled, SelectedBall)
end)
workspace.DescendantRemoving:Connect(function(Child)
if Child:IsDescendantOf(workspace) and PartList[Child.ClassName] then
if Child == CurrentBall then else return end
Toggle(false, CurrentBall)
end
end)
Any scripting corrections/solutions would be deeply appreciated!
You aren’t changing the camera type to scriptable and follow, I believe this will fix your error.
(Also, I know this isn’t a huge priority but it is unwise to take gameplay style / visuals from Football Fusion )
I’m noticing quite a few interesting choices in your code. I’m gonna assume the lack of indentation is due to some weird copy-paste issue, but you have the following:
-- Example 1:
if Boolean == true then -- Bad name for a variable, it should be named after what it represents
elseif Boolean == false then
if SelectedBall == CurrentBall then
...
end
end
-- Example 2:
if Child == CurrentBall then else return end
Variables in Lua are typically in snakeCase, not a big deal but something to keep in mind. The code I highlighted above though is something you might want to look into, as it is pretty weird.
-- "Fix" for example 1:
if not Boolean then
if SelectedBall == CurrentBall then
...
end
end
-- Alternative "fix" for example 1:
if not Boolean and SelectedBall == CurrentBall then
...
end
-- "Fix" for example 2:
if Child ~= CurrentBall then return end
ok so
if you made your code a lot cleaner you wouldn’t have bugs like this and bugfixing would be a lot smoother and writing and reading would bo so much easier
here’s the main problems your doing
player(first variable) is a global this is bad don’t
you redeclared it in the local variable below
local player should always be available never encountered a case where is had to do that
DO 4 SPACES(TAB FOR SHORT) THAT IS A INDENT, you have NO indents and it looks horrible
Also, adding on to what @ifkpop said, there are some code choices in here that are definitley questionable.
local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:FindFirstChild("HumanoidRootPart")
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local CurrentBall
local PartList = {
["WedgePart"] = true,
["Part"] = true,
["CornerWedgePart"] = true,
["MeshPart"] = true,
["TrussPart"] = true,
}
local function Toggle(Boolean, SelectedBall)
if Boolean == true then
elseif Boolean == false then
if SelectedBall == CurrentBall then
CurrentBall = nil
camera.CameraType = follow
camera.CameraSubject = nil
else return end
end
if SelectedBall:IsDescendantOf(workspace) and PartList[SelectedBall.ClassName] then
CurrentBall = SelectedBall
camera.CameraSubject = SelectedBall
else
CurrentBall = nil
camera.CameraType = follow
camera.CameraSubject = nil
return end
end
game.ReplicatedStorage:FindFirstChild("Events").BallCam.OnClientEvent:Connect(function(Enabled, SelectedBall)
Toggle(Enabled, SelectedBall)
end)
workspace.DescendantRemoving:Connect(function(Child)
if Child:IsDescendantOf(workspace) and PartList[Child.ClassName] then
if Child == CurrentBall then else return end
Toggle(false, CurrentBall)
end
end)
It still doesn’t work as fully intended, here’s the current code:
local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:FindFirstChild("HumanoidRootPart")
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local CurrentBall
local PartList = {
["WedgePart"] = true,
["Part"] = true,
["CornerWedgePart"] = true,
["MeshPart"] = true,
["TrussPart"] = true,
}
local function Toggle(Boolean, SelectedBall)
if not Boolean then
if SelectedBall == CurrentBall then
CurrentBall = nil
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
else return end
end
if SelectedBall:IsDescendantOf(workspace) and PartList[SelectedBall.ClassName] then
CurrentBall = SelectedBall
camera.CameraType = Enum.CameraType.Follow
camera.CameraSubject = SelectedBall
else
CurrentBall = nil
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
return end
end
game.ReplicatedStorage:FindFirstChild("Events").BallCam.OnClientEvent:Connect(function(Enabled, SelectedBall)
Toggle(Enabled, SelectedBall)
end)
workspace.DescendantRemoving:Connect(function(Child)
if Child:IsDescendantOf(workspace) and PartList[Child.ClassName] then
if Child ~= CurrentBall then
Toggle(false, CurrentBall)
end
end
end)
And if you’re wondering, it still behaves like the previous video i showed
Here is a list of prints that should’ve been printed:
print("currently following the ball.")
print("stopped following the ball.")
print("ball isn't located in workspace.")
print("ball is apparently destroyed.")
Go on the server and tell me if the ball is actually being destroyed, as this would explain why it doesn’t change the camera, I’ll keep looking over the code for a solution.
local function Toggle(Boolean, SelectedBall)
if not Boolean then
if SelectedBall == CurrentBall then
CurrentBall = nil
end
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
return
end
if SelectedBall:IsDescendantOf(workspace) and PartList[SelectedBall.ClassName] then
CurrentBall = SelectedBall
camera.CameraType = Enum.CameraType.Follow
camera.CameraSubject = SelectedBall
else
CurrentBall = nil
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
end
end
Try the script I just sent and tell me what happens. The issue with the script was that if the SelectedBall is not equal to the CurrentBall , the camera type and subject will not be reset, potentially causing the camera to continue following the previously selected ball object even when it is no longer valid or removed from the game world.
Something interesting happend, when the ballcam triggers the signal to stop following the ball, it actually does but the camera then stays on its position. And the script detects if the ball got destroyed.
Current code:
local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local character = player.Character or player.CharacterAdded:Wait()
local hrp = character:FindFirstChild("HumanoidRootPart")
local humanoid = character:FindFirstChildWhichIsA("Humanoid")
local CurrentBall
local PartList = {
["WedgePart"] = true,
["Part"] = true,
["CornerWedgePart"] = true,
["MeshPart"] = true,
["TrussPart"] = true,
}
local function Toggle(Boolean, SelectedBall)
if not Boolean then
if SelectedBall == CurrentBall then
CurrentBall = nil
end
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
print("stopped following the ball.")
return
end
if SelectedBall:IsDescendantOf(workspace) and PartList[SelectedBall.ClassName] then
CurrentBall = SelectedBall
camera.CameraType = Enum.CameraType.Follow
camera.CameraSubject = SelectedBall
print("currently following the ball.")
else
CurrentBall = nil
camera.CameraType = Enum.CameraType.Fixed
camera.CameraSubject = humanoid
print("ball isn't located in workspace.")
end
end
game.ReplicatedStorage:FindFirstChild("Events").BallCam.OnClientEvent:Connect(function(Enabled, SelectedBall)
Toggle(Enabled, SelectedBall)
end)
workspace.DescendantRemoving:Connect(function(Child)
if Child:IsDescendantOf(workspace) and PartList[Child.ClassName] then
if Child ~= CurrentBall then
Toggle(false, CurrentBall)
--print(camera.CameraType.Name)
print("ball is apparently destroyed.")
end
end
end)