Defult roblox scripts running over 10/s - Roblox Help

Hi! So, I recently noticed that a few games such as ER:LC’s network receive is green mostly all the time. This is great, however when I join an empty baseplate… the network receive is red. So I took a look at script performance on that empty baseplate world, now, scripts should never be running over 10/s and I saw that a couple of the default Roblox scripts, are running over 10/s:
image

I will post the both scripts below, I’m guessing they’re un-optimised and Roblox hasn’t taken the time to optimise them. I’m guessing ER:LC did take the time to optimise these scripts so that their network receive is high.

If you can help in optimising these scripts or replacing them that would be greatly appreciated.
Cheers,

RbxCharacterSounds Script:

-- Roblox character sound script

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local SOUND_DATA : { [string]: {[string]: any}} = {
	Climbing = {
		SoundId = "rbxasset://sounds/action_footsteps_plastic.mp3",
		Looped = true,
	},
	Died = {
		SoundId = "rbxasset://sounds/uuhhh.mp3",
	},
	FreeFalling = {
		SoundId = "rbxasset://sounds/action_falling.mp3",
		Looped = true,
	},
	GettingUp = {
		SoundId = "rbxasset://sounds/action_get_up.mp3",
	},
	Jumping = {
		SoundId = "rbxasset://sounds/action_jump.mp3",
	},
	Landing = {
		SoundId = "rbxasset://sounds/action_jump_land.mp3",
	},
	Running = {
		SoundId = "rbxasset://sounds/action_footsteps_plastic.mp3",
		Looped = true,
		Pitch = 1.85,
	},
	Splash = {
		SoundId = "rbxasset://sounds/impact_water.mp3",
	},
	Swimming = {
		SoundId = "rbxasset://sounds/action_swim.mp3",
		Looped = true,
		Pitch = 1.6,
	},
}

-- wait for the first of the passed signals to fire
local function waitForFirst(...) -- RBXScriptSignal
	local shunt: BindableEvent = Instance.new("BindableEvent")
	local slots = {...}

	local function fire(...)
		for i = 1, #slots do
			slots[i]:Disconnect()
		end

		return shunt:Fire(...)
	end

	for i = 1, #slots do -- RBXScriptSignal
		slots[i] = slots[i]:Connect(fire) -- Change to RBXScriptConnection
	end

	return shunt.Event:Wait()
end

-- map a value from one range to another
local function map(x: number, inMin: number, inMax: number, outMin: number, outMax: number): number
	return (x - inMin)*(outMax - outMin)/(inMax - inMin) + outMin
end

local function playSound(sound: Sound)
	sound.TimePosition = 0
	sound.Playing = true
end

local function shallowCopy(t)
	local out = {}
	for k, v in pairs(t) do
		out[k] = v
	end
	return out
end

