Skip to content

CoreObject

CoreObject is an Object placed in the scene hierarchy during edit mode or is part of a template. Usually they'll be a more specific type of CoreObject, but all CoreObjects have these properties and functions:

Properties

Property Name Return Type Description Tags
name string The object's name as seen in the Hierarchy. Read-Write
id string The object's MUID. Read-Only
parent CoreObject The object's parent object, may be nil. Read-Write
visibility Visibility Turn on/off the rendering of an object and its children. Read-Write
collision Collision Turn on/off the collision of an object and its children. Read-Write
cameraCollision Collision Turn on/off the collision of the camera with an object and its children. Read-Write
isEnabled boolean Turn on/off an object and its children completely. Read-Write
isStatic boolean If true, dynamic properties may not be written to, and dynamic functions may not be called. Read-Only
isClientOnly boolean If true, this object was spawned on the client and is not replicated from the server. Read-Only
isServerOnly boolean If true, this object was spawned on the server and is not replicated to clients. Read-Only
isNetworked boolean If true, this object replicates from the server to clients. Read-Only
lifeSpan number Duration after which the object is destroyed. Read-Write
sourceTemplateId string The ID of the template from which this CoreObject was instantiated. 0000000000000000 if this object is not a template. Deinstanced templates also return 0000000000000000. Read-Only

Functions

