IN THIS ARTICLE
Using EBuses in Lua
Components provide interfaces that allow scripts to send them information and receive notifications when certain actions take place. Communication is established by creating two different objects in Lua: senders and handlers. A sender or a handler is an interface to an
EBus, a communication system used extensively in the O3DE Engine. When a sender is created, it can call functions, which in turn send information to a component. When a handler is created, the component calls certain functions that the Lua script defines. These senders and handlers are created with an entity ID. You can use the entity ID to communicate with components that are attached to entities other than the one the script itself is running on. The main script table always provides a field called entityId
that contains the ID of the entity to which the script is attached. Other entity IDs can be passed to the script through the Properties
interface.
Order of component activation
Keep in mind the following points regarding the order of activation of Lua components:
- Lua components are activated after all C++ components have been activated.
- If an entity has multiple Lua components, there is no guarantee regarding which Lua component is activated first.
Communicating with components
When a Lua script creates a handler object in the OnActivate
function, it notifies a component attached to an entity that it should call the script handler functions when certain events occur. Subsequently, the handler is explicitly disconnected and set back to nil in the OnDeactivate
function. This ensures that processing time is not wasted when the entity attached to the script isn’t active. As long as the entity is active, functions are called by the component at the appropriate time.
You can request information from some event sending functions that return values. The following example script uses the TransformBus
to get the current local transform of the entity and uses the GetLocalTM()
function, which returns a transform object. This object is stored in a variable in the main script table. TransformBus
is used again to reset the transform of the object to the identity.
The following example shows how to use the transform bus.
function samplescript:OnActivate()
-- Retrieve the object's local transform and store it for later use
self.myOldTransform = TransformBus.Event.GetLocalTM(self.entityId)
-- Reset the object's local transform to the identity matrix
TransformBus.Event.SetLocalTM(self.entityId, Transform.CreateIdentity())
end
Communicating with components attached to other entities
You can also send events and create handlers to communicate with components that are attached to other entities. The following example defines a parent entity in the properties table and requests its transform. This allows it to set its transform to that of another entity.
local ParentScriptSample = {
Properties = {
ParentEntity = {default = EntityId()}
}
}
function ParentScriptSample:OnActivate()
if self.Properties.ParentEntity:IsValid() then
self.entityBusHandler = EntityBus.Connect(self, self.Properties.ParentEntity)
end
end
function ParentScriptSample:OnEntityActivated()
local parentTransform = TransformBus.Event.GetLocalTM(self.Properties.ParentEntity)
TransformBus.Event.SetLocalTM(self.entityId, parentTransform)
end
return ParentScriptSample
Important:If you have a Lua script that is attached to an entity that needs to get information from another entity, your script must subscribe to the target entity’sOnEntityActivated
event. Your script should wait for the target entity to be activated before requesting the relevant information. Otherwise, your script might return nil.
Using AZStd::vector and AZStd::array
Vectors and arrays in Lua behave very simarly to tables, with a few limitations. Both vector and array have the following features.
Length Operator #
You can obtain the length of a collection by prefixing the name of the collection with the length operator #
, as in the following example.
#myCollection
Indexing [] To obtain the elements in a collection, use indexing in square brackets as the following syntax shows. Indexing is 1 based, just like Lua tables.
myCollection[index]
Vector
also has the following methods for mutating the collection.
push_back
Use the push_back
method to append elements to the vector, as in the following example.
myCollection:push_back(5)
pop_back
Use the pop_back
method to remove the last element of the vector, as in the following example.
myCollection:pop_back()
clear
Use the clear
method to remove all elements from the vector, as in the following example.
myCollection:clear()
Using AZStd::any
You can pass any Lua primitive type excluding tables to any bus or function that takes AZStd::any
as a parameter (for example, GameplayNotificationBus::OnEventBegin
). You can also pass any type reflected from C++ (for example, vectors or EntityId
values). There is no syntax required to pass a value as an any
-just call the bus or function.
The following example shows the use of AZStd::any
.
GameplayNotificationBus.Broadcast.OnEventBegin(self.eventId, "The value I'd like to pass to the handler")