local function initializeSoundSystem(player: Player, humanoid: Humanoid, rootPart: BasePart)
	local sounds: {[string]: Sound} = {}

	-- initialize sounds
	for name: string, props: {[string]: any} in pairs(SOUND_DATA) do
		local sound: Sound = Instance.new("Sound") 
		sound.Name = name

		-- set default values
		sound.Archivable = false
		sound.EmitterSize = 5
		sound.MaxDistance = 150
		sound.Volume = 0.65

		for propName, propValue: any in pairs(props) do
			sound[propName] = propValue
		end

		sound.Parent = rootPart
		sounds[name] = sound
	end

	local playingLoopedSounds: {[Sound]: boolean?} = {}

	local function stopPlayingLoopedSounds(except: Sound?)
		for sound in pairs(shallowCopy(playingLoopedSounds)) do
			if sound ~= except then
				sound.Playing = false
				playingLoopedSounds[sound] = nil
			end
		end
	end

	-- state transition callbacks.
	local stateTransitions: {[Enum.HumanoidStateType]: () -> ()} = {
		[Enum.HumanoidStateType.FallingDown] = function()
			stopPlayingLoopedSounds()
		end,

		[Enum.HumanoidStateType.GettingUp] = function()
			stopPlayingLoopedSounds()
			playSound(sounds.GettingUp)
		end,

		[Enum.HumanoidStateType.Jumping] = function()
			stopPlayingLoopedSounds()
			playSound(sounds.Jumping)
		end,

		[Enum.HumanoidStateType.Swimming] = function()
			local verticalSpeed = math.abs(rootPart.Velocity.Y)
			if verticalSpeed > 0.1 then
				sounds.Splash.Volume = math.clamp(map(verticalSpeed, 100, 350, 0.28, 1), 0, 1)
				playSound(sounds.Splash)
			end
			stopPlayingLoopedSounds(sounds.Swimming)
			sounds.Swimming.Playing = true
			playingLoopedSounds[sounds.Swimming] = true
		end,

		[Enum.HumanoidStateType.Freefall] = function()
			sounds.FreeFalling.Volume = 0
			stopPlayingLoopedSounds(sounds.FreeFalling)
			playingLoopedSounds[sounds.FreeFalling] = true
		end,

		[Enum.HumanoidStateType.Landed] = function()
			stopPlayingLoopedSounds()
			local verticalSpeed = math.abs(rootPart.Velocity.Y)
			if verticalSpeed > 75 then
				sounds.Landing.Volume = math.clamp(map(verticalSpeed, 50, 100, 0, 1), 0, 1)
				playSound(sounds.Landing)
			end
		end,

		[Enum.HumanoidStateType.Running] = function()
			stopPlayingLoopedSounds(sounds.Running)
			sounds.Running.Playing = true
			playingLoopedSounds[sounds.Running] = true
		end,

		[Enum.HumanoidStateType.Climbing] = function()
			local sound = sounds.Climbing
			if math.abs(rootPart.Velocity.Y) > 0.1 then
				sound.Playing = true
				stopPlayingLoopedSounds(sound)
			else
				stopPlayingLoopedSounds()
			end
			playingLoopedSounds[sound] = true
		end,

		[Enum.HumanoidStateType.Seated] = function()
			stopPlayingLoopedSounds()
		end,

		[Enum.HumanoidStateType.Dead] = function()
			stopPlayingLoopedSounds()
			playSound(sounds.Died)
		end,
	}

	-- updaters for looped sounds
	local loopedSoundUpdaters: {[Sound]: (number, Sound, Vector3) -> ()} = {
		[sounds.Climbing] = function(dt: number, sound: Sound, vel: Vector3)
			sound.Playing = vel.Magnitude > 0.1
		end,

		[sounds.FreeFalling] = function(dt: number, sound: Sound, vel: Vector3): ()
			if vel.Magnitude > 75 then
				sound.Volume = math.clamp(sound.Volume + 0.9*dt, 0, 1)
			else
				sound.Volume = 0
			end
		end,

		[sounds.Running] = function(dt: number, sound: Sound, vel: Vector3)
			sound.Playing = vel.Magnitude > 0.5 and humanoid.MoveDirection.Magnitude > 0.5
		end,
	}

	-- state substitutions to avoid duplicating entries in the state table
	local stateRemap: {[Enum.HumanoidStateType]: Enum.HumanoidStateType} = {
		[Enum.HumanoidStateType.RunningNoPhysics] = Enum.HumanoidStateType.Running,
	}

	local activeState: Enum.HumanoidStateType = stateRemap[humanoid:GetState()] or humanoid:GetState()

	local stateChangedConn = humanoid.StateChanged:Connect(function(_, state)
		state = stateRemap[state] or state

		if state ~= activeState then
			local transitionFunc: () -> () = stateTransitions[state]

			if transitionFunc then
				transitionFunc()
			end

			activeState = state
		end
	end)

	local steppedConn = RunService.Stepped:Connect(function(_, worldDt: number)
		-- update looped sounds on stepped
		for sound in pairs(playingLoopedSounds) do
			local updater: (number, Sound, Vector3) -> () = loopedSoundUpdaters[sound]

			if updater then
				updater(worldDt, sound, rootPart.Velocity)
			end
		end
	end)

	local humanoidAncestryChangedConn: RBXScriptConnection
	local rootPartAncestryChangedConn: RBXScriptConnection
	local characterAddedConn: RBXScriptConnection

	local function terminate()
		stateChangedConn:Disconnect()
		steppedConn:Disconnect()
		humanoidAncestryChangedConn:Disconnect()
		rootPartAncestryChangedConn:Disconnect()
		characterAddedConn:Disconnect()
	end

	humanoidAncestryChangedConn = humanoid.AncestryChanged:Connect(function(_, parent)
		if not parent then
			terminate()
		end
	end)

	rootPartAncestryChangedConn = rootPart.AncestryChanged:Connect(function(_, parent)
		if not parent then
			terminate()
		end
	end)

	characterAddedConn = player.CharacterAdded:Connect(terminate)
end

local function playerAdded(player: Player)
	local function characterAdded(character)
		-- Avoiding memory leaks in the face of Character/Humanoid/RootPart lifetime has a few complications:
		-- * character deparenting is a Remove instead of a Destroy, so signals are not cleaned up automatically.
		-- ** must use a waitForFirst on everything and listen for hierarchy changes.
		-- * the character might not be in the dm by the time CharacterAdded fires
		-- ** constantly check consistency with player.Character and abort if CharacterAdded is fired again
		-- * Humanoid may not exist immediately, and by the time it's inserted the character might be deparented.
		-- * RootPart probably won't exist immediately.
		-- ** by the time RootPart is inserted and Humanoid.RootPart is set, the character or the humanoid might be deparented.

		if not character.Parent then
			waitForFirst(character.AncestryChanged, player.CharacterAdded)
		end

		if player.Character ~= character or not character.Parent then
			return
		end

		local humanoid = character:FindFirstChildOfClass("Humanoid")
		while character:IsDescendantOf(game) and not humanoid do
			waitForFirst(character.ChildAdded, character.AncestryChanged, player.CharacterAdded)
			humanoid = character:FindFirstChildOfClass("Humanoid")
		end

		if player.Character ~= character or not character:IsDescendantOf(game) then
			return
		end

		-- must rely on HumanoidRootPart naming because Humanoid.RootPart does not fire changed signals
		local rootPart = character:FindFirstChild("HumanoidRootPart")
		while character:IsDescendantOf(game) and not rootPart do
			waitForFirst(character.ChildAdded, character.AncestryChanged, humanoid.AncestryChanged, player.CharacterAdded)
			rootPart = character:FindFirstChild("HumanoidRootPart")
		end

		if rootPart and humanoid:IsDescendantOf(game) and character:IsDescendantOf(game) and player.Character == character then
			initializeSoundSystem(player, humanoid, rootPart)
		end
	end

	if player.Character then
		characterAdded(player.Character)
	end
	player.CharacterAdded:Connect(characterAdded)