Function Name Return Type Description Tags
GetTransform() Transform The Transform relative to this object's parent. None
SetTransform(Transform) None The Transform relative to this object's parent. None
GetPosition() Vector3 The position of this object relative to its parent. None
SetPosition(Vector3) None The position of this object relative to its parent. None
GetRotation() Rotation The rotation relative to its parent. None
SetRotation(Rotation) None The rotation relative to its parent. None
GetScale() Vector3 The scale relative to its parent. None
SetScale(Vector3) None The scale relative to its parent. None
GetWorldTransform() Transform The absolute Transform of this object. None
SetWorldTransform(Transform) None The absolute Transform of this object. None
GetWorldPosition() Vector3 The absolute position. None
SetWorldPosition(Vector3) None The absolute position. None
GetWorldRotation() Rotation The absolute rotation. None
SetWorldRotation(Rotation) None The absolute rotation. None
GetWorldScale() Vector3 The absolute scale. None
SetWorldScale(Vector3) None The absolute scale. None
GetVelocity() Vector3 The object's velocity in world space. The velocity vector indicates the direction, with its magnitude expressed in centimeters per second. None
SetVelocity(Vector3) None Set the object's velocity in world space. Only works for physics objects. The velocity vector indicates the direction, with its magnitude expressed in centimeters per second. None
GetAngularVelocity() Vector3 The object's angular velocity in degrees per second. None
SetAngularVelocity(Vector3) None Set the object's angular velocity in degrees per second in world space. Only works for physics objects. None
SetLocalAngularVelocity(Vector3) None Set the object's angular velocity in degrees per second in local space. Only works for physics objects. None
GetReference() CoreObjectReference Returns a CoreObjectReference pointing at this object. None
GetChildren() Array<CoreObject> Returns a table containing the object's children, may be empty. Order is not guaranteed to match what is in the hierarchy. None
IsVisibleInHierarchy() boolean Returns true if this object and all of its ancestors are visible. None
IsCollidableInHierarchy() boolean Returns true if this object and all of its ancestors are collidable. None
IsCameraCollidableInHierarchy() boolean Returns true if this object and all of its ancestors are collidable with the camera. None
IsEnabledInHierarchy() boolean Returns true if this object and all of its ancestors are enabled. None
FindAncestorByName(string name) CoreObject Returns the first parent or ancestor whose name matches the provided name. If none match, returns nil. None
FindChildByName(string name) CoreObject Returns the first immediate child whose name matches the provided name. If none match, returns nil. None
FindDescendantByName(string name) CoreObject Returns the first child or descendant whose name matches the provided name. If none match, returns nil. None
FindDescendantsByName(string name) Array<CoreObject> Returns the descendants whose name matches the provided name. If none match, returns an empty table. None
FindAncestorByType(string typeName) CoreObject Returns the first parent or ancestor whose type is or extends the specified type. For example, calling FindAncestorByType('CoreObject') will return the first ancestor that is any type of CoreObject, while FindAncestorByType('StaticMesh') will only return the first mesh. If no ancestors match, returns nil. None
FindChildByType(string typeName) CoreObject Returns the first immediate child whose type is or extends the specified type. If none match, returns nil. None
FindDescendantByType(string typeName) CoreObject Returns the first child or descendant whose type is or extends the specified type. If none match, returns nil. None
FindDescendantsByType(string typeName) Array<CoreObject> Returns the descendants whose type is or extends the specified type. If none match, returns an empty table. None
FindTemplateRoot() CoreObject If the object is part of a template, returns the root object of the template (which may be itself). If not part of a template, returns nil. None
IsAncestorOf(CoreObject) boolean Returns true if this CoreObject is a parent somewhere in the hierarchy above the given parameter object. False otherwise. None
GetCustomProperties() table Returns a table containing the names and values of all custom properties on a CoreObject. None
GetCustomProperty(string propertyName) value, boolean Gets data which has been added to an object using the custom property system. Returns the value, which can be an integer, number, boolean, string, Vector2, Vector3, Vector4, Rotation, Color, CoreObjectReference, a MUID string (for Asset References), NetReference, or nil if not found. Second return value is a boolean, true if found and false if not. None
IsCustomPropertyDynamic(string propertyName) boolean Returns true if the named custom property exists and is marked as dynamic. Otherwise, returns false. None
SetCustomProperty(string propertyName, value) boolean Sets the named custom property if it is marked as dynamic and the object it belongs to is server-side networked or in a client/server context. The value must match the existing type of the property, with the exception of CoreObjectReference properties (which accept a CoreObjectReference or a CoreObject) and Asset Reference properties (which accept a string MUID). AssetReferences, CoreObjectReferences, and NetReferences also accept nil to clear their value, although GetCustomProperty() will still return an unassigned CoreObjectReference or NetReference rather than nil. (See the .isAssigned property on those types.) None
SetNetworkedCustomProperty(string propertyName, value) boolean This function is deprecated. Please use CoreObject:SetCustomProperty() instead. Sets the named custom property if it is marked as replicated and the object it belongs to is server-side networked. The value must match the existing type of the property, with the exception of CoreObjectReference properties (which accept a CoreObjectReference or a CoreObject) and Asset Reference properties (which accept a string MUID). AssetReferences, CoreObjectReferences, and NetReferences also accept nil to clear their value, although GetCustomProperty() will still return an unassigned CoreObjectReference or NetReference rather than nil. (See the .isAssigned property on those types.) Deprecated
AttachToPlayer(Player, string socketName) None Attaches a CoreObject to a Player at a specified socket. The CoreObject will be un-parented from its current hierarchy and its parent property will be nil. See Socket Names for the list of possible values. None
AttachToLocalView() None Attaches a CoreObject to the local player's camera. Reminder to turn off the object's collision otherwise it will cause camera to jitter. Client-Only
Detach() None Detaches a CoreObject from any player it has been attached to, or from its parent object. None
GetAttachedToSocketName() string Returns the name of the socket this object is attached to. None
MoveTo(Vector3, number, [boolean]) None Smoothly moves the object to the target location over a given amount of time (seconds). Third parameter specifies if the given destination is in local space (true) or world space (false). None
RotateTo(Rotation/Quaternion, number, [boolean]) None Smoothly rotates the object to the target orientation over a given amount of time. Third parameter specifies if given rotation is in local space (true) or world space (false). None
ScaleTo(Vector3, number, [boolean]) None Smoothly scales the object to the target scale over a given amount of time. Third parameter specifies if the given scale is in local space (true) or world space (false). None
MoveContinuous(Vector3, [boolean]) None Smoothly moves the object over time by the given velocity vector. Second parameter specifies if the given velocity is in local space (true) or world space (false). The velocity vector indicates the direction, with its magnitude expressed in centimeters per second. None
RotateContinuous(Rotation/Quaternion, [number, [boolean]]) None Smoothly rotates the object over time by the given rotation (per second). The second parameter is an optional multiplier, for very fast rotations. Third parameter specifies if the given rotation or quaternion is in local space (true) or world space (false (default)). Angular velocity is expressed in degrees per second. None
RotateContinuous(Vector3, [boolean]) None Smoothly rotates the object over time by the given angular velocity. Second parameter specifies whether to interpret the given velocity in local space (true) or world space (false (default)). Angular velocity is expressed in degrees per second. None
ScaleContinuous(Vector3, [boolean]) None Smoothly scales the object over time by the given scale vector per second. Second parameter specifies if the given scale rate is in local space (true) or world space (false). None
StopMove() None Interrupts further movement from MoveTo(), MoveContinuous(), or Follow(). None
StopRotate() None Interrupts further rotation from RotateTo(), RotateContinuous(), LookAtContinuous(), or LookAtLocalView(). None
StopScale() None Interrupts further movement from ScaleTo() or ScaleContinuous(). None
Follow(Object, [number, [number]]) None Follows a CoreObject or Player at a certain speed. If the speed is not supplied it will follow as fast as possible. The third parameter specifies a distance to keep away from the target. None
LookAt(Vector3 position) None Instantly rotates the object to look at the given position. None
LookAtContinuous(Object, [boolean], [number]) None Smoothly rotates a CoreObject to look at another given CoreObject or Player. Second parameter is optional and locks the pitch, default is unlocked. Third parameter is optional and sets how fast it tracks the target (in radians/second). If speed is not supplied it tracks as fast as possible. None
LookAtLocalView([boolean]) None Continuously looks at the local camera. The boolean parameter is optional and locks the pitch. Client-Only
Destroy() None Destroys the object and all descendants. You can check whether an object has been destroyed by calling Object.IsValid(object), which will return true if object is still a valid object, or false if it has been destroyed. None
ReorderBeforeSiblings() None Reorders this object before all of its siblings in the hierarchy. None
ReorderAfterSiblings() None Reorders this object after all of its siblings in the hierarchy. None
ReorderBefore(CoreObject sibling) None Reorders this object just before the specified sibling in the hierarchy. None
ReorderAfter(CoreObject sibling) None Reorders this object just after the specified sibling in the hierarchy. None
IsReplicationEnabled() boolean Returns true if the object has replication enabled, else returns false. Server-Only
SetReplicationEnabled(boolean) None Enables/Disables replication for the networked object. Server-Only
ForceReplication() None If the networked object does not have replication enabled and this call is made, this will force it to replicate its current state. Server-Only

