Dictionaries
With arrays, you have numerical indexes and any values. This makes it a list, like
array = {
[1] = "First item!",
[2] = "Second item!",
[3] = "Third item!",
[4] = "Fourth item!",
}
You can access these items with array[1]
or array[3]
You can loop over this array using for index, value in pairs(array) do
With dictionaries, you have keys instead of indexes, and they can be anything! A common example is strings:
dictionary = {
["Name"] = "Corecii",
["Color"] = Color3.new(0, 0, 1),
["Goggles"] = true,
}
You can access these items with array["Name"]
or array["Goggles"]
You can loop over this dictionary using for key, value in pairs(dictionary) do
Dictionaries can also have parts as their keys. This means if you save all of your last transparent parts in a dictionary dictionary[part] = true
, you can then use dictionary[some_part] == true
to check if some_part
was made transparent last time.
Similarly, if you make a dictionary of all of the new parts, you can do new_dictionary[some_part] == true
to check if some_part
is obscuring the camera in the new obscuring parts list.
You can use dictionary[part] ~= true
to check if a part is not in one of the dictionaries.
Here is a simple example
local lastDictionary = {}
game:GetService("RunService").RenderStepped:connect(function()
local parts = Camera:GetPartsObscuringTarget({rootPart.CFrame.p},Character:GetChildren())
local newDictionary = {}
for index, part in ipairs(parts) do
part.Transparency = 1
newDictionary[part] = true
end
for part, value in pairs(lastDictionary) do -- `value` will always be `true`; we don't really need it
if newDictionary[part] ~= true then -- check if `part` was *not* in the new parts list
part.Transparency = 0 -- if not in the list, we need to make it visible again
end
end
lastDictionary = newDictionary -- on the next renderstep, it will use our newDictionary to check what parts to make visible
end)
This is not the most optimal example, but it’s good for learning dictionaries.
Here is an optimal example
local partDictionary = {}
game:GetService("RunService").RenderStepped:connect(function()
local parts = Camera:GetPartsObscuringTarget({rootPart.CFrame.p},Character:GetChildren())
for index, part in ipairs(parts) do
part.Transparency = 1
partDictionary[part] = false
end
for part, value in pairs(partDictionary) do -- value will be false if it's in the new parts list, and true if it was in the last one
if value then -- [1]
part.Transparency = 0
partDictionary[part] = nil -- [2]
else
partDictionary[part] = true
end
end
-- we have just removed all previously `true` (last) keys, and set all `false` (new) keys to `true`
-- all of the values in `partDictionary` are `true` now. on the next run, those will be the last-run keys.
-- if it encounters any of the same parts, then `partDictionary[part]` will be set to `false` first, and
-- the only `true` parts left over will be the old ones. then the cycle repeats.
-- this uses only one dictionary and doesn't create a new one every frame
-- creating new tables is not a huge issue, but it's better to avoid it if you know how.
end)
-- [1]:
-- if-then statements check the "truthiness" of values. for example:
-- `if a == true then` is the same as `if a then` when `a` is a true/false value
-- `a == true` actually gives you `true` or `false`, and the `if` checks against that
-- you can even use values like `"Hello World!"`, `5`, or `Workspace`
-- here's the rule:
-- if the value is `false` or `nil`, it's considered `false`
-- if the value is anything else, it's considered `true`
-- [2]:
-- this removes the part from the dictionary
-- it's fine to reassign or remove values from a dictionary in a pairs loop
-- see http://lua-users.org/wiki/TablesTutorial