end

Players.PlayerAdded:Connect(playerAdded)
for _, player in ipairs(Players:GetPlayers()) do
	playerAdded(player)
end

Bubble chat script (I noticed this script only runs over 10/s when the player has movement input for some reason):

--[[
	// FileName: BubbleChat.lua
	// Written by: jeditkacheff, TheGamer101
	// Description: Code for rendering bubble chat
]]

--[[ SERVICES ]]
local PlayersService = game:GetService('Players')
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ChatService = game:GetService("Chat")
local TextService = game:GetService("TextService")
--[[ END OF SERVICES ]]

local LocalPlayer = PlayersService.LocalPlayer
while LocalPlayer == nil do
	PlayersService.ChildAdded:wait()
	LocalPlayer = PlayersService.LocalPlayer
end

local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local success, UserShouldLocalizeGameChatBubble = pcall(function()
	return UserSettings():IsUserFeatureEnabled("UserShouldLocalizeGameChatBubble")
end)
local UserShouldLocalizeGameChatBubble = success and UserShouldLocalizeGameChatBubble

local UserFixBubbleChatText do
	local success, value = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserFixBubbleChatText")
	end)
	UserFixBubbleChatText = success and value
end

local UserRoactBubbleChatBeta do
	local success, value = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserRoactBubbleChatBeta")
	end)
	UserRoactBubbleChatBeta = success and value
end

local UserPreventOldBubbleChatOverlap do
	local success, value = pcall(function()
		return UserSettings():IsUserFeatureEnabled("UserPreventOldBubbleChatOverlap")
	end)
	UserPreventOldBubbleChatOverlap = success and value
end

local function getMessageLength(message)
	return utf8.len(utf8.nfcnormalize(message))
end

--[[ SCRIPT VARIABLES ]]
local CHAT_BUBBLE_FONT = Enum.Font.SourceSans
local CHAT_BUBBLE_FONT_SIZE = Enum.FontSize.Size24 -- if you change CHAT_BUBBLE_FONT_SIZE_INT please change this to match
local CHAT_BUBBLE_FONT_SIZE_INT = 24 -- if you change CHAT_BUBBLE_FONT_SIZE please change this to match
local CHAT_BUBBLE_LINE_HEIGHT = CHAT_BUBBLE_FONT_SIZE_INT + 10
local CHAT_BUBBLE_TAIL_HEIGHT = 14
local CHAT_BUBBLE_WIDTH_PADDING = 30
local CHAT_BUBBLE_PADDING = 12
local CHAT_BUBBLE_FADE_SPEED = 1.5

local BILLBOARD_MAX_WIDTH = 400
local BILLBOARD_MAX_HEIGHT = 250	--This limits the number of bubble chats that you see above characters

local ELIPSES = "..."
local MaxChatMessageLength = 128 -- max chat message length, including null terminator and elipses.
local MaxChatMessageLengthExclusive = MaxChatMessageLength - getMessageLength(ELIPSES) - 1

local NEAR_BUBBLE_DISTANCE = 65	--previously 45
local MAX_BUBBLE_DISTANCE = 100	--previously 80

--[[ END OF SCRIPT VARIABLES ]]


-- [[ SCRIPT ENUMS ]]
local BubbleColor = {	WHITE = "dub",
					BLUE = "blu",
					GREEN = "gre",
					RED = "red" }

--[[ END OF SCRIPT ENUMS ]]

-- This screenGui exists so that the billboardGui is not deleted when the PlayerGui is reset.
local BubbleChatScreenGui = Instance.new("ScreenGui")
BubbleChatScreenGui.Name = "BubbleChat"
BubbleChatScreenGui.ResetOnSpawn = false
BubbleChatScreenGui.Parent = PlayerGui

--[[ FUNCTIONS ]]

local function lerpLength(msg, min, max)
	return min + (max - min) * math.min(getMessageLength(msg) / 75.0, 1.0)
end

local function createFifo()
	local this = {}
	this.data = {}

	local emptyEvent = Instance.new("BindableEvent")
	this.Emptied = emptyEvent.Event

	function this:Size()
		return #this.data
	end

	function this:Empty()
		return this:Size() <= 0
	end

	function this:PopFront()
		table.remove(this.data, 1)
		if this:Empty() then emptyEvent:Fire() end
	end

	function this:Front()
		return this.data[1]
	end

	function this:Get(index)
		return this.data[index]
	end

	function this:PushBack(value)
		table.insert(this.data, value)
	end

	function this:GetData()
		return this.data
	end

	return this
end

local function createCharacterChats()
	local this = {}

	this.Fifo = createFifo()
	this.BillboardGui = nil

	return this
end

local function createMap()
	local this = {}
	this.data = {}
	local count = 0

	function this:Size()
		return count
	end

	function this:Erase(key)
		if this.data[key] then count = count - 1 end
		this.data[key] = nil
	end

	function this:Set(key, value)
		this.data[key] = value
		if value then count = count + 1 end
	end

	function this:Get(key)
		if not key then return end
		if not this.data[key] then
			this.data[key] = createCharacterChats()
			local emptiedCon = nil
			emptiedCon = this.data[key].Fifo.Emptied:connect(function()
				emptiedCon:disconnect()
				this:Erase(key)
			end)
		end
		return this.data[key]
	end

	function this:GetData()
		return this.data
	end

	return this