Events

Event Name Return Type Description Tags
childAddedEvent Event<CoreObject parent, CoreObject newChild> Fired when a child is added to this object. None
childRemovedEvent Event<CoreObject parent, CoreObject removedChild> Fired when a child is removed from this object. None
descendantAddedEvent Event<CoreObject ancestor, CoreObject newChild> Fired when a child is added to this object or any of its descendants. None
descendantRemovedEvent Event<CoreObject ancestor, CoreObject removedChild> Fired when a child is removed from this object or any of its descendants. None
destroyEvent Event<CoreObject> Fired when this object is about to be destroyed. None
customPropertyChangedEvent Event<CoreObject owner, string propertyName> Fired whenever any of the dynamic custom properties on this object receive an update. The event is fired on the server and the client. Event payload is the owning object and the name of the property that just changed. None
networkedPropertyChangedEvent Event<CoreObject owner, string propertyName> This event is deprecated. Please use CoreObject.customPropertyChangedEvent instead. Fired whenever any of the networked custom properties on this object receive an update. The event is fired on the server and the client. Event payload is the owning object and the name of the property that just changed. Deprecated

Examples

Example using:

childAddedEvent

This event fires when something gets added as a direct child of an object. (i. e. not a child of a child.)

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local obj = World.SpawnAsset(propCubeTemplate)

local function ChildAdded()
    -- This code will be executed every time a child is added to the object.
    UI.PrintToScreen("A child was added to the object!")
end

obj.childAddedEvent:Connect(ChildAdded)

-- This will cause ChildAdded to execute.
local obj2 = World.SpawnAsset(propCubeTemplate, {parent = obj})

-- This will NOT cause ChildAdded to execute, because obj3 is not a direct child of obj.
local obj3 = World.SpawnAsset(propCubeTemplate, {parent = obj2})

Example using:

childRemovedEvent

This event fires when a direct child of the object is removed.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local obj = World.SpawnAsset(propCubeTemplate)

local function ChildRemoved()
    -- This code will be executed every time a child is removed from the object.
    UI.PrintToScreen("A child was removed from the object!")
end

obj.childRemovedEvent:Connect(ChildRemoved)

local obj2 = World.SpawnAsset(propCubeTemplate, {parent = obj})

-- This will cause ChildRemoved to fire, because we are removing a child from obj.
obj2:Destroy()

Example using:

descendantAddedEvent

This event fires when something gets added as a direct child of an object. (i. e. not a child of a child.)

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local obj = World.SpawnAsset(propCubeTemplate)

local function DescendantAdded()
    -- This code will be executed every time a child is added to the object, or one of its children.
    UI.PrintToScreen("A descendant was added to the object!")
end

obj.descendantAddedEvent:Connect(DescendantAdded)

-- This will cause DescendantAdded to execute.
local obj2 = World.SpawnAsset(propCubeTemplate, {parent = obj})

-- This will also cause DescendantAdded to execute, because obj3 is a descendant of obj.
local obj3 = World.SpawnAsset(propCubeTemplate, {parent = obj2})

Example using:

descendantRemovedEvent

This event fires when a descendant of the object is removed. This is any object that has the object somewhere up the hierarchy tree as a parent.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local obj = World.SpawnAsset(propCubeTemplate)

local function DescendantRemoved()
    -- This code will be executed every time a descendant is removed from the object.
    UI.PrintToScreen("A descendant was removed from the object!")
end

obj.descendantRemovedEvent:Connect(DescendantRemoved)

local obj2 = World.SpawnAsset(propCubeTemplate, {parent = obj})
local obj3 = World.SpawnAsset(propCubeTemplate, {parent = obj2})

-- This will cause DescendantRemoved to fire, because we are removing a descendant from obj.
obj3:Destroy()
-- This will also cause DescendantRemoved to fire, because we are removing a descendant from obj.
obj2:Destroy()

Example using:

destroyEvent

Destroy

lifeSpan

There are several ways of destroying CoreObjects, and noticing when they are destroyed.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")

function OnDestroyListener(obj)
    print(obj.name .. " has been destroyed!")
end

local template1 = World.SpawnAsset(propCubeTemplate)
local template2 = World.SpawnAsset(propCubeTemplate, {parent = template1})

-- You can destroy an object directly, via the Destroy() method.
-- Children are also automatically destroyed when their parent is destroyed.

template1.destroyEvent:Connect(OnDestroyListener)
template2.destroyEvent:Connect(OnDestroyListener)

template1.name = "Template 1"
template2.name = "Template 2"

template1:Destroy()

-- output:
-- Template 2 has been destroyed.
-- Template 1 has been destroyed.

