How to go about displaying a "distance visualizer" to the client without lag?

Hopefully this won’t be too confusing.

I’m working on a project where players can use spells, and each spell uses one of four distances for hit detection: 20, 32, 48, and 64 studs.

The player can press and hold Ctrl to visualize those four ranges in a circle, depicted in the picture below. Letting go of Ctrl will turn this off.

However, my game is already very physics-heavy, and viewing this visualizer will cause a split second lag spike. Enabling the micro profile will show the spike (writing this on my phone right now so I don’t have the screenshot).

Is there any methods I could use where I can achieve this without lag spikes? I’ve tried the following and all have not fixed the lag spikes:

  • Use a union instead of 4 cylinders: Nothing changes
  • Added a denounce whenever Ctrl is held down: Lag spikes still occur when pressing down Ctrl
  • Used decals and changed transparency values on the decal, whilst keeping part transparency at 1: Lag spikes were still there but less noticeable
  • Used a transparency value of 0 instead of 0.8: Less lag spikes but not desired outcome as I want this visualizer to be translucent
1 Like

I’m guessing that also means you tried to keep the cylinders loaded in with a transparency of 1, changing it to be visible when pressing Ctrl?
Maybe it’s also an option to put a small delay in between loading/showing the different cylinders from red to green. Could mask it as just some visual design if it works out.

1 Like

Yeah, I tried keeping the cylinders transparency at 1, and then changing the visibility when pressing Ctrl, still did not stop the lag spikes.

I’m not at my computer right now but even with the cylinders unioned into one piece, toggling that doesn’t change anything.

1 Like

After doing some searching, the most optimal way to minimise the performance on parts is to either delete faces or by pre-loading meshes and then using them. If that does not fix the lag spikes, then perhaps the only other option is to optimize other parts of your game to make room for the distance visualizer.

1 Like

So changing a single property, a single time, on 4 basic parts, causes a lag spike? Something doesn’t sound quite right about that. Could you provide more details to the code/logic behind this?

Now that I’m on my PC here’s what I have right now. It uses an invisible union with a decal that changes which direction it’s facing to simulate a 1-sided part. Lag spikes are less noticeable but still present.

The setup (AbilityVisualizer is irrelevant)
image

This happens all in one LocalScript, CombatClient. It has other functions but they aren’t used for range visualization. First, the code creates the RangePart with the function SetupRangePart:

local function SetupRangePart()
	local Part = script.Ranges:Clone()
	
	local Constraint = Instance.new("RigidConstraint")
	Constraint.Attachment0 = Part.RootRig
	Constraint.Attachment1 = Character:WaitForChild("HumanoidRootPart"):WaitForChild("RootRigAttachment")
	Constraint.Parent = Part
	
	Part.Parent = Character
	return Part
end

-- RangePart is a global variable in the LocalScript
local RangePart = SetupRangePart()

I use ContextActionService to bind the ViewRanges function to LeftAlt (And L1 for console)
ContextActionService:BindAction("ViewRanges", ViewRanges, false, Enum.KeyCode.LeftAlt, Enum.KeyCode.ButtonL1)

Here’s the ViewRanges function:

function ViewRanges(ActionName, InputState, InputObject)
	if InputState == Enum.UserInputState.Begin then
		RangePart.Decal.Face = Enum.NormalId.Left
		RangePart.RangeList.Enabled = true
	elseif InputState == Enum.UserInputState.End then
		RangePart.Decal.Face = Enum.NormalId.Right
		RangePart.RangeList.Enabled = false
	end
end

Whenever the player dies, this function is called to reset some global variables:

local function ResetCharacter(NewCharacter)
	GetInputType()
	
	Character = NewCharacter
	Humanoid = Character:WaitForChild("Humanoid")
	
	DodgeAnimation = Character.Humanoid:LoadAnimation(script:WaitForChild("DodgeAnimation"))
	RangePart = SetupRangePart()

	Character.ChildAdded:Connect(NewChild)
	Character.ChildRemoved:Connect(RemovingChild)
end

Player.CharacterAdded:Connect(ResetCharacter)

Update: The issue resides in the code I provided above and it can’t be with my other scripts. I tested the code I provided in an empty baseplate and the lag spikes still persist.

RobloxStudioBeta_TZo8vISxff