end

local function createChatLine(message, bubbleColor, isLocalPlayer)
	local this = {}

	function this:ComputeBubbleLifetime(msg, isSelf)
		if isSelf then
			return lerpLength(msg, 8, 15)
		else
			return lerpLength(msg, 12, 20)
		end
	end

	this.Origin = nil
	this.RenderBubble = nil
	this.Message = message
	this.BubbleDieDelay = this:ComputeBubbleLifetime(message, isLocalPlayer)
	this.BubbleColor = bubbleColor
	this.IsLocalPlayer = isLocalPlayer

	return this
end

local function createPlayerChatLine(player, message, isLocalPlayer)
	local this = createChatLine(message, BubbleColor.WHITE, isLocalPlayer)

	if player then
		this.User = player.Name
		this.Origin = player.Character
	end

	return this
end

local function createGameChatLine(origin, message, isLocalPlayer, bubbleColor)
	local this = createChatLine(message, bubbleColor, isLocalPlayer)
	this.Origin = origin

	return this
end

function createChatBubbleMain(filePrefix, sliceRect)
	local chatBubbleMain = Instance.new("ImageLabel")
	chatBubbleMain.Name = "ChatBubble"
	chatBubbleMain.ScaleType = Enum.ScaleType.Slice
	chatBubbleMain.SliceCenter = sliceRect
	chatBubbleMain.Image = "rbxasset://textures/" .. tostring(filePrefix) .. ".png"
	chatBubbleMain.BackgroundTransparency = 1
	chatBubbleMain.BorderSizePixel = 0
	chatBubbleMain.Size = UDim2.new(1.0, 0, 1.0, 0)
	chatBubbleMain.Position = UDim2.new(0, 0, 0, 0)

	return chatBubbleMain
end

function createChatBubbleTail(position, size)
	local chatBubbleTail = Instance.new("ImageLabel")
	chatBubbleTail.Name = "ChatBubbleTail"
	chatBubbleTail.Image = "rbxasset://textures/ui/dialog_tail.png"
	chatBubbleTail.BackgroundTransparency = 1
	chatBubbleTail.BorderSizePixel = 0
	chatBubbleTail.Position = position
	chatBubbleTail.Size = size

	return chatBubbleTail
end

function createChatBubbleWithTail(filePrefix, position, size, sliceRect)
	local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)

	local chatBubbleTail = createChatBubbleTail(position, size)
	chatBubbleTail.Parent = chatBubbleMain

	return chatBubbleMain
end

function createScaledChatBubbleWithTail(filePrefix, frameScaleSize, position, sliceRect)
	local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)

	local frame = Instance.new("Frame")
	frame.Name = "ChatBubbleTailFrame"
	frame.BackgroundTransparency = 1
	frame.SizeConstraint = Enum.SizeConstraint.RelativeXX
	frame.Position = UDim2.new(0.5, 0, 1, 0)
	frame.Size = UDim2.new(frameScaleSize, 0, frameScaleSize, 0)
	frame.Parent = chatBubbleMain

	local chatBubbleTail = createChatBubbleTail(position, UDim2.new(1, 0, 0.5, 0))
	chatBubbleTail.Parent = frame

	return chatBubbleMain
end

function createChatImposter(filePrefix, dotDotDot, yOffset)
	local result = Instance.new("ImageLabel")
	result.Name = "DialogPlaceholder"
	result.Image = "rbxasset://textures/" .. tostring(filePrefix) .. ".png"
	result.BackgroundTransparency = 1
	result.BorderSizePixel = 0
	result.Position = UDim2.new(0, 0, -1.25, 0)
	result.Size = UDim2.new(1, 0, 1, 0)

	local image = Instance.new("ImageLabel")
	image.Name = "DotDotDot"
	image.Image = "rbxasset://textures/" .. tostring(dotDotDot) .. ".png"
	image.BackgroundTransparency = 1
	image.BorderSizePixel = 0
	image.Position = UDim2.new(0.001, 0, yOffset, 0)
	image.Size = UDim2.new(1, 0, 0.7, 0)
	image.Parent = result

	return result
end


local this = {}
this.ChatBubble = {}
this.ChatBubbleWithTail = {}
this.ScalingChatBubbleWithTail = {}
this.CharacterSortedMsg = createMap()

-- init chat bubble tables
local function initChatBubbleType(chatBubbleType, fileName, imposterFileName, isInset, sliceRect)
	this.ChatBubble[chatBubbleType] = createChatBubbleMain(fileName, sliceRect)
	this.ChatBubbleWithTail[chatBubbleType] = createChatBubbleWithTail(fileName, UDim2.new(0.5, -CHAT_BUBBLE_TAIL_HEIGHT, 1, isInset and -1 or 0), UDim2.new(0, 30, 0, CHAT_BUBBLE_TAIL_HEIGHT), sliceRect)
	this.ScalingChatBubbleWithTail[chatBubbleType] = createScaledChatBubbleWithTail(fileName, 0.5, UDim2.new(-0.5, 0, 0, isInset and -1 or 0), sliceRect)
end