-- You can also set the lifeSpan of objects. They will destroy themselves in
-- that many seconds.
local template3 = World.SpawnAsset(propCubeTemplate)
template3.name = "Template 3"
template3.destroyEvent:Connect(OnDestroyListener)
template3.lifeSpan = 1
Task.Wait(1.5)
-- Template 3 has been destroyed.

-- The timer for lifespans is set when the lifeSpan property is changed.
-- So even though the object has existed for 1 second already, setting the
-- lifeSpan to 0.5 does not immediately destroy it - instead, the object
-- is destroyed 0.5 seconds after the lifeSpan is set.
local template4 = World.SpawnAsset(propCubeTemplate)
template4.name = "Template 4"
template4.destroyEvent:Connect(OnDestroyListener)
Task.Wait(1)
template4.lifeSpan = 0.5
Task.Wait(1)

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Event.Connect | Task.Wait | CoreLua.print


Example using:

AttachToPlayer

AttachToLocalView

Detach

GetAttachedToSocketName

Whether you're building sticky-mines, or costumes, sometimes it is useful to be able to attach a CoreObject directly to a spot on a player.

When attaching an object to a player you need to specify the "socket" you want to attach it to. The list of legal sockets can be found on its own page in the documentation.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local cube = World.SpawnAsset(propCubeTemplate)
cube.collision = Collision.FORCE_OFF

-- attach the cube to the player's head
cube:AttachToPlayer(player, "head")

-- We can also check what socket an object is attached to.
print(cube:GetAttachedToSocketName())   -- Head

-- Alternately, we can ask the player for a list of CoreObjects that
-- are attached to it:
print("Attached objects: ")
for _, v in ipairs(player:GetAttachedObjects()) do
    print(tostring(v.name))
end

cube:Detach()

-- It's also possible to attach objects to the local view on the client.
-- Note that this only works from inside a client context:
cube:AttachToLocalView()

See also: Player.GetAttachedObjects | CoreObject.GetCustomProperty | World.SpawnAsset | CoreLua.print


Example using:

Destroy

A simple example on how to destroy a CoreObject.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
-- This is the object you would like to destroy/remove:
local cube = World.SpawnAsset(propCubeTemplate)

cube:Destroy() -- This will destroy the object.

Example using:

Follow

LookAt

LookAtContinuous

LookAtLocalView

There are some handy convenience functions for animating certain kinds of behaviors. There is a CoreObject:LookAt() function, which forces a CoreObject to rotate itself to be facing a specific point in the world. There is a CoreObject:Follow() function, that tells a CoreObject to follow a set distance and speed behind another object. And there is a CoreObject:LookAtContinuous(), which tells a core object to rotate itself towards another CoreObject or Player, and keep looking at them until stopped.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local movingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, -200, 100)})
local followingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, 0, 100)})
local watchingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, 200, 100)})

-- We can make an object turn to face any given point in the world:
watchingCube:LookAt(movingCube:GetWorldPosition())

-- We can also have an object keep facing a player or object, until we
-- call stopRotate. This example makes a cube move, while an other
-- cube watches it, while yet a third cube tries to follow it. (While
-- staying 200 units away.)
movingCube:MoveTo(movingCube:GetWorldPosition() + Vector3.UP * 1000, 5)
followingCube:Follow(movingCube, 500, 200)
watchingCube:LookAtContinuous(movingCube)
Task.Wait(5)

--[[#Description
    It's also possible to make an object always look at EVERY player. This only works
    on objects that are in a client context, but the `LookAtLocalView` function causes a client-context
    object to always turn and face the local player.
]]
    local watchingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, 200, 100)})
    watchingCube:LookAtLocalView() -- This only works in a client context.

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Vector3.New | Task.Wait


Example using:

GetChildren

FindAncestorByName

FindChildByName

FindDescendantByName

FindDescendantsByName

FindAncestorByType

FindChildByType

FindDescendantByType

FindDescendantsByType

FindTemplateRoot

IsAncestorOf

parent

You can inspect most of the hierarchy at runtime.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local propSampleSoundFX = script:GetCustomProperty("SampleSoundFX")

local template1 = World.SpawnAsset(propCubeTemplate)
local template2 = World.SpawnAsset(propSampleSoundFX, {parent = template1})
local template3 = World.SpawnAsset(propCubeTemplate, {parent = template2})
local template4 = World.SpawnAsset(propSampleSoundFX, {parent = template2})

template1.name = "template1"
template2.name = "template2"
template3.name = "child"
template4.name = "child"

-- The hierarchy should now look like this:
--
-- template 1
--   +-template 2      -- Note that this one is an audio object.
--       +-template 3
--       +-template 4  -- This is also audio

-- We can get references to other things in the tree if we know their string name:
local ancestor = template4:FindAncestorByName("template1")

-- This one only looks at direct children.
local child = template1:FindChildByName("template2")

-- You can also get a list of all direct children:
local childList = template2:GetChildren()

-- CoreObjects are also aware of their own parents, if any:
print(template2.parent.name) -- template1

if ancestor:IsAncestorOf(child) then
    print("This is an ancestor!")
end

-- FindDescendantByName will return the *first* descendant that matches the name.
local descendant = template1:FindDescendantByName("child")
-- descendant now equals template3

