Table of Contents

ExportTransform

The ExportTransform class is a class that can interfere with Transform and Rigidbody.

You can change the position, rotation and scale of a VCI, or you can rotate and blow them by applying force.


List of member variables and functions

For the complete list, refer to “types.lua” file in “EmbeddedScriptWorkspace” folder.

To shorten the description, Vector3 type is abbreviated as Vec and number type is abbreviated as num.
Arguments are shown in () and return values are shown after semicolons :.

Name Description VC version
GetName fun(): string Get the name of a subitem
GetLocalPosition fun(): Vec3 Get the position of a SubItem
(Subitem local)
GetPosition fun(): Vec3 Get the position of a SubItem
GetLocalRotation fun(): Quaternion Get the rotation of a SubItem\\(Subitem local)
GetRotation fun(): Quaternion Get the rotation of a SubItem
GetLocalScale fun(): Vec3 Get the scale of a SubItem
GetForward fun(): Vec3 Get the forward direction (positive z axis) based on a SubItem
GetRight fun(): Vec3 Get the right direction (positive x axis) based on a SubItem
GetUp fun(): Vec3 Get the up direction (positive y axis) based on a SubItem
GetLocalToWorldMatrix fun(): Matrix4x4 Matrix when converting from the local coordinate to the world coordinate
GetAnimation fun(): ExportAnimation Used for ExportAnimation
IsMine bool Returns true in case of subItem owner, otherwise returns nil
IsSubItem bool Returns true in case of SubItem, otherwise returns false
SetPosition fun(position: Vec3) Change the position of a Subitem to the value specified with Vec3
SetLocalPosition fun(localPosition: Vec3) Change the position of a Subitem to the value specified with Vec3
SetRotation fun(rotation: Quaternion) Change the Rotation of a Subitem to the value specified with quaternion
SetLocalRotation fun(localRotation: Quaternion) Change the Rotation of a Subitem to the value specified with quaternion
SetLocalScale fun(localScale: Vec3) Change the scale of a Subitem to the value specified with Vec3
SetVelocity fun(velocity: Vec3) Change the force applied to a Subitem to the value specified with Vec3
SetAngularVelocity fun(angularVelocity: Vec3) Change the rotation applied to a Subitem to the direction specified with Vec3
AddForce fun(force: Vec3) Apply the force specified with Vec3 to a Subitem

Attachable item

Name Description VC version
IsAttached bool Returns true when attached 1.9.2a and later
AttachableDistance number Returns the distance at which it is attachable 1.9.2a and later
AttachableHumanBodyBones usertype Returns the list of attachable bone names as a table 1.9.2a and later
AttachToAvatar fun() When it is attachable, ties to attach 1.9.2a and later
DetachFromAvatar fun() When it is attached, detaches 1.9.2a and later

To use the ExportTransform class, you must first instantiate a Subitem by specifying its name like Subitem = vci.assets.GetSubItem(“Subitem”).
Then, you can call the methods like Subitem.MethodName().

Synchronization of VCI

When you are creating something that moves over a network, you have to take the synchronization into account.
In a scenario where there are three people (A, B and C) in a single Virtual Cast studio, the act of applying the result of person A moving an object to the computer of person B and C is called “synchronization.”
On the other hand, when something moves only in the computer of the person who moved it, that situation is called “working in local only.”
Following are the most common way of synchronization in VCI.

As for the synchronization of transform, the result of the script run in the client of the user who spawned the VCI will be synced across other clients via the base functions of Virtual Cast, without needing special attention from you.
For details on the synchronization of transform, refer to About VCI items and subitems.

GetSubItem()

Example

main.lua
--ExportTransform
-- Object name set to the SubItem is "SubItem"
SubItem = vci.assets.GetSubItem("SubItem") 
 
print(SubItem.GetName())
print(SubItem.ToString())


The result

SubItem
VCIEmbedded.LuaMoonSharp.ExportTransform