initChatBubbleType(BubbleColor.WHITE,	"ui/dialog_white",	"ui/chatBubble_white_notify_bkg", 	false,	Rect.new(5,5,15,15))
initChatBubbleType(BubbleColor.BLUE,	"ui/dialog_blue",	"ui/chatBubble_blue_notify_bkg",	true, 	Rect.new(7,7,33,33))
initChatBubbleType(BubbleColor.RED,		"ui/dialog_red",	"ui/chatBubble_red_notify_bkg",		true,	Rect.new(7,7,33,33))
initChatBubbleType(BubbleColor.GREEN,	"ui/dialog_green",	"ui/chatBubble_green_notify_bkg",	true,	Rect.new(7,7,33,33))

function this:SanitizeChatLine(msg)
	if getMessageLength(msg) > MaxChatMessageLengthExclusive then
		local byteOffset = utf8.offset(msg, MaxChatMessageLengthExclusive + getMessageLength(ELIPSES) + 1) - 1
		return string.sub(msg, 1, byteOffset)
	else
		return msg
	end
end

local function createBillboardInstance(adornee)
	local billboardGui = Instance.new("BillboardGui")
	billboardGui.Adornee = adornee
	billboardGui.Size = UDim2.new(0, BILLBOARD_MAX_WIDTH, 0, BILLBOARD_MAX_HEIGHT)
	billboardGui.StudsOffset = Vector3.new(0, 1.5, 2)
	billboardGui.Parent = BubbleChatScreenGui

	local billboardFrame = Instance.new("Frame")
	billboardFrame.Name = "BillboardFrame"
	billboardFrame.Size = UDim2.new(1, 0, 1, 0)
	billboardFrame.Position = UDim2.new(0, 0, -0.5, 0)
	billboardFrame.BackgroundTransparency = 1
	billboardFrame.Parent = billboardGui

	local billboardChildRemovedCon = nil
	billboardChildRemovedCon = billboardFrame.ChildRemoved:connect(function()
		if #billboardFrame:GetChildren() <= 1 then
			billboardChildRemovedCon:disconnect()
			billboardGui:Destroy()
		end
	end)

	this:CreateSmallTalkBubble(BubbleColor.WHITE).Parent = billboardFrame

	return billboardGui
end

function this:CreateBillboardGuiHelper(instance, onlyCharacter)
	if instance and not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
		if not onlyCharacter then
			if instance:IsA("BasePart") then
				-- Create a new billboardGui object attached to this player
				local billboardGui = createBillboardInstance(instance)
				this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
				return
			end
		end

		if instance:IsA("Model") then
			local head = instance:FindFirstChild("Head")
			if head and head:IsA("BasePart") then
				-- Create a new billboardGui object attached to this player
				local billboardGui = createBillboardInstance(head)
				this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
			end
		end
	end
end

local function distanceToBubbleOrigin(origin)
	if not origin then return 100000 end

	return (origin.Position - game.Workspace.CurrentCamera.CoordinateFrame.p).magnitude
end

local function isPartOfLocalPlayer(adornee)
	if adornee and PlayersService.LocalPlayer.Character then
		return adornee:IsDescendantOf(PlayersService.LocalPlayer.Character)
	end
end

function this:SetBillboardLODNear(billboardGui)
	local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
	billboardGui.Size = UDim2.new(0, BILLBOARD_MAX_WIDTH, 0, BILLBOARD_MAX_HEIGHT)
	billboardGui.StudsOffset = Vector3.new(0, isLocalPlayer and 1.5 or 2.5, isLocalPlayer and 2 or 0.1)
	billboardGui.Enabled = true
	local billChildren = billboardGui.BillboardFrame:GetChildren()
	for i = 1, #billChildren do
		billChildren[i].Visible = true
	end
	billboardGui.BillboardFrame.SmallTalkBubble.Visible = false
end

function this:SetBillboardLODDistant(billboardGui)
	local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
	billboardGui.Size = UDim2.new(4, 0, 3, 0)
	billboardGui.StudsOffset = Vector3.new(0, 3, isLocalPlayer and 2 or 0.1)
	billboardGui.Enabled = true
	local billChildren = billboardGui.BillboardFrame:GetChildren()
	for i = 1, #billChildren do
		billChildren[i].Visible = false
	end
	billboardGui.BillboardFrame.SmallTalkBubble.Visible = true
end

function this:SetBillboardLODVeryFar(billboardGui)
	billboardGui.Enabled = false
end

function this:SetBillboardGuiLOD(billboardGui, origin)
	if not origin then return end

	if origin:IsA("Model") then
		local head = origin:FindFirstChild("Head")
		if not head then origin = origin.PrimaryPart
		else origin = head end
	end

	local bubbleDistance = distanceToBubbleOrigin(origin)

	if bubbleDistance < NEAR_BUBBLE_DISTANCE then
		this:SetBillboardLODNear(billboardGui)
	elseif bubbleDistance >= NEAR_BUBBLE_DISTANCE and bubbleDistance < MAX_BUBBLE_DISTANCE then
		this:SetBillboardLODDistant(billboardGui)
	else
		this:SetBillboardLODVeryFar(billboardGui)
	end
end

function this:CameraCFrameChanged()
	for index, value in pairs(this.CharacterSortedMsg:GetData()) do
		local playerBillboardGui = value["BillboardGui"]
		if playerBillboardGui then this:SetBillboardGuiLOD(playerBillboardGui, index) end
	end
end