-- FindDescendantsByName will return an array of ALL the descendants who match the name.
local descendantList = template1:FindDescendantsByName("child")
-- descendantList is an array that contains {template3, template4}

-- We can also search by object type. template2 is an Audio object, so we can search for it:
local audioDescendant = template1:FindDescendantByType("Audio")
local audioDescendantList = template1:FindDescendantsByType("Audio")
-- audioDescendantList is an array that contains {template2, template4}

-- FindChildByType will only look at direct children.
local child = template1:FindChildByType("Audio")
-- Should give us template2

-- We can search up the tree by type as well:
local ancestorByType = template3:FindAncestorByType("StaticMesh")
-- This one goes all the way up the tree and returns template 1, because template3's direct
-- parent is an Audio object and not a StaticMesh.

-- If we have a reference to an object in a template, we can also find the root of the template.
local templateRoot = template1:FindTemplateRoot()
-- this should just give us back Template1, because it is already the root.

See also: CoreObject.GetCustomProperty | World.SpawnAsset | CoreLua.print


Example using:

GetCustomProperties

GetCustomProperty

Almost any object in the hierarchy can have "custom properties" associated with it. These are values that you can change in the editor, but that scripts can easily access. They're useful for making modular components that can be configured without needing to modify Lua code. You can specify the data type of a custom property, to tell the Core editor what sort of data you plan on storing in there.

In this example, we've added some custom properties onto the script, to demonstrate how to access them.

Specifically, we've added the following custom types to our script:

BestFood : String

NumberOfCats : Int

FavoriteColor : Color

-- We can read from custom properties directly, if we know their name:
-- When you add a custom property, code like this is auto-generated in the
-- inspector window, and can be easily cut-and-pasted into your script.
local propBestFood = script:GetCustomProperty("BestFood")
local propNumberOfCats = script:GetCustomProperty("NumberOfCats")
local propFavoriteColor = script:GetCustomProperty("FavoriteColor")

-- In some cases, a script might not know which custom properties exist.
-- We can request a list of ALL custom properties, in table form:

for propName, propValue in pairs(script:GetCustomProperties()) do
    print("Found property [" .. propName .. "] with value [" .. tostring(propValue) .. "]")
end

See also: CoreLua.print


Example using:

GetTransform

SetTransform

GetPosition

SetPosition

GetRotation

SetRotation

GetScale

SetScale

GetWorldTransform

SetWorldTransform

GetWorldPosition

SetWorldPosition

GetWorldRotation

SetWorldRotation

GetWorldScale

SetWorldScale

One of the most common basic thing you will want to do, is move things around in the world. All CoreObjects have a Transform, which represents where they are, which direction they are facing, and what size they are. You can read or write this, either as a whole Transform object, or by its components. (Scale, Rotation, and Position)

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local cube1 = World.SpawnAsset(propCubeTemplate)
local cube2 = World.SpawnAsset(propCubeTemplate)

cube2.parent = cube1

cube1:SetWorldPosition(Vector3.New(0, 500, 100))
cube2:SetPosition(Vector3.New(0, 200, 0))
-- Cube 1 has been placed in the world, and cube2 has been placed, relative to cube1.

print("cube2 relative position: " .. tostring(cube2:GetPosition()))      -- X=0.000 Y=200.000 Z=0.000
print("cube2 world position:    " .. tostring(cube2:GetWorldPosition())) -- X=0.000 Y=700.000 Z=100.000

cube1:SetWorldRotation(cube1:GetWorldRotation() + Rotation.New(0, 0, 90))
cube2:SetRotation(cube2:GetRotation() + Rotation.New(0, 0, 90))
-- Both cubes have been rotated by 90 degrees, but cube2 gets the combined rotation
-- because it is the child of cube1.

print("cube2 relative rotation: " .. tostring(cube2:GetRotation()))      -- X=0.000 Y=0.000 Z=90.000
print("cube2 world rotation:    " .. tostring(cube2:GetWorldRotation())) -- X=0.000 Y=0.000 Z=180.000

cube1:SetWorldScale(cube1:GetWorldScale() * 2)
cube2:SetScale(cube2:GetScale() * 2)
-- Both cubes have been doubled in size. But again, the child cube (cube2) also takes the scale
-- of the parent. (cube1)
print("cube2 relative scale:    " .. tostring(cube2:GetScale()))      -- X=2.000 Y=2.000 Z=2.000
print("cube2 world scale:       " .. tostring(cube2:GetWorldScale())) -- X=4.000 Y=4.000 Z=4.000

-- It's also possible to read and write the entire transform at once.
local cube3 = World.SpawnAsset(propCubeTemplate)
local cube4 = World.SpawnAsset(propCubeTemplate)
cube4.parent = cube1

cube3:SetWorldTransform(cube1:GetWorldTransform())
cube4:SetTransform(cube2:GetTransform())

-- Cube1 and cube3 now have the same transforms, and cube2 and cube4 also match.

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Vector3.New | Rotation.New | CoreLua.print


Example using:

GetVelocity

SetVelocity

GetAngularVelocity

SetAngularVelocity

SetLocalAngularVelocity

