I’m trying to create a palette system in my game so I can have bodies of terrain water that are different colors as my player moves through zones.
I want to cache the default Terrain settings and then apply a diff to them like so:
game.ReplicatedStorage.Sig.ChangePlayerTerrainSettings.OnClientEvent:Connect(function(settings)
-- First apply defaults
game.Workspace.Terrain.WaterColor = Color3.fromRGB(23,166,182)
game.Workspace.Terrain.WaterReflectance = .5
game.Workspace.Terrain.WaterTransparency = .9
game.Workspace.Terrain.WaterWaveSize = .15
game.Workspace.Terrain.WaterWaveSpeed = 10
-- todo material colors?
-- Then modify
if (settings["WaterColor"] ~= nil) then
game.Workspace.Terrain.WaterColor = settings["WaterColor"]
end
if (settings["WaterReflectance"] ~= nil) then
game.Workspace.Terrain.WaterReflectance = settings["WaterReflectance"]
end
if (settings["WaterTransparency"] ~= nil) then
game.Workspace.Terrain.WaterTransparency = settings["WaterTransparency"]
end
if (settings["WaterWaveSize"] ~= nil) then
game.Workspace.Terrain.WaterWaveSize = settings["WaterWaveSize"]
end
if (settings["WaterWaveSpeed"] ~= nil) then
game.Workspace.Terrain.WaterWaveSpeed = settings["WaterWaveSpeed"]
end
end)
But I would love to not have to spell out every single property I want to override. I was surprised that there was no way to simply iterate over all the properties an Instance has.
I searched around here and found other devs doing some crazy stuff to hack around this limitation.
There should be an API like the one that was recently added for Attributes.
One thing that will make the code slightly simpler (short of having a full reflection API) is that the . operator is really syntactic sugar for [string] operator:
t = {Transparency= 0.5} for k,v in pairs(t) do workspace.Part[k] = v end
so, as long as all keys in your table are valid property names, you can use a simple for loop to set every property listed in the table on the given object (without needing to copy-paste lines for every possible property).
If you are willing to only give the users a specific subset of properties that you want to allow them to modify, this is sufficient (just make a table where the properties you want to make edit-able are “whitelisted” by being keys in the table). This might be a reasonable limitation anyway for your usecase (e.g. you may not want users to be able to set other properties of Terrain, like CanCollide, Name, etc.)
I need to play with that idiom. It seems really close to what I tried to do the first time. But I don’t think it gets my code into a 3-liner for loop over properties I want to alter.
I’m open to the possibility that I’m just an idiot. You guys wrote like 1.4M lines of Lua code for player, so if this never came up maybe I’m just slow/bad at programming.
I very much agree. I’ve done this exact thing and had to manually keep a list of Lighting properties (which also means trusting the Properties pane and/or the dev hub).
Even more so, I’ve needed reflection for gui related plugins and scripts. A common action in creating UI in studio is to switch from a TextButton to an ImageButton or some other Instance transformation, but keep all the common properties the same (Size, Position, etc). Which is, as you said, tedious without reflection.