Combat MainMenu Issue Making Camera Very Buggy

While creating a main menu for my combat game, i’ve run into a problem with :LoadCharacter() The problem is that when the player presses play and loads in, the gui is still on screen and the camera is stuck.

Here’s a video of the problem:
robloxapp-20230529-1537375.wmv (2.0 MB)

Here’s both the scripts I’m using:
Localscript - In the UI in ReplicatedStorage

local Player = game.Players.LocalPlayer
local Character = Player.Character
local Camera = workspace.CurrentCamera
local Mouse = game.Players.LocalPlayer:GetMouse()
local DefaultCFrame = workspace.CameraPart.CFrame
local Scale = 160
local InMenu = true

local UI = script.Parent
local Buttons = UI.Buttons
local FadeFrame = UI:WaitForChild('FadeFrame')
local SpawnText = UI:WaitForChild('FadeFrame').Spawn
local MenuItems = UI:WaitForChild('Buttons')
local PlayButton = MenuItems:WaitForChild('Play')
local ModesButton = MenuItems:WaitForChild('Play')
local Modes = MenuItems:WaitForChild('Play')

local tweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(
	1,
	Enum.EasingStyle.Quart,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)

local tweenInfo2 = TweenInfo.new(
	0.8,
	Enum.EasingStyle.Quart,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)
local tween = tweenService:Create(FadeFrame, tweenInfo, {BackgroundTransparency = 0})
local tweenText = tweenService:Create(SpawnText, tweenInfo, {TextTransparency = 0})

local tween2 = tweenService:Create(FadeFrame, tweenInfo2, {BackgroundTransparency = 1})
local tweenText2 = tweenService:Create(SpawnText, tweenInfo2, {TextTransparency = 1})

repeat wait()
	Camera.CameraType = Enum.CameraType.Scriptable
until Camera.CameraType == Enum.CameraType.Scriptable

game:GetService("RunService").Heartbeat:Connect(function()
	Camera.Focus = DefaultCFrame
	local Center = Vector2.new(Camera.ViewportSize.X/2, Camera.ViewportSize.Y/2)
	local MoveVector = Vector3.new((Mouse.X-Center.X)/Scale, -(Mouse.Y-Center.Y)/Scale, 0)
	Camera.CFrame = DefaultCFrame * CFrame.Angles(math.rad(MoveVector.X), math.rad(MoveVector.Y), math.rad(MoveVector.Z))
	Camera.FieldOfView = 83
end)

Camera.CFrame = workspace.CameraPart.CFrame

PlayButton.MouseButton1Click:Connect(function()
	if InMenu then
	InMenu = false
		tween:Play()
		tweenText:Play()
		wait(5)
		tween2:Play()
		tweenText2:Play()
		game.ReplicatedStorage.LoadChar:FireServer()
		task.wait()
		Camera.CameraType = Enum.CameraType.Custom
		Camera.CameraSubject = Player.Character:WaitForChild("Humanoid")
	end
end)

Script - In ServerScriptService

game.Players.PlayerAdded:Connect(function(Plr)
	game.ReplicatedStorage.Spawn.Parent = Plr:WaitForChild("PlayerGui")
end)

local Camera = workspace.CurrentCamera

local characterLoader = game.ReplicatedStorage:WaitForChild("LoadChar")
local function loadCharacter(client)
	if client then
		if client.Character ~= nil then print(client.Name .. " already has character loaded, reloading")
		else print(client.Name .. " had no character loaded, loading their character now!")
			client:LoadCharacter()
		end
	end
end
characterLoader.OnServerEvent:connect(loadCharacter)

I’m a little stumped, I’m not sure what to do.

1 Like

Forgot to mention this before: I’m pretty sure the camera is stuck because RunService continues to run after the character has been loaded using LoadCharacter. You will need to stop the Heartbeat function when a character has loaded, and this should be determined by a BoolValue parented anywhere (accessible by the server) under the Player Object.
As to why the gui is still on screen, this could be caused by having ResetOnSpawn enabled for the ScreenGui. What I’d suggest is to first disable ResetOnSpawn, and also disable the ScreenGui entirely once the character has loaded.

Create a BoolValue under the Player Object from a Server Script (create a Server Script under ServerScriptService and use the following code)

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(plr)
	local InMenu = Instance.new("BoolValue")
	InMenu.Name = "InMenu"
	InMenu.Value = true -- change this to 'false' if the player does not automatically spawn in menu when they first join the server
	InMenu.Parent = plr
end)

Now here is your updated Local Script (I am only applying changes to a part of the code, from RunService to the end of the script):

local inMenuVal = Player:WaitForChild("InMenu")
local connections = {} -- this is for stopping the 'Heartbeat' function from running after character has reloaded

local function cameraFunc() -- this function should be called when player goes back into menu (if that is an option)
	if connections.playerInMenu ~= nil then -- prevent the function from running more than once
		return
	end

	connections.playerInMenu = game:GetService("RunService").Heartbeat:Connect(function()
		if not inMenuVal.Value then -- when player is not in menu
			UI.Enabled = false -- I'm going to assume 'UI' is your ScreenGui

			if connections.playerInMenu then
				connections.playerInMenu:Disconnect() -- disconnects the function
				connections.playerInMenu = nil
			end
		end

		Camera.Focus = DefaultCFrame
		local Center = Vector2.new(Camera.ViewportSize.X/2, Camera.ViewportSize.Y/2)
		local MoveVector = Vector3.new((Mouse.X-Center.X)/Scale, -(Mouse.Y-Center.Y)/Scale, 0)
		Camera.CFrame = DefaultCFrame * CFrame.Angles(math.rad(MoveVector.X), math.rad(MoveVector.Y), math.rad(MoveVector.Z))
		Camera.FieldOfView = 83
	end)