Some core objects are handled by the physics system. Anything that is marked as "debris physics" is such an object, as well as some special objects in the catalog, such as "Physics Sphere".

For objects like this, you can set their velocity and angular velocity directly.

local propPhysicsSphere = script:GetCustomProperty("PhysicsSphere")
local sphere = World.SpawnAsset(propPhysicsSphere, {position = Vector3.New(500, -200, 300)})

sphere:SetVelocity(Vector3.UP * 1000)
sphere:SetAngularVelocity(Vector3.UP * 1000)

Task.Wait(2)
-- Cut the velocity (and angular velocity) down to 25%
sphere:SetVelocity(sphere:GetVelocity() * 0.25)
sphere:SetAngularVelocity(sphere:GetAngularVelocity() * 0.25)

-- You can also set the angular velocity in local space, relative to the angular
-- velocity of its parent, if any:
sphere:SetLocalAngularVelocity(sphere:GetAngularVelocity() * 0.25)

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Vector3.New | Task.Wait


Example using:

MoveTo

RotateTo

ScaleTo

MoveContinuous

RotateContinuous

ScaleContinuous

StopMove

StopRotate

StopScale

There are quite a few functions that make it easy to animate CoreObjects in your game. Since most things are CoreObjects, this gives you a lot of flexibility in creating animations for a wide variety of objects.

MoveTo(), RotateTo() and ScaleTo() are the most basic, and they allow you to change a CoreObject's position, rotation, or scale over time. The base version of these functions just takes a destination position/scale/rotation, and how much time it should take to get there.

There are also continuous versions of these functions, that cause a CoreObject to continuously change position/scale/rotation forever, or until told to stop.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local movingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, -200, 100)})
local spinningCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, 0, 100)})
local shrinkingCube = World.SpawnAsset(propCubeTemplate, {position = Vector3.New(500, 200, 100)})

local transitionTime = 5

-- These functions will make cubes rise, spin, and shrink, over the next 5 seconds.
movingCube:MoveTo(movingCube:GetWorldPosition() + Vector3.UP * 1000, transitionTime)
spinningCube:RotateTo(Rotation.New(0, 0, 179), transitionTime)
shrinkingCube:ScaleTo(Vector3.ZERO, transitionTime)

Task.Wait(transitionTime)

-- These functions will make the cubes fall, spin, and grow indefinitely, until stopped.
movingCube:MoveContinuous(Vector3.UP * -100)
spinningCube:RotateContinuous(Rotation.New(0, 0, 20))
shrinkingCube:ScaleContinuous(Vector3.New(0.2, 0.2, 0.2))

-- And here, 2 seconds later, we stop them.
Task.Wait(2)
movingCube:StopMove()
spinningCube:StopRotate()
shrinkingCube:StopScale()

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Vector3.New | Rotation.New | Task.Wait


Example using:

SetCustomProperty

customPropertyChangedEvent

GetReference

