Hello! I have been trying to create a game with a cartoony style, basically every cube has an outline, done so using the SelectionBox, specifically trying to make the game in a way where it has static colors and no reflections of any kind.
(Note: I did want the game to have shadows at first, but I don’t think it’s even possible to do that with custom materials… A reflectionless cube that still has shadows can be achieved by using a SurfaceGUI but that’d be even more resource heavy, so I am sticking to a shadowless world for now, allows me to disable shadows completely and set the light technology to Compatibility so the game runs better?)
My issue is, more of a concern than anything, I am wondering if the Selection Boxes I use to give these cubes outlines are resource heavy? I could not find any information on that and I am afraid that could be the case, the game will have some physics as well, I am not fully sure what it’s going to be fully about yet, but it will for sure have some demolition mechanics. (I have a system that can actually result in some realistic structure collapsing when I tune it right, and it already has a built-in system that removes cubes after a set amount of time, so it has the potential to fix issues related to being resource heavy.)
I did think about using decals or texture instead but I believe it’d be harder to apply to every single part, along with the complexity of that, plus these decals do reflect light which is something I don’t want, as I want to keep this one tone color.
I guess the best method would be using some kind of script that makes these selection boxes invisible until someone is within a specified amount of studs away from the cube? With my current scripting knowledge I could at most create a script managing one part at once, and paste it into every single part in the game, I don’t think that’d be a good fix to such a thing- Unless there is some way to unload all objects not visible to the player, or just ones far away from the player.
While trying to help I encountered a strange bug where the top face becomes pretty much the Neon material, you can remedy this however by having a bloom with intensity set to 0
This is a custom material with only a roughness map (so you can change the brickcolour all you want), the roughness map is just a white square taken from the toolbox; rbxassetid://5168609593 - the id if you’d like it
It no longer reflects, however light sources will obviously change the colours because thats what lights do
also it can have shadows if you’d like but the no shadows is a vibe
And on the lag part with selection boxes, I’d say try it and find out if it lags!
I feel like it won’t add much to performance.
Wish I could help with the coding part to unload far away selection boxes but I’m not much of a coder and I made a similar script that did that with lights… it was really laggy but I likely went about it wrong.
I did actually try creating a new material with the roughness map set to full white, like R255 G255 B255 / #FFFFFF, but it still somehow had a slight reflection of the sun, as I did test it, it did kind of ruin the vibe I think- unless I did something wrong there for some reason! I will probably stay with the shadowless look because it is indeed quite pretty, and does not require me to use any kind of light sources, and completely disable global shadows and the ability for parts to cast shadows. I am currently playing around with some optimizing scripts to see which one works best- so far I can’t get any to work, some errors pop up. I would post something related to these scripts but I don’t think Building Support is the right place for that-
I know its not the right topic but this might work- (got help from GPT)
I tested it out with lights and selection boxes, it seems to work really well
local script in StarterPlayerScripts
local player = game.Players.LocalPlayer
local function hasSelectionBox(part)
return part:IsA("BasePart") and part:FindFirstChild("SelectionBox") ~= nil -- Checking all BaseParts in Workspace for selectionbox
end
local function updateSelectionBoxes()
local character = player.Character
if not character then
return
end
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
for _, part in ipairs(workspace:GetDescendants()) do
if hasSelectionBox(part) then
local distance = (part.Position - humanoidRootPart.Position).Magnitude
if distance > 100 then -- Range
part.SelectionBox.Visible = false -- Disable the SelectionBox
else
part.SelectionBox.Visible = true -- Enable the SelectionBox
end
end
end
end
player.CharacterAdded:Connect(function(character)
character:WaitForChild("HumanoidRootPart")
updateSelectionBoxes()
end)
player.CharacterRemoving:Connect(function()
updateSelectionBoxes()
end)
while wait(1) do -- Updates every second
updateSelectionBoxes()
end
Tested it, appears to work very well I have to say! Will increase the radius at which it makes the selection box disappear for sure, should be good at reducing the possible lag of far-away structures, along with either enabling streaming and setting it to like, 512 studs, perhaps more, or modifying this script to make cubes disappear at a higher distance, but we’ll see…
I will see if I can also modify this system to make a large selection box appear around structures when you are far away from them, so like, when the structure is not loaded in you can still see a large selection box where it should be, to give the game a simulation-like vibe.
How I think it could work- simply make a large cube that is invisible and has no collisions or anything and put it around a structure, give it a selection box with an unique name, and when you move far enough to make the building unload, a large selection box appears where the building should normally be.
Funnily enough the game looks exactly the same both on lowest and highest graphic settings which could make it pretty lightweight.
Yeah that works perfectly and solves all my issues! I am very thankful for your help. Also, it was very easy to modify this script in such a way that allows me to create a really neat way of rendering the map, thought I could show it here because it’s just cool:
Yes good job. However, from a designer’s point of view, I think it looks great, it’s just the pacing looks a little jittery; mind you I know very little about lua, yet if there’s a way to smooth out the blocks - transparency as you move further away - instead of it suddenly having a quarter of the building vanish. I think it’d look more clean in my opinion; although, as I said, it’s just my preference.
I had a script that does smooth out the way blocks appear, I will find it and attempt to do so-
It sadly only works with one part at a time and I have no idea how to make it affect all cubes at once, this one is for the selection boxes around each part-
local player = game.Players.LocalPlayer
local function hasSelectionBox(part)
return part:IsA("BasePart") and part:FindFirstChild("SelectionBox") ~= nil -- Checking all BaseParts in Workspace for selectionbox
end
local function updateSelectionBoxes()
local character = player.Character
if not character then
return
end
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
for _, part in ipairs(workspace:GetDescendants()) do
if hasSelectionBox(part) then
local distance = (part.Position - humanoidRootPart.Position).Magnitude
if distance > 140 then -- Range
while part.SelectionBox.Transparency < 1 do
part.SelectionBox.Transparency +=0.05
wait()
end
else
while part.SelectionBox.Transparency > 0 do
part.SelectionBox.Transparency -=0.05
wait()
end
end
end
end
end
player.CharacterAdded:Connect(function(character)
character:WaitForChild("HumanoidRootPart")
updateSelectionBoxes()
end)
player.CharacterRemoving:Connect(function()
updateSelectionBoxes()
end)
while wait(1) do -- Updates every second
updateSelectionBoxes()
end
it works, but as I said it unloads only one cube at a time, and with the fact they take like a second to appear, it would take like, over a thousand seconds for the whole thing to unload or load back up.
Video that does show said effect:
I will probably make a new topic on scripting support to see if someone can make it work- that is unless it comes out that such an affect is pretty resource heavy, I would rather avoid that, as I want the game to be lightweight.
Thank you for the idea though! If you are interested in seeing it work as intended you can check out my profile later to see if I made any topic on it.
The issue was that your ‘while wait(1) do’ is set to 1 on the “updateSelectionBoxes” function so it was only 1 at a time
This should work and lag less as it now goes over a table instead of the entire workspace but it might lag if you’re handling 1k parts as it did for me when I tried collusion culling for my plants, try and find out
local player = game.Players.LocalPlayer
local selectionBoxes = {}
local function hasSelectionBox(part)
return part:IsA("BasePart") and part:FindFirstChild("SelectionBox") ~= nil
end
local function updateSelectionBoxes()
local character = player.Character
if not character then
return
end
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
-- Update existing selection boxes
for part, _ in pairs(selectionBoxes) do
if part:IsDescendantOf(workspace) then
local distance = (part.Position - humanoidRootPart.Position).Magnitude
if distance > 140 then
while part.SelectionBox.Transparency < 1 do
part.SelectionBox.Transparency += 0.05
wait()
end
else
while part.SelectionBox.Transparency > 0 do
part.SelectionBox.Transparency -= 0.05
wait()
end
end
else
-- Remove selection box from table if it no longer exists in the workspace
selectionBoxes[part] = nil
end
end
-- Find new selection boxes
for _, part in ipairs(workspace:GetDescendants()) do
if hasSelectionBox(part) and not selectionBoxes[part] then
selectionBoxes[part] = true
end
end
end
player.CharacterAdded:Connect(function(character)
character:WaitForChild("HumanoidRootPart")
updateSelectionBoxes()
end)
player.CharacterRemoving:Connect(function()
updateSelectionBoxes()
end)
while wait(0.05) do -- change number to the refresh rate u want
updateSelectionBoxes()
end
I did try it, appears to work the same way I think? That only one part at a time appears. Although the added modifications could improve how well the script runs perhaps? Developer console is not giving me any kind of errors.