By passing an object name of a SubItem as the argument to vci.assets.GetSubItem(),
you can instantiate the ExportTransform of the SubItem you passed as the argument.
By using the functions of the ExportTransform instantiated, you can change or acquire the value of the transform.

Declaring multiple SubItems in a for statement

main.lua
-- Declare a table with for statement
local _Items = {}
for i=1, 5 do
    _Items[i] = vci.assets.GetSubItem("Item"..tostring(i))
    print("Registered ".._Items[i].. "in the table.")
end

By giving SubItems serialized names, such as Item1 Item2 Item3,
you can GetSubItem() in the order from 1 using for statement.
* i can be converted into string with tostring(i).

IsMine

Example

main.lua
subitem = vci.assets.GetSubItem('SubItem')
 
function updateAll() -- All users execute this regardless of ownership
    if subitem.IsMine then -- true when you are the owner of the subitem.
        subitem.SetPosition = Vector3.__new(1, 2, 3)
    end
end

Used to run a certain process only when the user is the owner of the SubItem.
For details of ownership, refer to Relation between ownership and event functions.

Get transform

Example

main.lua
--ExportTransform
-- Object name set to the SubItem is "SubItem"
SubItem = vci.assets.GetSubItem("SubItem") 
 
print(SubItem.GetPosition())
print(SubItem.GetLocalPosition())
print(SubItem.GetRotation())
print(SubItem.GetLocalRotation())
print(SubItem.GetLocalScale())
print(SubItem.GetForward())


The result

(0.0, 1.2, 0.0)
(0.0, 1.2, 0.0)
(0.0, 0.0, 0.0, 1.0)
(0.0, 0.0, 0.0, 1.0)
(1.0, 1.0, 1.0)
(0.0, 0.0, 1.0)

GetName()

return value: string
You can get the name of the VCI object name.

GetPosition() / GetLocalPosition()

return value: Vector3
You can get the current position of the Subitem.
Position() uses the origin in Unity (0,0,0) as the reference point. On the other hand, LocalPosition() uses the spawn position as the reference point.

GetRotation() / GetLocalRotation()

return value: Quaternion
You can get the rotation (Quaternion) of the Subitem.
Rotation() uses entire Unity as its reference rotation (Z+ forward). LocalRotation() uses the direction at which the VCI is spawned as the reference rotation.
SetRotation(Quaternion.identity) changes the orientation using Unity's Z+ as the forward direction.

GetLocalScale()

return value: Vector3
You can get the scale of the SubItem.

When changing the scale of a SubItem that is scalable, retrieve the scale value by GetLocalScale(), then multiply it by the desired scale factor to set “a scale value changed based on the current scale.”
(Only using SetLocalScale() means it is a scale change without considering current scale).

GetForward()

return value: Vector3
Get the current forward direction of the SubItem.
(Vector of positive Z-axis based on the SubItem)

One use case of this is to retrieve the vector of the forward direction by GetForward(), then when onUngrab() (when you release the SubItem) is called, you can use AddForce() and the retrieved forward direction vector to push the item in the forward direction.
You can use this to “shoot the item to forward direction.”

SetPosition() / SetLocalPosition()

Argument: vector3
Change the current position of a Subitem to the value specified with Vector3.
Position() uses the origin in Unity (0,0,0) as the reference point. On the other hand, LocalPosition() uses the spawn position as the reference point.

When setting position or rotation, if any force is being applied to the SubItem, the calculation for the force being applied happens right after the values are set, which may produce an unintended result.
Therefore, it is recommended to use SetVelocity(0,0,0) to set the force to be zero after a Set method is called.