function this:CreateBubbleText(message, shouldAutoLocalize)
	local bubbleText = Instance.new("TextLabel")
	bubbleText.Name = "BubbleText"
	bubbleText.BackgroundTransparency = 1

	if UserFixBubbleChatText then
		bubbleText.Size = UDim2.fromScale(1, 1)
	else
		bubbleText.Position = UDim2.new(0, CHAT_BUBBLE_WIDTH_PADDING / 2, 0, 0)
		bubbleText.Size = UDim2.new(1, -CHAT_BUBBLE_WIDTH_PADDING, 1, 0)
	end

	bubbleText.Font = CHAT_BUBBLE_FONT
	bubbleText.ClipsDescendants = true
	bubbleText.TextWrapped = true
	bubbleText.FontSize = CHAT_BUBBLE_FONT_SIZE
	bubbleText.Text = message
	bubbleText.Visible = false
	bubbleText.AutoLocalize = shouldAutoLocalize

	if UserFixBubbleChatText then
		local padding = Instance.new("UIPadding")
		padding.PaddingTop = UDim.new(0, CHAT_BUBBLE_PADDING)
		padding.PaddingRight = UDim.new(0, CHAT_BUBBLE_PADDING)
		padding.PaddingBottom = UDim.new(0, CHAT_BUBBLE_PADDING)
		padding.PaddingLeft = UDim.new(0, CHAT_BUBBLE_PADDING)
		padding.Parent = bubbleText
	end

	return bubbleText
end

function this:CreateSmallTalkBubble(chatBubbleType)
	local smallTalkBubble = this.ScalingChatBubbleWithTail[chatBubbleType]:Clone()
	smallTalkBubble.Name = "SmallTalkBubble"
	smallTalkBubble.AnchorPoint = Vector2.new(0, 0.5)
	smallTalkBubble.Position = UDim2.new(0, 0, 0.5, 0)
	smallTalkBubble.Visible = false
	local text = this:CreateBubbleText("...")
	text.TextScaled = true
	text.TextWrapped = false
	text.Visible = true
	text.Parent = smallTalkBubble

	return smallTalkBubble
end

