Attributes are now available!
Hey developers,
Over the past year we’ve been working on a new feature called Attributes. Our goal was to provide an efficient way to set and configure parameters for game assets, allowing developers to rapidly iterate and customize key features.
We are excited to announce the launch of the Attributes Studio Beta so that you can try them out and give us feedback before we enable them on production.
How do I enable the beta?
You can enable attributes under the beta features section in studio:
What are Attributes?
Attributes allow you to customize instances with your own data. You can think of them as being similar to properties, but you can create your own for your project.
- Create, view, edit and delete Attributes within the properties widget
- Attributes and their values are saved with your place and assets
- Attributes are replicated with the instance so players can access them immediately
- Changes to Attributes can be viewed in real-time within the properties widget
They are especially useful when collaborating with other developers or testing. You can surface parameters to team members, so that they can be adjusted without requiring a complete understanding of the underlying code and you can view/edit them in real time while testing.
Use Cases
- Weapon with custom parameters (see images below)
- Easily tune a weapon by surfacing parameters such as fire rate, damage, etc.
- Vehicle tuning
- Surface parameters such as acceleration and max speed
- Additional package or asset metadata
- Include information such as title, description, version
How do you use them?
In Studio
View and Edit Attributes
Create a new Attribute
Rename and Delete Attributes
From Code
-- Adding a new Attribute:
instance:SetAttribute("MyAttribute", myValue)
-- Getting an Attribute:
local myAttribute = instance:GetAttribute("MyAttribute")
-- Removing an Attribute:
instance:SetAttribute("MyAttribute", nil)
-- Changing an Attribute's value:
instance:SetAttribute("MyAttribute", newValue)
-- Getting all Attributes:
local myAttributes = instance:GetAttributes()
--- Listening to an Attribute changing:
instance:GetAttributeChangedSignal("MyAttribute"):Connect(function ()
...
end)
--- Listening to any Attribute changing:
instance.AttributeChanged:Connect(function (attributeName)
...
end)
Examples
Lava with configurable damage
local CollectionService = game:GetService("CollectionService")
local function lavaAdded(instance)
instance.Touched:Connect(function (hit)
local humanoid = hit.Parent:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid:TakeDamage(instance:GetAttribute("Damage"))
end
end)
end
CollectionService:GetInstanceAddedSignal("Lava"):Connect(lavaAdded)
Details
Documentation
You can find the complete API documentation on the developer hub:
Types
For the initial release, the following types are supported:
- string
- boolean
- double
- UDim
- UDim2
- BrickColor
- Color3
- Vector2
- Vector3
- NumberSequence
- ColorSequence
- NumberRange
- Rect
If there are any other types you would like to see supported let us know and please make sure to include clear examples and use cases with your requests.
Name Requirements
When naming attributes, we enforce specific naming conventions for consistency and to help you avoid mistakes. These are:
- Names must only use alphanumeric characters and underscore
- No spaces or unique symbols are allowed
- Strings must be 100 characters or less
- Names are not allowed to start with RBX (reserved for Roblox)
FAQ
When will the feature go live?
What’s the difference between Attributes and value objects?
Attributes are a part of the instance they are assigned to. You never need to wait for them to replicate or traverse the instance hierarchy to find them. They are there as soon as you need them.
You can view all Attributes on an instance at once, unlike a value object which only supports a single value and therefore you must look at each individually.
In terms of performance, the difference is mostly negligble with a few exceptions:
- Attributes take up less memory on your device
- Attributes are ~18x faster to create dynamically
- Attributes are ~240x faster to delete
As this features continues to evolve you can expect additional behavior to become available which sets them further apart from value objects.
Is there a limit to the number of attributes I can use in my game?
There is no limit to the number of attributes you can use in your game, however there is a limit to the number that can be saved per-instance. That limit is very big so you should not need to worry about it.
Are they replicated from the client to server?
No. Attributes respect filtering rules, the only exception to this is team-create.
Why can’t Attributes be accessed through the index operator?
When designing the API we considered allowing you to index attributes directly:
local myAttribute = instance.MyAttribute
While this may seem convenient there were a number of reasons we decided against this:
Compatability: We could add a new property with the same name as an attribute, this would break your code which depends on the attribute.
Mutability: For mutable data structures we would need to track changes to them. For example assume Vector3 allowed you to change it’s individual components.
- Should the following code update the attribute?
- Should the update happen twice? (once for X, once for Y)
local myAttribute = instance.MyAttribute
myAttribute.X = 5
myAttribute.Y = 10
By making you call SetAttribute
and GetAttribute
we are always working with a copy of your value, and you are explicitly telling us when to update our copy.
Known Issues
Any issues found during beta will be posted here until they are addressed.
- GetAttribute returns 0 values instead of nil when no value has been assigned
Deleting an instance with the attributes context menu open, and then selecting an option on that menu, will cause a crashIf you filter for any property and change the value, the attributes section will sometimes appear with no attributes (even if attributes were added to the instance)If you use and then clear the filter, the full list of attributes doesn’t reappearMemory increases with each call to the API