The order should be SetPosition() then SetVelocity(0,0,0).
(If its the opposite, some force could be applied by SetPosition() after the force is being set to 0.

SetRotation() / SetLocalRotation()

Argument: Quaternion
Change the current attitude (rotation) of a Subitem to the value specified with Quaternion.
Rotation() uses entire Unity as its reference rotation (Z+ forward). LocalRotation() uses the direction at which the VCI is spawned as the reference rotation.

When setting position or rotation, if any force is being applied to the SubItem, the calculation for the force being applied happens right after the values are set, which may produce an unintended result.
Therefore, it is recommended to use SetVelocity(0,0,0) to set the force to be zero after a Set method is called.

The order should be SetPosition() then SetVelocity(0,0,0).
(If its the opposite, some force could be applied by SetPosition() after the force is being set to 0.

SetLocalScale()

Argument: vector3
Change the scale of a Subitem to the value specified with Vector3.

When changing the scale of a SubItem that is scalable, retrieve the scale value by GetLocalScale(), then multiply it by the desired scale factor to set “a scale value changed based on the current scale.”

SetVelocity()

Argument: vector3
Change the force being applied to a VCI to the value set with a Vector3.

In the example below, the object with the name “subitem” moves toward Z direction when being grabbed.
The object will hold the Velocity value right after the code is executed.
By setting Vector3.zero you can disable the motion being applied by physics calculation.

Example

main.lua
item = vci.assets.GetSubItem("subitem")
function onGrab()
    local velocity = Vector3.__new(0, 0, 10)
    print(velocity)
    item.SetVelocity(velocity)
end

SetAngularVelocity()

Argument: vector3
This will apply a rotational force based on the Vector3 value.

In the example below, the rotational force “velocity” will be applied to the object with the name “subitem”.

Example

main.lua
item = vci.assets.GetSubItem("subitem")
function onGrab()
    local velocity = Vector3.__new(10, 0, 0)
    print(velocity)
    item.SetAngularVelocity(velocity)
end

AddForce()

Argument: vector3
Force will be added toward the Vector3 direction.

In the example below, the object with the name “subitem” moves toward Z direction when being grabbed.
AddForce will apply the force little by little as if an object is being accelerated.

Example

main.lua
item = vci.assets.GetSubItem("subitem")
function onGrab()
    local force = Vector3.__new(0, 0, 10)
    print(force)
    item.AddForce(force)
end

Controlling an attachable item

VC version: 1.9.2a and later

You can control the subitem with VCIAttachable component attached. Attach with AttachToAvatar and detach with DetachFromAvatar. You can check the attached state with IsAttached. The attachability is decided based on the distance specified in VCIAttachable and the distance to a bone. You cannot attach if you don't have the ownership for the SubItem.

Example

main.lua
local item = vci.assets.GetSubItem("Cube")
 
local dist = item.AttachableDistance
print("AttachableDistance: "..dist)
 
print("Bones")
local bones = item.AttachableHumanBodyBones
for key,value in ipairs(bones) do
    print(key .. " : " .. value)
end
 
function update()
 
    if vci.me.GetButtonInput(1) then
        print("Attach")
        item.AttachToAvatar()
    end
 
    if vci.me.GetButtonInput(2) then
        print("Detach")
        item.DetachFromAvatar()
    end
 
end
 
vci.StartCoroutine(
    coroutine.create(
        function()
            while true do
                local isAttached = item.IsAttached
                if isAttached then
                    print("Attached")
                else
                    print("Not attached")
                end
                sleep(1)
            end
        end
    )
)
 
function sleep(sec)
    local t0 = os.time() + sec
    while os.time() < t0 do
        coroutine.yield()
    end
end

Example data

A VCI that attaches when you hold a hand over it and detaches after five seconds. An effect will be played while the item is attached.

attachsample.zip

main.lua
local item = vci.assets.GetSubItem("Ball")
local effect = vci.assets.GetEffekseerEmitter("Ball")
 
vci.StartCoroutine(
    coroutine.create(
        function()
            while true do
                if item.IsAttached == false then
                    item.AttachToAvatar()
                    sleep(0.1)
                    if item.IsAttached then
                        effect.Play()
                        sleep(5)
                        item.DetachFromAvatar()
                        effect.Stop()
                        sleep(1)
                    end
                end
                sleep(0.5)
            end
        end
    )
)
 
function sleep(sec)
    local t0 = os.time() + sec
    while os.time() < t0 do
        coroutine.yield()
    end
end