function this:UpdateChatLinesForOrigin(origin, currentBubbleYPos)
	local bubbleQueue = this.CharacterSortedMsg:Get(origin).Fifo
	local bubbleQueueSize = bubbleQueue:Size()
	local bubbleQueueData = bubbleQueue:GetData()
	if #bubbleQueueData <= 1 then return end

	for index = (#bubbleQueueData - 1), 1, -1 do
		local value = bubbleQueueData[index]
		local bubble = value.RenderBubble
		if not bubble then return end
		local bubblePos = bubbleQueueSize - index + 1

		if bubblePos > 1 then
			local tail = bubble:FindFirstChild("ChatBubbleTail")
			if tail then tail:Destroy() end
			local bubbleText = bubble:FindFirstChild("BubbleText")
			if bubbleText then bubbleText.TextTransparency = 0.5 end
		end

		local udimValue = UDim2.new( bubble.Position.X.Scale, bubble.Position.X.Offset,
									1, currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT)
		bubble:TweenPosition(udimValue, Enum.EasingDirection.Out, Enum.EasingStyle.Bounce, 0.1, true)
		currentBubbleYPos = currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT
	end
end

function this:DestroyBubble(bubbleQueue, bubbleToDestroy)
	if not bubbleQueue then return end
	if bubbleQueue:Empty() then return end

	local bubble = bubbleQueue:Front().RenderBubble
	if not bubble then
		bubbleQueue:PopFront()
	 	return
	end

	spawn(function()
		while bubbleQueue:Front().RenderBubble ~= bubbleToDestroy do
			wait()
		end

		bubble = bubbleQueue:Front().RenderBubble

		local timeBetween = 0
		local bubbleText = bubble:FindFirstChild("BubbleText")
		local bubbleTail = bubble:FindFirstChild("ChatBubbleTail")

		while bubble and bubble.ImageTransparency < 1 do
			timeBetween = wait()
			if bubble then
				local fadeAmount = timeBetween * CHAT_BUBBLE_FADE_SPEED
				bubble.ImageTransparency = bubble.ImageTransparency + fadeAmount
				if bubbleText then bubbleText.TextTransparency = bubbleText.TextTransparency + fadeAmount end
				if bubbleTail then bubbleTail.ImageTransparency = bubbleTail.ImageTransparency + fadeAmount end
			end
		end

		if bubble then
			bubble:Destroy()
			bubbleQueue:PopFront()
		end
	end)
end

function this:CreateChatLineRender(instance, line, onlyCharacter, fifo, shouldAutoLocalize)
	if not instance then return end

	if not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
		this:CreateBillboardGuiHelper(instance, onlyCharacter)
	end

	local billboardGui = this.CharacterSortedMsg:Get(instance)["BillboardGui"]
	if billboardGui then
		local chatBubbleRender = this.ChatBubbleWithTail[line.BubbleColor]:Clone()
		chatBubbleRender.Visible = false
		local bubbleText = this:CreateBubbleText(line.Message, shouldAutoLocalize)

		bubbleText.Parent = chatBubbleRender
		chatBubbleRender.Parent = billboardGui.BillboardFrame

		line.RenderBubble = chatBubbleRender

		local currentTextBounds = TextService:GetTextSize(
				bubbleText.Text, CHAT_BUBBLE_FONT_SIZE_INT, CHAT_BUBBLE_FONT,
				Vector2.new(BILLBOARD_MAX_WIDTH, BILLBOARD_MAX_HEIGHT))
		local numOflines = (currentTextBounds.Y / CHAT_BUBBLE_FONT_SIZE_INT)

		if UserFixBubbleChatText then
			-- Need to use math.ceil to round up on retina displays
			local width = math.ceil(currentTextBounds.X + CHAT_BUBBLE_PADDING * 2)
			local height = numOflines * CHAT_BUBBLE_LINE_HEIGHT

			-- prep chat bubble for tween
			chatBubbleRender.Size = UDim2.fromOffset(0, 0)
			chatBubbleRender.Position = UDim2.fromScale(0.5, 1)

			chatBubbleRender:TweenSizeAndPosition(
				UDim2.fromOffset(width, height),
				UDim2.new(0.5, -width / 2, 1, -height),
				Enum.EasingDirection.Out,
				Enum.EasingStyle.Elastic,
				0.1,
				true,
				function()
					bubbleText.Visible = true
				end
			)

			-- todo: remove when over max bubbles
			this:SetBillboardGuiLOD(billboardGui, line.Origin)
			this:UpdateChatLinesForOrigin(line.Origin, -height)
		else
			local bubbleWidthScale = math.max((currentTextBounds.X + CHAT_BUBBLE_WIDTH_PADDING) / BILLBOARD_MAX_WIDTH, 0.1)

			-- prep chat bubble for tween
			chatBubbleRender.Size = UDim2.new(0, 0, 0, 0)
			chatBubbleRender.Position = UDim2.new(0.5, 0, 1, 0)

			local newChatBubbleOffsetSizeY = numOflines * CHAT_BUBBLE_LINE_HEIGHT

			chatBubbleRender:TweenSizeAndPosition(UDim2.new(bubbleWidthScale, 0, 0, newChatBubbleOffsetSizeY),
													UDim2.new( (1 - bubbleWidthScale) / 2, 0, 1, -newChatBubbleOffsetSizeY),
													Enum.EasingDirection.Out, Enum.EasingStyle.Elastic, 0.1, true,
													function() bubbleText.Visible = true end)

			-- todo: remove when over max bubbles
			this:SetBillboardGuiLOD(billboardGui, line.Origin)
			this:UpdateChatLinesForOrigin(line.Origin, -newChatBubbleOffsetSizeY)
		end

		delay(line.BubbleDieDelay, function()
			this:DestroyBubble(fifo, chatBubbleRender)
		end)
	end
end

function this:OnPlayerChatMessage(sourcePlayer, message, targetPlayer)

	if not this:BubbleChatEnabled() then return end

	local localPlayer = PlayersService.LocalPlayer
	local fromOthers = localPlayer ~= nil and sourcePlayer ~= localPlayer

	local safeMessage = this:SanitizeChatLine(message)

	local line = createPlayerChatLine(sourcePlayer, safeMessage, not fromOthers)

	if sourcePlayer and line.Origin then
		local fifo = this.CharacterSortedMsg:Get(line.Origin).Fifo
		fifo:PushBack(line)
		--Game chat (badges) won't show up here
		this:CreateChatLineRender(sourcePlayer.Character, line, true, fifo, false)
	end
end

function this:OnGameChatMessage(origin, message, color)
	-- Prevents conflicts with the new bubble chat if it is enabled
	if UserRoactBubbleChatBeta or (UserPreventOldBubbleChatOverlap and ChatService.BubbleChatEnabled) then
		return
	end

	local localPlayer = PlayersService.LocalPlayer
	local fromOthers = localPlayer ~= nil and (localPlayer.Character ~= origin)

	local bubbleColor = BubbleColor.WHITE

	if color == Enum.ChatColor.Blue then bubbleColor = BubbleColor.BLUE
	elseif color == Enum.ChatColor.Green then bubbleColor = BubbleColor.GREEN
	elseif color == Enum.ChatColor.Red then bubbleColor = BubbleColor.RED end

	local safeMessage = this:SanitizeChatLine(message)
	local line = createGameChatLine(origin, safeMessage, not fromOthers, bubbleColor)

	this.CharacterSortedMsg:Get(line.Origin).Fifo:PushBack(line)
	if UserShouldLocalizeGameChatBubble then
		this:CreateChatLineRender(origin, line, false, this.CharacterSortedMsg:Get(line.Origin).Fifo, true)
	else
		this:CreateChatLineRender(origin, line, false, this.CharacterSortedMsg:Get(line.Origin).Fifo, false)
	end
end

function this:BubbleChatEnabled()
	if UserRoactBubbleChatBeta or (UserPreventOldBubbleChatOverlap and ChatService.BubbleChatEnabled) then
		return false
	end
	local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
	if clientChatModules then
		local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
		if chatSettings then
			chatSettings = require(chatSettings)
			if chatSettings.BubbleChatEnabled ~= nil then
				return chatSettings.BubbleChatEnabled
			end
		end
	end
	return PlayersService.BubbleChat
end

function this:ShowOwnFilteredMessage()
	local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
	if clientChatModules then
		local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
		if chatSettings then
			chatSettings = require(chatSettings)
			return chatSettings.ShowUserOwnFilteredMessage
		end
	end
	return false
end

function findPlayer(playerName)
	for i,v in pairs(PlayersService:GetPlayers()) do
		if v.Name == playerName then
			return v
		end
	end
end

ChatService.Chatted:connect(function(origin, message, color) this:OnGameChatMessage(origin, message, color) end)

local cameraChangedCon = nil
if game.Workspace.CurrentCamera then
	cameraChangedCon = game.Workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function(prop) this:CameraCFrameChanged() end)