end

Camera.CFrame = workspace.CameraPart.CFrame

PlayButton.MouseButton1Click:Connect(function()
	if inMenuVal.Value then -- replaced variable with the 'BoolValue'
		--InMenu = false
		 -- we will change the InMenu BoolValue on the server
		tween:Play()
		tweenText:Play()
		task.wait(5)
		tween2:Play()
		tweenText2:Play()
		game.ReplicatedStorage.LoadChar:FireServer()
		task.wait()
		Camera.CameraType = Enum.CameraType.Custom
		Camera.CameraSubject = Player.Character:WaitForChild("Humanoid")
	end
end)

inMenuVal.Changed:Connect(function()
	if inMenuVal.Value then
		cameraFunc() -- run camera function when player goes into menu again
	end
end)

And here is your updated Server Script:

game.Players.PlayerAdded:Connect(function(Plr)
	game.ReplicatedStorage.Spawn.Parent = Plr:WaitForChild("PlayerGui")
end)

local characterLoader = game.ReplicatedStorage:WaitForChild("LoadChar")

local function loadCharacter(client)
	if client then
		local InMenuValue = client:FindFirstChild("InMenu")
		
		if InMenuValue and InMenuValue.Value then
		
		 	print(client.Name .. " had no character loaded, loading their character now!")
			client:LoadCharacter()
			InMenuValue.Value = false -- this will execute once the character has loaded
		end
	end
end
characterLoader.OnServerEvent:Connect(loadCharacter)

-- Side note: Remember to use the 'InMenu' BoolValue when going back into menu

Edit:

A suggestion I have is to have an exclusive Team only used for players in Menu. This could also be a useful way to determine whether or not a player is in Menu.

this never gets disconnected on .MouseButton1Click:

do

local RunConnection

RunConnection = game:GetService("RunService").Heartbeat:Connect(function()
	Camera.Focus = DefaultCFrame
	local Center = Vector2.new(Camera.ViewportSize.X/2, Camera.ViewportSize.Y/2)
	local MoveVector = Vector3.new((Mouse.X-Center.X)/Scale, -(Mouse.Y-Center.Y)/Scale, 0)
	Camera.CFrame = DefaultCFrame * CFrame.Angles(math.rad(MoveVector.X), math.rad(MoveVector.Y), math.rad(MoveVector.Z))
	Camera.FieldOfView = 83
end)

PlayButton.MouseButton1Click:Connect(function()
	if InMenu then
	InMenu = false
		tween:Play()
		tweenText:Play()
		wait(5)
		tween2:Play()
		tweenText2:Play()
		game.ReplicatedStorage.LoadChar:FireServer()
		task.wait()
		Camera.CameraType = Enum.CameraType.Custom
		Camera.CameraSubject = Player.Character:WaitForChild("Humanoid")
RunConnection:Disconnect()
	end
end)

do make sure that when you loadchar, that the gui doesnt have ResetOnSpawn set to true

Ok, this works, but now there is leftover gui on the screen, but you got the camera fixed


And these two are orange should I be worried?

I assumed the UI variable at the top of your LocalScript was the ScreenGui, I might have been wrong. If you haven’t created a variable for your ScreenGui, create one right above the cameraFunc function. Then change this part of the code:

-- this code block is right under the **RunService.Heartbeat** function

if not inMenuVal.Value then -- when player is not in menu
	ScreenGui.Enabled = false -- change 'ScreenGui' to the variable name of your ScreenGui

	if connections.playerInMenu then
		connections.playerInMenu:Disconnect() -- disconnects the function
		connections.playerInMenu = nil
	end
end

What does it say when you hover over the orange line? If they do not affect the whole function, then I believe you should be fine.

It is, I guess its just not enabling it for some reason

Key ‘playerInMenu’ not found in table ‘connections’

Did you mean it’s not disabling?
I just noticed that I placed that code line, where the ScreenGui is meant to be disabled, right after the function is disconnected, which is likely why it isn’t disabling (if that is the issue).
I have updated the LocalScript in the post with 3 given codes. Also, make sure that the ResetOnSpawn property is disabled for your ScreenGui.

Now the camera wont shift in the menu and I get an error in the console when the player spawns, the error says: Players.Auseral.PlayerGui.Spawn.MainMenuHandler:86: attempt to index nil with ‘WaitForChild’

I believe this is the code line for your issue:

Camera.CameraSubject = Player.Character:WaitForChild("Humanoid")

This issue is occurring because now that you have ResetOnSpawn disabled, that specific code line would be executing while the character is currently reloading.
To fix this, I believe you should either run that line of code under the inMenuVal.Changed function, or just don’t run that code at all, since I believe when the character is respawned, the CameraSubject is automatically set to the humanoid.

Try removing that line of code first, and if that doesn’t automatically set the CameraSubject to the humanoid, run that line of code under the .Changed function.

inMenuVal.Changed:Connect(function()
	if inMenuVal.Value then
		cameraFunc() -- run camera function when player goes into menu again
	else
		Camera.CameraSubject = Player.Character:WaitForChild("Humanoid")
	end
end)

Edit:

I’m pretty sure this is because the cameraFunc function hasn’t been called when the script first runs.
Run this line of code anywhere in the script (make sure it’s not under any function or statements):

-- also make sure this is ran after the function has been created
cameraFunc()
1 Like

Thank you so much! But one more thing, how do I get the player to respawn? Because right now, the player doesn’t respawn, instead just sits their when dead.

1 Like

I don’t think this is related to the main issues that were occurring for you. This may be something you’ll need to figure out yourself, or create another topic about it if you’ve been struggling with this for a while now.
And you are welcome, happy to help!

Thanks for all the needed help! :happy3:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.