VRTK Core Interaction Refactor
See original GitHub issueThis proposal has been co-authored by: @dustinlacewell and @bddckr
tl;dr
- Move event propagation from
ControllerEvents.Update
toControllerSDK.Update
- Replace
ControllerEvents
andControllerActions
withControllerBridge
- Deprecate
ControllerEvents
,ControllerActions
and the ‘script alias’ fields on theSDKManager
- Introduce
SDKManager
fields to represent the “current” bridges for left/right/etc controller devices - Propagate events from
ControllerSDK.Update
to the currently assigned bridges via the new fields - Perform tracking upon
ControllerBridge.trackedTransform
inSDKManager.Update
versus re-parenting on startup.
Summary
The idea is to do event generation, once, in ControllerSDK
and propagate them to the relevant ControllerBridge
s currently assigned to the SDKManager
. This is both a bit more efficient, but also allows for an elegant mechanism of swapping around whole controller interaction mechanisms.
Standard interaction scripts, such as
InteractTouch
,InteractGrab
,InteractUse
andInteractableObject
are not the topic. The existing model of interaction they implement should continue to work.
How VRTK controller events work
In VRTK, ControllerEvent
components poll the SDK_Bridge
for controller state and emit events for the benefit of subscribers, usually interaction components. Interaction components may also utilize ControllerAction
components as an API for initiating haptics and manipulating the controller mesh.
How VRTK interactions work
For simplicity’s sake, despite there usually being two tracked controllers they’ll be talked about as one.
As described, ControllerEvent
components emit events to interaction scripts so they can implement their behaviours. This ControllerEvent
instance is placed on a GameObject
along with any of those interaction scripts.
Many interaction scripts use the ‘script alias’ field on the SDKManager
to get a reference to this GO where all the scripts for a controller live. This alias is set when play begins. Changing it during run-time will change which ControllerEvents
instance code that uses these fields will find. However, VRTK does not currently use these fields for anything internally, except for transform tracking which is described next.
How VRTK tracking works
When Play-mode begins, VRTK utilizes the SDKManager
to identify the current GameObject
assigned as the ‘script alias’. It then relocates this GameObject
to be parented to the SDK tracked controller GameObject
. As the SDK tracked controller GO is transformed, so is the now relocated “script alias” GO.
Identified problems with VRTK
- Changing the script alias does not update tracking
- Changing the script alias does not affect event propagation
- Any number of
ControllerEvents
may poll and generate events - Using the
ControllerEvents
parent GO for tracking is limiting - Privacy of fields connecting interaction scripts to
ControllerEvents
is limiting
Each user must handle the above complexity by either:
- twiddling settings on single instances of interaction scripts to model changes in user interactivity
- emulating the swapability provided by this proposal
Proposed Changes
Minor Changes:
- Make
public
the fields of interaction scripts that depend core interaction scripts
Major Changes:
- Merge
ControllerEvents
andControllerActions
intoControllerBridge
- Deprecate all related ‘script alias’ fields and helper methods from
SDKManager
- Create
SDKManager
fields to refer to the current bridge for each controller device - Track
ControllerBridge.trackedTransform
instead of its parent GO. - Move event generation from
ControllerEvents
toControllerSDK.Update
- Only emit events on currently assigned bridges on the
SDKManager
Related Changes:
- Rethink event virtualization
Public Dependency Fields
Making public
the fields which link core interaction scripts to the event and action components they no longer have the artificial limitation of being required to exist on the same object. This allows for some flexibility by linking up these dependencies in the inspector or programatically without inheritance.
Currently these private fields are automatically assigned on script startup. This feature can be reserved in the case that the now public fields are left null
.
ControllerBridge
The merging of the existing ControllerEvents
and ControllerActions
, it is the single interface for “user components” to interact with individual SDK-managed devices.
Event Emission
The ControllerBridge
works much like before. It has events for “user components” interested in device events. Interaction scripts will still register handlers in the way they did before. However, given that their dependency fields are no longer public, these scripts will not be required to exist on the same GO as the bridge.
Actions
Just as before, haptics and highlighting of the device associated with the bridge will be possible. Simply put, the API for ControllerActions
has been absorbed by ControllerBridge
.
Tracked Transform
A new field, ControllerBridge.trackedTransform
will identify the the transform that should be translated to match the tracking of the associated SDK device. This frees the ControllerBridge
from having to specifically be located upon the tracked GameObject
.
SDKManager Fields
At least two new fields are being introduced to the SDKManager
:
ControllerBridge SDKManager.leftBridge
;ControllerBridge SDKManager.rightBridge
;
These fields replace the “script alias” fields. By tracking ControllerBridge
components directly, the dependency on their parent GameObject
s is further reduced, such in the case of tracking.
Transform Tracking
Old way: Reparent the GO assigned as the “script alias” on startup to the SDK-tracked GO.
New way: ControllerSDK
uses the SDKManager
’s bridge fields to get at ControllerBridge.trackedTransform
Event Propagation
Event propagation will be changed from polling in the old ControllerEvents
component against the SDK, to the ControllerSDK.Update
method. Events will be sent directly the the relevant currently assigned ControllerBridge
on the SDKManager
.
This creates one of the largest benefits of the bridge architecture. By simply reassigning the bridge fields on the SDKManager
the flow of events can be altered. Every ControllerBridge
acts as the root event source for a tree of interdependent interaction scripts. This indirection allows for dynamically controlling everything about a players interactability with the game. All without having any arbitrary or artificial constraints regarding the structure of GameObjects, the proximity of interaction components, or any of the previously mentioned concerns.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:2
- Comments:7 (4 by maintainers)
Top GitHub Comments
This needs a tldr; and probably a nice diagram 😃
Merging with https://github.com/thestonefox/VRTK/issues/1523