end

game.Workspace.Changed:connect(function(prop)
	if prop == "CurrentCamera" then
		if cameraChangedCon then cameraChangedCon:disconnect() end
		if game.Workspace.CurrentCamera then
			cameraChangedCon = game.Workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function(prop) this:CameraCFrameChanged() end)
		end
	end
end)


local AllowedMessageTypes = nil

function getAllowedMessageTypes()
	if AllowedMessageTypes then
		return AllowedMessageTypes
	end
	local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
	if clientChatModules then
		local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
		if chatSettings then
			chatSettings = require(chatSettings)
			if chatSettings.BubbleChatMessageTypes then
				AllowedMessageTypes = chatSettings.BubbleChatMessageTypes
				return AllowedMessageTypes
			end
		end
		local chatConstants = clientChatModules:FindFirstChild("ChatConstants")
		if chatConstants then
			chatConstants = require(chatConstants)
			AllowedMessageTypes = {chatConstants.MessageTypeDefault, chatConstants.MessageTypeWhisper}
		end
		return AllowedMessageTypes
	end
	return {"Message", "Whisper"}
end

function checkAllowedMessageType(messageData)
	local allowedMessageTypes = getAllowedMessageTypes()
	for i = 1, #allowedMessageTypes do
		if allowedMessageTypes[i] == messageData.MessageType then
			return true
		end
	end
	return false
end

local ChatEvents = ReplicatedStorage:WaitForChild("DefaultChatSystemChatEvents")
local OnMessageDoneFiltering = ChatEvents:WaitForChild("OnMessageDoneFiltering")
local OnNewMessage = ChatEvents:WaitForChild("OnNewMessage")

OnNewMessage.OnClientEvent:connect(function(messageData, channelName)
	if not checkAllowedMessageType(messageData) then
		return
	end

	local sender = findPlayer(messageData.FromSpeaker)
	if not sender then
		return
	end

	if not messageData.IsFiltered or messageData.FromSpeaker == LocalPlayer.Name then
		if messageData.FromSpeaker ~= LocalPlayer.Name or this:ShowOwnFilteredMessage() then
			return
		end
	end

	this:OnPlayerChatMessage(sender, messageData.Message, nil)
end)

OnMessageDoneFiltering.OnClientEvent:connect(function(messageData, channelName)
	if not checkAllowedMessageType(messageData) then
		return
	end

	local sender = findPlayer(messageData.FromSpeaker)
	if not sender then
		return
	end

	if messageData.FromSpeaker == LocalPlayer.Name and not this:ShowOwnFilteredMessage() then
		return
	end

	this:OnPlayerChatMessage(sender, messageData.Message, nil)
end)

Thats normal?

Also its rate /s what does that have to do with networking?

Also unless you actually see any performance drops in game theres no reason to be worried

image

Always been like this, no need for concern?

Might just be your wifi

I know it’s not my wifi effecting the network receive as when I join some games like ER:LC for example, the network receive is green (good) and when I join an empty baseplate it is red (bad). On my game I am creating, when ever more than one player joins the game is extremely laggy. ER:LC however is perfectly fine. I checked script performance on my game and the only scripts that are running over 10/s is those 2 scripts (RbxCharacterSounds and Bubblechat). All of my other scripts are optimised and are running well below 10/s

What network recieve are you using, the performance stats?

Is this in studio?

Are you sure its one of your script?

Also I doubt its roblox having unefficient scripts, they’ve been used for ages and surely it would a site wide problem if an update caused such bad ping.

Also as I said before, rate /s has nothing to do with networking.

Oh, rate /s has nothing to do with networking? Then why is it that I join erlc the networking receive is green but when I join an empty baseplate the network receive is bad?

Dude these scripts are very performant. They’re running at 30fps, not even half of the typical 60fps you’ll achieve.

And this is micro-optimization. They’re barely even taking up 0.1% activity. That leaves you with 99.9% activity to freely use.

Also. These are local scripts for Client only visuals/sounds meaning there’s, as @legs_v stated (about rate), no correlation between this and network.

1 Like

I don’t know thats why I’m trying to ask what else your doing.

Do you actually notice any difference though? Such as assets not loading or movement being a bit off. Since it just might be the measurement tool your using is inaccurate.

Yes

Join these 2 games and take a look at the network receive (press Shift+F5)
– An empty baseplate (no scripts other than the default roblox scripts)
Empty Baseplate

– ER:LC (A really big game with loads of scripts)
Emergancy Responce | Liberty County

Tell me the network receives for both of these games.

The measurement tool I’m using are the built-in roblox measuring tools

Yea its completely fine for me and @IDoLua

https://gyazo.com/1a01d38f660a677f9111df1df4afb89f

Expected spikes.

Might just be a problem with you

I managed to get this code running below 10/s, working on the rblx sounds one now and I’ll let you know if there is any difference in the network receive, if there isn’t I’ll make a new topic on how to make my network receive yellow-green in my game.

So on the baseplate world, your network receive is green?

Yea as you can see in the link, Its not even visible how low my recv is

image

It’s so green it’s invisible! There’s no receive showing after the initial spike.
image
image

image