Dynamic custom properties are a special kind of custom property that can be used to communicate with client contexts. (They're actually one of the few ways that the server can send data that a client context can respond to.)

To create a dynamic custom property, right click a custom property in the Core editor, and select "Enable Dynamic Property."

Once a custom property has been set to be networked, the server can change its value at runtime via SetCustomProperty(), and the client can listen for changes to that property via customPropertyChangedEvent.

In this sample, it is assumed that the script has a custom dynamic property.

In a client context, we can set up listeners to tell us when a custom property changes, and what its current value is:

-- Client context:
local function OnPropertyChanged(coreObject, propertyName)
    print("The dynamic property [" .. coreObject.name .. "] just had its ["
            .. propertyName .. "] property changed.")

    local newValue = coreObject:GetCustomProperty(propertyName)
    print("New value: " .. tostring(newValue))
end

script.customPropertyChangedEvent:Connect(OnPropertyChanged)

--[[#description
    Now, if the server changes the custom property, the client is notified:
]]

-- Server context:
script:SetCustomProperty("NetworkedGreeting", "Buenos Dias")

-- The client should print out:
-- The dynamic property [test_CoreObject] just had its [NetworkedGreeting] property changed.
-- New value: Buenos Dias

--[[#description
    In addition to basic types (strings, integers, colors, etc) you can also pass
    references to core objects via networked custom properties. This is really useful
    if you want to have a client-side script know about a particular networked object.

    To do this, you need to first convert the `CoreObject` into a `CoreObjectReference`.
]]
-- Server context:
local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local cube = World.SpawnAsset(propCubeTemplate)
script:SetCustomProperty("NetworkedCoreObjectReference", cube:GetReference())

See also: CoreObject.GetCustomProperty | World.SpawnAsset | Event.Connect | CoreLua.print


Example using:

IsCustomPropertyDynamic

GetCustomProperties

In this example we look at all custom properties of a script. We then evaluate if each of them is dynamic. Only dynamic properties can be modified at runtime. To make a custom property dynamic first change the Core Object to networked, then right-click the property and change it to dynamic.

local allProperties = script:GetCustomProperties()

for key,value in pairs(allProperties) do
    if script:IsCustomPropertyDynamic(key) then
        print("Custom property '" .. key .. "' is dynamic!")
    else
        print("Custom property '" .. key .. "' is not dynamic.")
    end
end

Example using:

ReorderAfter

ReorderAfterSiblings

In this example, a UI Panel has several buttons as children. At runtime they are sorted vertically, one below the other. The player can click to drag them and change their order, depending on where they are released. The draw order of the buttons is updated to reflect the new positions. Draw order is changed with the methods ReorderAfter() and ReorderAfterSiblings().

local UI_PANEL = script:GetCustomProperty("UIPanel"):WaitForObject()
local allButtons = UI_PANEL:FindDescendantsByType("UIButton")

UI.SetCursorVisible(true)
UI.SetCanCursorInteractWithUI(true)

local deltaY = 0
local activeButton = nil

function Tick(deltaTime)
    if activeButton then
        local cursorPos = Input.GetCursorPosition()
        activeButton.x = CoreMath.Lerp(activeButton.x, 10, deltaTime * 12)
        activeButton.y = cursorPos.y + deltaY
    end
end

function OnPressed(button)
    activeButton = button
    local cursorPos = Input.GetCursorPosition()
    deltaY = button.y - cursorPos.y

    button:ReorderAfterSiblings()
end

function OnReleased(button)
    activeButton = nil

    local lastButton = allButtons[#allButtons]

    if button.y < allButtons[1].y then
        MoveToIndex(button, 1)

    elseif button ~= lastButton and button.y > lastButton.y then
        MoveToIndex(button, #allButtons)
    else
        for i,btn in ipairs(allButtons) do
            if button.y < btn.y then
                if button.clientUserData.index > i then
                    MoveToIndex(button, i)
                else
                    MoveToIndex(button, i - 1)
                end
                break
            end
        end
    end
    UpdatePositions()
end

function MoveToIndex(button, index)
    table.remove(allButtons, button.clientUserData.index)
    table.insert(allButtons, index, button)
end

function UpdatePositions()
    local y = 0
    for i,btn in ipairs(allButtons) do
        btn.x = 0
        btn.y = y
        y = y + btn.height

        if i > 1 then
            btn:ReorderAfter(allButtons[i - 1])
        end
        btn.clientUserData.index = i
    end
end

for _,btn in ipairs(allButtons) do
    btn.pressedEvent:Connect(OnPressed)
    btn.releasedEvent:Connect(OnReleased)
end

UpdatePositions()

See also: Input.GetCursorPosition | UIControl.y | UIButton.pressedEvent | CoreObject.clientUserData | CoreMath.Lerp | CoreObjectReference.WaitForObject


Example using:

ReorderBefore

In this example, a black translucent image is spawned behind a panel and adjusted to fill the parent space. ReorderBefore() is used so the image will draw on top of other elements, but behind the designated UI element.

local IMAGE_TEMPLATE = script:GetCustomProperty("BlankImage")

function AddModalFadeToDialog(uiDialogRoot)
    local fadeImage = World.SpawnAsset(IMAGE_TEMPLATE, {parent = uiDialogRoot.parent})

    fadeImage:ReorderBefore(uiDialogRoot)

    fadeImage:SetColor(Color.New(0, 0, 0, 0.5))

    fadeImage.width = uiDialogRoot.parent.width
    fadeImage.height = uiDialogRoot.parent.height

    fadeImage.anchor = UIPivot.TOP_LEFT
    fadeImage.dock = UIPivot.TOP_LEFT
end

See also: Color.New | World.SpawnAsset | UIImage.SetColor | UIControl.width


Example using:

ReorderBeforeSiblings

The draw order of UI elements is affected by their order in the hierarchy. In this example, calling AddBackground() spawns an image and moves it behind all the other elements.

local BG_TEMPLATE = script:GetCustomProperty("BackgroundImage")

function AddBackground(uiPanel)
    local bg = World.SpawnAsset(BG_TEMPLATE, {parent = uiPanel.parent})
    bg:ReorderBeforeSiblings()
end

See also: World.SpawnAsset


Example using:

SetReplicationEnabled

IsReplicationEnabled

ForceReplication

In this example, an object is replicated to clients every 10 seconds by spawning a task which will toggle the replication state of the object. When replication is enabled, the object will be moved up for a certain time, and then replication will be turned off, which will send no more updates to clients.

The server script will listen for the event ForceUpdate, and force a replication if the object is not already replicating.

--Server Script

-- An object in the hierarchy that is networked.
local OBJECT = script:GetCustomProperty("MyObject"):WaitForObject()

-- Toggle object replication on and off.
local function ToggleReplication()
if OBJECT:IsReplicationEnabled() then
    OBJECT:SetReplicationEnabled(false)
else
    OBJECT:SetReplicationEnabled(true)
end
end

-- If the object does not have replication enabled, update the position then force
-- replication which will update for all connected clients.
local function ForceUpdate()
if not OBJECT:IsReplicationEnabled() then
    OBJECT:SetWorldPosition(OBJECT:GetWorldPosition() + (Vector3.UP * 50))
    OBJECT:ForceReplication()
end
end

-- If the object has replication enabled, update the world position.
function Tick(deltaTime)
if OBJECT:IsReplicationEnabled() then
    OBJECT:SetWorldPosition(OBJECT:GetWorldPosition() + (Vector3.UP * (deltaTime * 10)))
end
end

-- Spawn a task that runs every 10 seconds that toggles replication.
local task = Task.Spawn(ToggleReplication, 10)

task.repeatCount = -1
task.repeatInterval = 10

-- Broadcast this event to force replication.
Events.Connect("ForceUpdate", ForceUpdate)

See also: CoreObject.GetCustomProperty | CoreObjectReference.WaitForObject | Vector3.UP, | Task.Spawn | Event.Connect | CoreLua.Tick


Example using:

name

id

sourceTemplateId

isStatic

isClientOnly

isServerOnly

isNetworked

You can find out a lot about an object via its CoreProperties.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")

local template = World.SpawnAsset(propCubeTemplate)

-- The name of the object is its name in the hierarchy, or the name of the
-- template it was spawned from.
print("Name: " .. template.name)
-- The ID of the object is its core object reference. (A MUID)
print("Id: " .. template.id)
-- The source template id is the MUID of template it was spawned from.
-- (Or nil if it was just placed in the hierarchy at edit-time.)
print("sourceTemplateId: " .. template.sourceTemplateId)

-- You can also tell if an object is networked, and if it is in a static, client, or server context:
if template.isNetworked then
    print("It is networked!")
else
    print("It is not networked!")
end
if template.isClientOnly then print("It is Client only!") end
if template.isServerOnly then print("It is Server only!") end
if template.isStatic then print("It is Static") end

-- Output:
--    Name: GoldCube
--    Id: E355483D7F78F3B1:GoldCube
--    sourceTemplateId: AF4DDC200B982801
--    It is networked.

See also: CoreObject.GetCustomProperty | CoreObjectReference.WaitForObject | World.SpawnAsset | CoreLua.print


Example using:

visibility

collision

isEnabled

IsVisibleInHierarchy

IsCollidableInHierarchy

IsEnabledInHierarchy

You can make objects appear and disappear in the world in several different ways.

By changing their visibility property, you can make them appear or disappear, but they will otherwise still exist. (Players can collide with them, etc.)

By changing their collision property, you can make the object something that players (and other objects) can no longer collide with. The object will still be visible though.

You can also completely disable an object, via the isEnabled property. Objects with isEnabled set to false cannot be seen or collided with, nor can any of their children.

Both collision and visibility have three possible values: FORCE_ON, FORCE_OFF and INHERIT. By default, things are set to INHERIT, which means they will have whatever visibility or collision settings their parent object has. This makes it convenient to hide or remove collision from a whole group of things, by simply changing the settings of the root object.

FORCE_ON and FORCE_OFF override this, and force the object to be collidable or visible (or not) regardless of the state of their parents.

It is sometimes useful to know if an object is currently visible/collidable/enabled. Because this may depend on the state of its parents, there are several convenience functions that allow you to check, without having to climb the hierarchy yourself.

local propCubeTemplate = script:GetCustomProperty("CubeTemplate")
local cube1 = World.SpawnAsset(propCubeTemplate)
local cube2 = World.SpawnAsset(propCubeTemplate)
cube2.parent = cube1

-- Cube2 is now the child of cube1.
-- By default they both off with Visibility.INHERIT and Collision.INHERIT
print("default state:")
print("cube2 visible?    " .. tostring(cube2:IsVisibleInHierarchy()))
print("cube2 collidable? " .. tostring(cube2:IsCollidableInHierarchy()))
print("cube2 enabled?    " .. tostring(cube2:IsEnabledInHierarchy()))
-- These should all be true when we start.

-- If we set cube1 to be disabled, then cube2 is no longer visible or collidable:
cube1.isEnabled = false
print("parent disabled:")
print("cube2 visible?    " .. tostring(cube2:IsVisibleInHierarchy()))
print("cube2 collidable? " .. tostring(cube2:IsCollidableInHierarchy()))
print("cube2 enabled?    " .. tostring(cube2:IsEnabledInHierarchy()))

-- Note that isEnabled overrides visibility/collision settings. So even
-- if we set cube2 to force its visibility and collision on, they are
-- still overridden as long as its parent is disabled:
print("parent disabled, but forcing things on:")
cube2.visibility = Visibility.FORCE_ON
cube2.collision = Collision.FORCE_ON
print("cube2 visible?    " .. tostring(cube2:IsVisibleInHierarchy()))
print("cube2 collidable? " .. tostring(cube2:IsCollidableInHierarchy()))
-- These are both false because the parent is still disabled.

-- On the other hand, if we set cube1 to enabled, but FORCE_OFF for
-- collision and visibility, cube2 is now visible and collidable, because
-- it is still FORCE_ON for both values, meaning it ignores its parent.
cube1.visibility = Visibility.FORCE_OFF
cube1.collision = Collision.FORCE_OFF
cube1.isEnabled = true
print("cube2 visible?    " .. tostring(cube2:IsVisibleInHierarchy()))
print("cube2 collidable? " .. tostring(cube2:IsCollidableInHierarchy()))
-- These are both true now because the parent is no longer disabled.

See also: CoreObject.GetCustomProperty | World.SpawnAsset | CoreLua.print



Last update: February 16, 2023