Maksim789456 (talk | contribs) No edit summary |
Updating to match new version of source page |
||
Line 57: | Line 57: | ||
=== <span lang="en" dir="ltr" class="mw-content-ltr">Binding</span> === | === <span lang="en" dir="ltr" class="mw-content-ltr">Binding</span> === | ||
<span lang="en" dir="ltr" class="mw-content-ltr">Creating, duplicating, or moving a dynamic variable requires '''binding''' that variable to a space.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">This is a process that happens automatically but isn't perfect yet. (see [[#Warning|Warning]])</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">In essence it starts searching for a matching dynamic variable space at the slot of the dynamic variable.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">If there is no match, it tries the parent slot, its parent etc. until a matching space is found.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">Variables with explicitly given space names only match spaces with the same name.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">Variables without explicit space name match all spaces that are not <code>OnlyDirectBinding</code></span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">The following image will demonstrate the differences in binding:</span> | |||
[[File:Dynamic_Variables.svg|border| | [[File:Dynamic_Variables.svg|border|<span lang="en" dir="ltr" class="mw-content-ltr">an image demonstrating that dynamic variable spaces with enabled OnlyDirectBinding are ignored except by variables which have explicitly declared the same space name</span>]] | ||
* <span lang="en" dir="ltr" class="mw-content-ltr">I: <code>A</code> is connected to <code>Inner</code> because <code>Inner</code> is <u>not</u> <code>OnlyDirectBinding</code>.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">II/III: Both variables are bound explicitly.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">IV: <code>A</code> ignores <code>Inner</code> because <code>Inner</code> is <code>OnlyDirectBinding</code>.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">V/VI: Both variables are bound explicitly.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">VII/IX: There is no matching dynamic variable space. Both variables are not bound.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">VIII: The variable is explicitly bound to <code>World</code>.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">I and II share the same value.</span> | |||
* <span lang="en" dir="ltr" class="mw-content-ltr">III, IV and VI share the same value.</span> | |||
{{#mermaid:flowchart BT | {{#mermaid:flowchart BT | ||
Line 127: | Line 131: | ||
=== <span lang="en" dir="ltr" class="mw-content-ltr">Warning</span> === | === <span lang="en" dir="ltr" class="mw-content-ltr">Warning</span> === | ||
<span lang="en" dir="ltr" class="mw-content-ltr">In a few use-cases binding may take a small amount of time, before which the dynamic variable can appear to be present, but not be readable or writable. Therefore, if you create a dynamic variable using the [[ProtoFlux:Create Dynamic Variable|Create Dynamic Variable]] or [[ProtoFlux:Write Or Create Dynamic Variable|Write Or Create Dynamic Variable]] ProtoFlux Node, or cause it to be duplicated using the [[ProtoFlux:Duplicate Slot |Duplicate Slot]] ProtoFlux Node, or cause it to be moved using the [[ProtoFlux:Set Parent|Set Parent]] ProtoFlux Node, you may find it necessary to add an [[ProtoFlux:Updates Delay|Updates Delay]] or [[ProtoFlux:Updates Delay With Value|Updates Delay With Value]] ProtoFlux Node afterwards in order to ensure the dynamic variables have been bound by the time you use them. A delay of 1 to 3 updates usually suffices.</span> | <span lang="en" dir="ltr" class="mw-content-ltr">In a few use-cases, binding may take a small amount of time, before which the dynamic variable can appear to be present, but not be readable or writable.</span> | ||
<span lang="en" dir="ltr" class="mw-content-ltr">Therefore, if you create a dynamic variable using the [[ProtoFlux:Create Dynamic Variable|Create Dynamic Variable]] or [[ProtoFlux:Write Or Create Dynamic Variable|Write Or Create Dynamic Variable]] ProtoFlux Node, or cause it to be duplicated using the [[ProtoFlux:Duplicate Slot |Duplicate Slot]] ProtoFlux Node, or cause it to be moved using the [[ProtoFlux:Set Parent|Set Parent]] ProtoFlux Node, you may find it necessary to add an [[ProtoFlux:Updates Delay|Updates Delay]] or [[ProtoFlux:Updates Delay With Value|Updates Delay With Value]] ProtoFlux Node afterwards in order to ensure the dynamic variables have been bound by the time you use them. A delay of 1 to 3 updates usually suffices.</span> | |||
TODO: more precise list of problematic uses cases (e.g. <code>Duplicate Slot</code> of a whole space works totally fine.) | <!-- TODO: more precise list of problematic uses cases (e.g. <code>Duplicate Slot</code> of a whole space works totally fine.) --> | ||
== <span lang="en" dir="ltr" class="mw-content-ltr">Example Applications</span> == | == <span lang="en" dir="ltr" class="mw-content-ltr">Example Applications</span> == | ||
The following examples will demonstrate a few use-cases of dynamic variables. | <span lang="en" dir="ltr" class="mw-content-ltr">The following examples will demonstrate a few use-cases of dynamic variables.</span> | ||
There is a focus on how to use them to create separate objects | <span lang="en" dir="ltr" class="mw-content-ltr">There is a focus on how to use them to create separate objects</span> | ||
=== <span lang="en" dir="ltr" class="mw-content-ltr">Modules within an object</span> === | === <span lang="en" dir="ltr" class="mw-content-ltr">Modules within an object</span> === | ||
< | <span lang="en" dir="ltr" class="mw-content-ltr">Dynamic variables within an object allow modularization.</span> | ||
Commonly used names for such hierarchies are: | <span lang="en" dir="ltr" class="mw-content-ltr">Different modules would be connected via dynamic variables within the space located at the root of the object.</span> | ||
<span lang="en" dir="ltr" class="mw-content-ltr">If all hard-coded references going in or out of a module are eliminated you can replace it with a different variant/version without additional setup.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">Module-local variables can be created with a dynamic variable space located at the root of the module. Use appropriately named spaces to differentiate between the two.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">To make available variables more obvious to other people - including you in 6 months - it is recommended to place all dynamic variables within a dedicated slot hierarchy.</span> | |||
<!--T:42--> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">Commonly used names for such hierarchies are:</span> | |||
* DV | * DV | ||
* DynVar | * DynVar | ||
* Vars | * Vars | ||
* etc. | * etc. | ||
< | <span lang="en" dir="ltr" class="mw-content-ltr">A modular object could look like this:</span> | ||
A modular object could look like this: | * Project (<span lang="en" dir="ltr" class="mw-content-ltr">Space: <code>MyProject</code></span>) | ||
* Project (Space: <code>MyProject</code>) | |||
** Dynamic Variables | ** Dynamic Variables | ||
*** projectVar: String (Dynamic variable <code>projectVar</code> of type [[Type:String|String]]) | *** projectVar: String (Dynamic variable <code>projectVar</code> of type [[Type:String|String]]) | ||
** Module: UI (i.e. [[Component:MeshRenderer|MeshRenderer]] or [[Component:Canvas|Canvas]] plus [[Collider|Colliders]]), may contain: | ** Module: <span lang="en" dir="ltr" class="mw-content-ltr">UI (i.e. [[Component:MeshRenderer|MeshRenderer]] or [[Component:Canvas|Canvas]] plus [[Collider|Colliders]]), may contain:</span> | ||
*** Dynamic Variable Drivers → Visuals | *** Dynamic Variable Drivers → Visuals | ||
*** [[:Category:Components:Common_UI:Button_Interactions|Button Interactions]] → Dynamic Variables | *** [[:Category:Components:Common_UI:Button_Interactions|Button Interactions]] → Dynamic Variables | ||
Line 165: | Line 168: | ||
*** Dynamic Variables | *** Dynamic Variables | ||
**** logicVar: int (Dynamic variable <code>logicVar</code> of type [[Type:Int|int]]) | **** logicVar: int (Dynamic variable <code>logicVar</code> of type [[Type:Int|int]]) | ||
**** MyProject/Logic: Slot (Dynamic variable <code>Logic</code> of type [[Slot]] for space <code>MyProject</code>, driven with reference to Slot of module to make it accessible to other modules) | **** MyProject/Logic: <languages/>Slot (Dynamic variable <code>Logic</code> of type [[Slot]] for space <code>MyProject</code>, driven with reference to Slot of module to make it accessible to other modules) | ||
*** [[ProtoFlux]] (may read, write or even drive dynamic variables of space <code>MyProject</code>) | *** [[ProtoFlux]] <span lang="en" dir="ltr" class="mw-content-ltr">(may read, write or even drive dynamic variables of space <code>MyProject</code>)</span> | ||
</ | |||
=== <span lang="en" dir="ltr" class="mw-content-ltr">Configurable objects</span> === | === <span lang="en" dir="ltr" class="mw-content-ltr">Configurable objects</span> === | ||
< | <span lang="en" dir="ltr" class="mw-content-ltr">Dynamic variables make it possible to access other object's properties.</span> | ||
Assuming objects with a dynamic variable space, a collider and a string variable named <code>Description</code> you could then create a separate tool that reads and displays the <code>Description</code> of the object it is pointed at. The same tool could be extended to edit descriptions. | |||
</ | <span lang="en" dir="ltr" class="mw-content-ltr">Assuming objects with a dynamic variable space, a collider and a string variable named <code>Description</code> you could then create a separate tool that reads and displays the <code>Description</code> of the object it is pointed at. The same tool could be extended to edit descriptions.</span> | ||
<span lang="en" dir="ltr" class="mw-content-ltr">The same concept can also be applied to template slots used within a project.</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">Their instances can be interacted with using dynamic variables.</span> | |||
=== <span lang="en" dir="ltr" class="mw-content-ltr">World/User variables</span> === | === <span lang="en" dir="ltr" class="mw-content-ltr">World/User variables</span> === | ||
< | <span lang="en" dir="ltr" class="mw-content-ltr">There are already pre-made dynamic variable spaces:</span> | ||
See [[Dynamic Variable Naming Standard]] for a more detailed listing. | * <span lang="en" dir="ltr" class="mw-content-ltr"><code>World</code> on [[Root]] (<code>OnlyDirectBinding</code>)</span> | ||
</ | * <span lang="en" dir="ltr" class="mw-content-ltr"><code>User</code> on each [[Component:UserRoot|User Root]] Slot (<code>OnlyDirectBinding</code>)</span> | ||
* <span lang="en" dir="ltr" class="mw-content-ltr"><code>Dash</code> on Slot of [[Component:UserspaceRadiantDash|UserSpaceRadiantDash]]</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">They can be used for states that are shared by many objects (i.e. day/night toggle, performance) or to broadcast information into the world. ([[BeatLink]], library objects like the [[Redprint]] manager)</span> | |||
<span lang="en" dir="ltr" class="mw-content-ltr">See [[Dynamic Variable Naming Standard]] for a more detailed listing.</span> |
Revision as of 22:35, 24 April 2024
Обзор
Динамические переменные позволяют вам читать и писать данные по имени в контексте иерархии слотов. Это упрощает управление данными в больших системах; каждый бит данных четко помечен, и вы можете разбивать данные на несколько пространств, чтобы разделять ваши системы.
Ограничения именования
При использовании динамических переменных существуют некоторые ограничения на именование пространств и переменных внутри этих пространств.
Пространства и имена переменных не могут содержать:
- Любые символы
- Как определено в C# Char.IsSymbol
- Любую пунктуацию / Пустые строки
- Как определено в C# Char.IsPunctuation и C# Char.IsWhiteSpace
- За исключением точки (.), нижнего подчеркивания (_) и пробела ( ).
Использование
При желании к имени может быть добавлен префикс в виде пробела заканчивающийся символом /, чтобы выбрать конкретное пространство для использования переменной. Это полезно для того, что различать несвязанные системы, в которых используют динамические переменные.
Некоторые допустимые имена:
- Health -- нет определенного пространства, имя Health
- World/Color -- имя Color, в пространстве World
- MyCoolSystem/Score -- имя Score, в пространстве MyCoolSystem
Пространства
Динамические переменные могут находиться в слоте содержащий компонент DynamicVariableSpace или в его дочерних слотах.
Таким образом, пространство для переменных находящиеся в корневом слоте мира можно использовать из любого места, но пространство для переменных на вашем аватаре можно использовать из всех слотов, что хранятся в вашем аватаре.
Переменные
Самый простой способ использовать динамические переменные - это использовать компоненты DynamicValueVariable<T> и DynamicReferenceVariable<T>. Они предназначены для значимых (int, float, String, etc.) и ссылочных (Slot, User, etc.) типов, соответственно. Компонент DynamicTypeVariable существует для хранения типов.
Эти компоненты хранят значение или непосредственно ссылку на него. Если два компонента содержат одинаковые имена, то они будут иметь одинаковое содержимое.
Поля
Если вы хотите использовать существующее поле или ссылку на него в качестве содержимого динамической переменной, вы можете использовать компоненты DynamicField<T> или DynamicReference<T>. Вместо того чтобы сохранять что-либо напрямую, они указывают на поле, содержащее значение или ссылочный тип, соответственно.
Как и в случае с переменными, существует вариант для полей содержащие Тип
: DynamicTypeField
(TODO: clarify value vs. reference types; I think this isn't fully correct)
Drivers
Вы можете использовать содержимое динамической переменной для управления поля или ссылкой, используя компоненты DynamicValueVariableDriver<T> и DynamicReferenceVariableDriver<T>.
Не представленные типы
При создании компонента динамической переменной вам будет предоставлен список "распространённых типов". Если нужного вам типа нету в этом списке, вам придется ввести его вручную. Смотрите Сложные типы в компонентах.
Binding
Creating, duplicating, or moving a dynamic variable requires binding that variable to a space. This is a process that happens automatically but isn't perfect yet. (see Warning)
In essence it starts searching for a matching dynamic variable space at the slot of the dynamic variable.
If there is no match, it tries the parent slot, its parent etc. until a matching space is found.
Variables with explicitly given space names only match spaces with the same name.
Variables without explicit space name match all spaces that are not OnlyDirectBinding
The following image will demonstrate the differences in binding:
- I:
A
is connected toInner
becauseInner
is notOnlyDirectBinding
. - II/III: Both variables are bound explicitly.
- IV:
A
ignoresInner
becauseInner
isOnlyDirectBinding
. - V/VI: Both variables are bound explicitly.
- VII/IX: There is no matching dynamic variable space. Both variables are not bound.
- VIII: The variable is explicitly bound to
World
. - I and II share the same value.
- III, IV and VI share the same value.
Warning
In a few use-cases, binding may take a small amount of time, before which the dynamic variable can appear to be present, but not be readable or writable. Therefore, if you create a dynamic variable using the Create Dynamic Variable or Write Or Create Dynamic Variable ProtoFlux Node, or cause it to be duplicated using the Duplicate Slot ProtoFlux Node, or cause it to be moved using the Set Parent ProtoFlux Node, you may find it necessary to add an Updates Delay or Updates Delay With Value ProtoFlux Node afterwards in order to ensure the dynamic variables have been bound by the time you use them. A delay of 1 to 3 updates usually suffices.
Example Applications
The following examples will demonstrate a few use-cases of dynamic variables. There is a focus on how to use them to create separate objects
Modules within an object
Dynamic variables within an object allow modularization. Different modules would be connected via dynamic variables within the space located at the root of the object. If all hard-coded references going in or out of a module are eliminated you can replace it with a different variant/version without additional setup. Module-local variables can be created with a dynamic variable space located at the root of the module. Use appropriately named spaces to differentiate between the two. To make available variables more obvious to other people - including you in 6 months - it is recommended to place all dynamic variables within a dedicated slot hierarchy.
Commonly used names for such hierarchies are:
- DV
- DynVar
- Vars
- etc.
A modular object could look like this:
- Project (Space:
MyProject
)- Dynamic Variables
- projectVar: String (Dynamic variable
projectVar
of type String)
- projectVar: String (Dynamic variable
- Module: UI (i.e. MeshRenderer or Canvas plus Colliders), may contain:
- Dynamic Variable Drivers → Visuals
- Button Interactions → Dynamic Variables
- Editors ↔ Dynamic Variables
- Module: Logic (Space:
Logic
)- Dynamic Variables
- logicVar: int (Dynamic variable
logicVar
of type int) - MyProject/Logic:
- logicVar: int (Dynamic variable
- Dynamic Variables
- Dynamic Variables
- français
- русский
Slot (Dynamic variable Logic
of type Slot for space MyProject
, driven with reference to Slot of module to make it accessible to other modules)
- ProtoFlux (may read, write or even drive dynamic variables of space
MyProject
)
- ProtoFlux (may read, write or even drive dynamic variables of space
Configurable objects
Dynamic variables make it possible to access other object's properties.
Assuming objects with a dynamic variable space, a collider and a string variable named Description
you could then create a separate tool that reads and displays the Description
of the object it is pointed at. The same tool could be extended to edit descriptions.
The same concept can also be applied to template slots used within a project. Their instances can be interacted with using dynamic variables.
World/User variables
There are already pre-made dynamic variable spaces:
World
on Root (OnlyDirectBinding
)User
on each User Root Slot (OnlyDirectBinding
)Dash
on Slot of UserSpaceRadiantDash
They can be used for states that are shared by many objects (i.e. day/night toggle, performance) or to broadcast information into the world. (BeatLink, library objects like the Redprint manager)
See Dynamic Variable Naming Standard for a more detailed listing.