-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Plan of Record] Improve MRTK ease of use: system facades, registrar interface, config ux #3545
Comments
How do we know this docx doesn't contain a malware macro ;) But seriously, could we get these in a better format that's readable from a browser window? |
I can reformat to .md but it will take time |
GitHub does not appear to support attaching .md files.... Sorry about the length of this comment. Proposal: Support Individual Service LocatorsMicrosoft Mixed Reality Toolkit v2 This document describes a design change proposal for the Microsoft Mixed Reality Toolkit v2 concerning how developer customers consume the MRTK and its system services. The Issue: UsabilityThe MRTK team has received feedback from multiple sources that the current, single object presence in the application scene is difficult to use with regards to feature discovery and modularization. Multiple customers, both internal and external, have requested an alternative to beta 2’s MixedRealityToolkit object in the form of system specific locator components (ex: MixedRealityInputLocator) that can be additively included. One piece of feedback, heard from multiple sources, points out the promise of additive vs. subtractive consumption of MRTK. The comments largely center around two themes:
Proposed SolutionThe proposed solution will provide support for both a single, global service locator component (MixedRealityToolkit) and for individual service locator components out of the box in MRTK. This proposal will also enable developer customers to provide their own service locator implementations that can support custom functionality and/or support for a customized collection of pre-existing services. Core Scene Component Refactor and Creation of System Serivce Locator ComponentsThe proposal is to create a set of interfaces and base classes that that the MixedRealityToolkit object and other service locator objects can be built upon. The MRTK would then provide additional service locators for: • Camera Configuration Profile UI ChangesAs part of this work, the configuration profile inspectors will be updated to reduce the complexity and to enable “one stop” modification of settings. This proposal does not mandate merging related profiles, nor does it eliminate profile specific inspectors. Data Provider RegistrationAs of beta 2, all data providers are registered in the Additional Service Providers profile. With this proposal, all data providers will be registered in the profile of the relevant system and loaded / managed by the user's selected service locator, which is potentially the service itself. The additional providers profile will be reserved for extension systems and services. For example, the Windows Mixed Reality Device Manager and Open VR Device Manager components will be registered as data providers with the Input System locator. DetailsThe following sections describe architectural details for this proposal. As the proposal is implemented, some details may change. IMixedRealityServiceLocatorThe IMixedRealityServiceLocator interface will define the core requirements for all service locator implementations. Note: It is under consideration as to whether or not this interface will be subdivided by service type to allow some locator implementations to be simpler and to reduce the number of required methods. Each locator is responsible for loading supported services. The global locator will continue to support loading all currently defined as well as customer created systems and services (implementing IMixedRealityService). The following APIs are the minimum set that will be required. /// <summary>
/// Registers a service with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be registered (ex: IMixedRealityBoundarySystem.
/// <param name="serviceInstance">Instance of the service class.</param>
/// <returns>True if the service was successfully registered, false otherwise.</returns>
bool RegisterService<T>(
IMixedRealityService serviceInstance) where T : IMixedRealityService;
/// <summary>
/// Registers a service with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be registered (ex: IMixedRealityBoundarySystem).
/// <param name="concreteType">The concrete type to instantiate.</param>
/// <param name="supportedPlatforms">The platform(s) on which the service is supported.</param>
/// <param name="args">Optional arguments used when instantiating the concrete type.</param>
/// <returns>True if the service was successfully registered, false otherwise.</returns>
bool RegisterService<T>(
Type concreteType,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args = null) where T : IMixedRealityService;
/// <summary>
/// Unregisters a service from the service locator.
/// </summary>
/// <param name="name">The name of the service to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
bool UnregisterService(string name);
/// <summary>
/// Unregisters a service from the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be unregistered (ex: IMixedRealityBoundarySystem).
/// <param name="name">The name of the service to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
/// <remarks>If the name argument is not specified, the first instance will be unregistered</remarks>
bool UnregisterService<T>(
string name = null) where T : IMixedRealityService;
/// <summary>
/// Unregisters a service from the service locator.
/// </summary>
/// <param name="service">The specific service instance to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
bool UnregisterService(IMixedRealityService serviceInstance);
/// <summary>
/// Unregisters all services from the service locator.
/// </summary>
void UnregisterServices();
/// <summary>
/// Unregisters all services from the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the services to be unregistered (ex: IMixedRealityBoundarySystem).
void UnregisterServices<T>() where T : IMixedRealityService;
/// <summary>
/// Checks to see if a service has been registered with the service locator.
/// </summary>
/// <param name="name">The name of the service.</param>
/// <returns>True if the service is registered, false otherwise.</returns>
bool IsRegistered(string name);
/// <summary>
/// Checks to see if a service has been registered with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service (ex: IMixedRealityBoundarySystem).
/// <param name="name">The name of the service.</param>
/// <returns>True if the service is registered, false otherwise.</returns>
bool IsRegistered<T>(string name == null) where T : IMixedRealityService;
/// <summary>
/// Gets the instance of the registered service.
/// </summary>
/// <param name="name">The name of the service.</param>
/// <returns>The registered service instance, as IMixedRealityService.</returns>
IMixedRealityService GetService(string name);
/// <summary>
/// Gets the instance of the registered service.
/// </summary>
/// <typeparam name="T">The interface type of the service (ex: IMixedRealityBoundarySystem).
/// <param name="name">The name of the service.</param>
/// <returns>The registered service instance as the requested type.</returns>
T GetService<T>(string name) where T : IMixedRealityService;
/// <summary>
/// Gets the collection of the registered service instances matching the requested type.
/// </summary>
/// <returns>Read-only collection of the service instances, as IMixedRealityService.</returns>
IReadOnlyList<IMixedRealityService> GetServices();
/// <summary>
/// Gets the collection of the registered service instances matching the requested type.
/// </summary>
/// <typeparam name="T">The interface type of the service (ex: IMixedRealityBoundarySystem).
/// <returns>Read-only collection of the service instances, as type requested type.</returns>
IReadOnlyList<T> GetServices<T>() where T : IMixedRealityService; IMixedRealityExtensionServicelocatorThe IMixedRealityServicelocator can manage any service that implements IMixedRealityService and the IMixedRealityExtensionService is defined as extending this interface. The IMixedRealityExtensionServicelocator interface is an optional interface that provides methods that can be implemented to limit management to implementations of IMixedRealityExtensionService. /// <summary>
/// Registers an extension service with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be registered.
/// <param name="serviceInstance">Instance of the service class.</param>
/// <returns>True if the service was successfully registered, false otherwise.</returns>
bool RegisterExtensionService<T>(
IMixedRealityExtensionService serviceInstance) where T : IMixedRealityExtensionService;
/// <summary>
/// Registers an extension service with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be registered.
/// <returns>True if the service was successfully registered, false otherwise.</returns>
bool RegisterExtensionService<T>(
Type concreteType,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args = null) where T : IMixedRealityExtensionService;
/// <summary>
/// Unregisters an extension service from the service locator.
/// </summary>
/// <param name="name">The name of the service to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
bool UnregisterExtensionService(string name);
/// <summary>
/// Unregisters a service from the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service to be unregistered.
/// <param name="name">The name of the service to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
/// <remarks>If the name argument is not specified, the first instance will be unregistered</remarks>
bool UnregisterExtensionService<T>(string name == null) where T : IMixedRealityExtensionService;
/// <summary>
/// Unregisters an extension service from the service locator.
/// </summary>
/// <param name="service">The specific service instance to unregister.</param>
/// <returns>True if the service was successfully unregistered, false otherwise.</returns>
bool UnregisterExtensionService(IMixedRealityExtensionService serviceInstance);
/// <summary>
/// Unregisters all extension services from the service locator.
/// </summary>
bool UnregisterExtensionServices();
/// <summary>
/// Unregisters all extension services from the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the services to be unregistered.
bool UnregisterExtensionServices<T>() where T: IMixedRealityExtensionService;
/// <summary>
/// Checks to see if an extension service has been registered with the service locator.
/// </summary>
/// <param name="name">The name of the service.</param>
/// <returns>True if the service is registered, false otherwise.</returns>
bool IsExtensionServiceRegistered(string name);
/// <summary>
/// Checks to see if an extension service has been registered with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the service.
/// <param name="name">The name of the service.</param>
/// <returns>True if the service is registered, false otherwise.</returns>
bool IsExtensionServiceRegistered<T>(string name == null) where T : IMixedRealityExtensionService;
/// <summary>
/// Gets the instance of the registered extension service.
/// </summary>
/// <param name="name">The name of the service.</param>
/// <returns>The registered service instance, as IMixedRealityExtensionService.</returns>
IMixedRealityExtensionService GetExtensionService(string name);
/// <summary>
/// Gets the instance of the registered extension service.
/// </summary>
/// <typeparam name="T">The interface type of the service (ex: IMixedRealityBoundarySystem).
/// <param name="name">The name of the service.</param>
/// <returns>The registered service instance as the requested type.</returns>
T GetExtensionService<T>(string name) where T : IMixedRealityExtensionService;
/// <summary>
/// Gets the collection of the registered extension service instances matching the requested type.
/// </summary>
/// <returns>Read-only collection of the service instances, as IMixedRealityService.</returns>
IReadOnlyList<IMixedRealityExtensionService> GetExtensionServices();
/// <summary>
/// Gets the collection of the registered extension service instances matching the requested type.
/// </summary>
/// <typeparam name="T">The interface type of the service (ex: IMixedRealityBoundarySystem).
/// <returns>Read-only collection of the service instances, as tye requested type.</returns>
IReadOnlyList<T> GetExtensionServices<T>() where T: IMixedRealityExtensionService; IMixedRealityDataProviderlocatorAs with extension services, the IMixedRealityServicelocator can also manage data providers that implement the IMixedRealityDataProvider interface. Similarly, the IMixedRealityExtensionServicelocator supports management of IMixedRealityDataProvider implementations. The IMixedRealityDataProviderlocator interface is an optional interface that provides methods that can be implemented to limit management to implementations of IMixedRealityDataProvider. /// <summary>
/// Registers a data provider with the data provider locator.
/// </summary>
/// <typeparam name="T">The interface type of the data provider to be registered.
/// <param name="dataProviderInstance">Instance of the data provider class.</param>
/// <returns>True if the data provider was successfully registered, false otherwise.</returns>
bool RegisterDataProvider<T>(
IMixedRealityDataProvider dataProviderInstance) where T : IMixedRealityDataProvider;
/// <summary>
/// Registers a data provider with the data provider locator.
/// </summary>
/// <typeparam name="T">The interface type of the data provider to be registered.
/// <returns>True if the data provider was successfully registered, false otherwise.</returns>
bool RegisterDataProvider<T>(
Type concreteType,
SupportedPlatforms supportedPlatforms = (SupportedPlatforms)(-1),
params object[] args = null) where T : IMixedRealityDataProvider;
/// <summary>
/// Unregisters a data provider from the data provider locator.
/// </summary>
/// <param name="name">The name of the data provider to unregister.</param>
/// <returns>True if the data provider was successfully unregistered, false otherwise.</returns>
bool UnregisterDataProvider(string name);
/// <summary>
/// Unregisters a data provider from the data provider locator.
/// </summary>
/// <typeparam name="T">The interface type of the data provider to be unregistered.
/// <param name="name">The name of the data provider to unregister.</param>
/// <returns>True if the data provider was successfully unregistered, false otherwise.</returns>
/// <remarks>If the name argument is not specified, the first instance will be unregistered</remarks>
bool UnregisterDataProvider<T>(string name == null) where T : IMixedRealityDataProvider;
/// <summary>
/// Unregisters a data provider from the service locator.
/// </summary>
/// <param name="service">The specific data provider instance to unregister.</param>
/// <returns>True if the data provider was successfully unregistered, false otherwise.</returns>
bool UnregisterDataProviderService(IMixedRealityDataProvider dataProviderInstance);
/// <summary>
/// Unregisters all data providers from the data provider locator.
/// </summary>
bool UnregisterDataProviders();
/// <summary>
/// Unregisters all data providers from the data provider locator.
/// </summary>
/// <typeparam name="T">The interface type of the data providers to be unregistered.
bool UnregisterDataProviders<T>() where T: IMixedRealityDataProvider;
/// <summary>
/// Checks to see if a data provider has been registered with the service locator.
/// </summary>
/// <param name="name">The name of the data provider.</param>
/// <returns>True if the data provider is registered, false otherwise.</returns>
bool IsDataProviderRegistered(string name);
/// <summary>
/// Checks to see if a data provider has been registered with the service locator.
/// </summary>
/// <typeparam name="T">The interface type of the data provider.
/// <param name="name">The name of the data provider.</param>
/// <returns>True if the data provider is registered, false otherwise.</returns>
bool IsDataProviderRegistered<T>(string name == null) where T : IMixedRealityDataProvider;
/// <summary>
/// Gets the instance of the registered data provider.
/// </summary>
/// <param name="name">The name of the data provider.</param>
/// <returns>The registered data provider instance, as IMixedRealityDataProvider.</returns>
IMixedRealityDataProvider GetDataProvider(string name);
/// <summary>
/// Gets the instance of the registered data provider.
/// </summary>
/// <typeparam name="T">The interface type of the data provider.
/// <param name="name">The name of the data provider.</param>
/// <returns>The registered data provider instance as the requested type.</returns>
T GetDataProvider<T>(string name) where T : IMixedRealityDataProvider;
/// <summary>
/// Gets the collection of the registered data provider instances matching the requested type.
/// </summary
/// <returns>Read-only collection of the data provider instances, as IMixedRealitydata provider.</returns>
IReadOnlyList<IMixedRealityDataProvider> GetDataProviders();
/// <summary>
/// Gets the collection of the registered data provider instances matching the requested type.
/// </summary>
/// <typeparam name="T">The interface type of the data provider.
/// <returns>Read-only collection of the data provider instances, as tye requested type.</returns>
IReadOnlyList<T> GetDataProviders<T>() where T: IMixedRealityDataProvider; MixedRealityServicelocatorBaseThe MixedRealityServicelocatorBase class will provide a default implementation of the IMixedRealityServicelocator interface and will be leveraged by MixedRealityExtensionServicelocatorBase and MixedRealityDataProviderlocatorBase. Custom service locator implementations are encouraged to inherit from MixedRealityServicelocatorBase and customize behaviors as needed to avoid the need to implement duplicate code. MixedRealityExtensionServicelocatorBaseThe MixedRealityExtensionServicelocatorBase class will use MixedRealityServicelocatorBase to handle core service management functionality and add a layer of type checking to ensure that all managed services implement IMixedRealityExtensionService. MixedRealityDataProviderlocatorBaseThe MixedRealityDataProviderlocatorBase class will use MixedRealityServiceExtensionlocatorBase to handle core service management functionality and add a layer of type checking to ensure that all managed services implement IMixedRealityDataProvider. MixedRealityToolkit Class RefactorAs part of the interface and base class definition and implementation process, the MixedRealityToolkit class will be refactored with common and reusable code moving into the base class. System locatorslocators for each of the systems listed previously will be created leveraging the base classes and interfaces. Not all system locators will require all features (ex: the Spatial Awareness system does not use a profile) and each will implement the minimum set of interfaces necessary. System Implementation ChangesAs the systems will no longer be able to expect the concrete MixedRealityToolkit class to be managing them, the current system implementations will need to be updated. These changes will involve requesting data from the locator via interface contracts. Data ProvidersWith this proposal, each system will bear the responsibility for Unloading and managing registered data providers. The system implementations will call into the system locator to Unload, Unregister and request data about the registered data providers. Scene PresenceTo better support a wide variety of developers and applications, while maintaining the goal if MRTK being minimally intrusive in the scene hierarchy, the scene presence will be modified to add a Mixed Reality Toolkit top level GameObject which will contain the MRTK’s system locator(s). The following images illustrate the single, global locator and individual component locator options. For customers wishing to use the current, global system locator, the hierarchy now nests the MixedRealityToolkit object in a parent of the same name (exact name TBD). Customers that prefer to explicitly add individual system locators will see each added under the MixedRealityToolkit parent object. Each of the previous illustrations show the hierarchy that will appear when using the Mixed Reality Toolkit > Configure menu. Customers are free to manually modify / build the MRTK presence in their scene(s) manually if desired. For reference, the scene hierarchy in beta 2 is shown in the following illustration. While the above is arguably somewhat cleaner, collapsing the new MixedRealityToolkit parent object presents a similar appearance. Additionally, adding a parent object allows for better containment of scene components added and managed by MRTK, for example spatial mesh objects. Configuration MenuThe Mixed Reality Toolkit menu’s Configure item will be expanded to support configuring for the global system locator or individual component locators. The following image illustrates early thinking of the configuration UI. Configuration ProfilesExisting system configuration profiles will continue to be used by the systems regardless of the chosen locator. It is expected that some minor modifications to the user interface / navigation may be required to best provide a delightful customer experience. ExamplesThe following sections describe examples of how locators and services will be discovered and referenced in code. • locator Access in Services locator Access in ServicesWhen a locator loads a service, the constructor will be passed an instance of IMixedRealityServicelocator to provide access to an equivalent of beta 2’s MixedRealityToolkit.Instance property. Data Provider ManagementThrough the IMixedRealityServicelocator instance, services will be able to request data provider management (register, unregister, etc.). There are two proposals for providing service access to application code to replace beta 2’s direct MixedRealityToolkit calls. For example (ex: MixedRealityToolkit.Instance.InputSystem). Proposal 1: GetServicelocator()One possible solution is to provide a script that is attached to the MixedRealityToolkit parent object that iterates through the scene and builds a table of locator objects and which services the manage. This table would be created by locators registering themselves at startup. Application code would then request the appropriate locator for their service(s) of interest. Proposal 2: Script Registration of Service locatorAnother proposed solution involves customers dragging the instance of the locator to a script in the inspector. The MixedRealityToolkit would provide a generic solution that can be used or extended by customer projects. This solution would provide a mapping of service interface to locator instance. For example:
Data Provider Access in Application CodeAccess to data provider instances should be provided by the service which consumes the provider. This allows most application code to avoid needing knowledge of the locator and allows services to control when data providers are registered and unregistered. The current (beta 2) Spatial Awareness system implementation demonstrates this pattern: /// <summary>
/// Gets the collection of registered <see cref="IMixedRealitySpatialAwarenessObserver"/> data providers.
/// </summary>
/// <returns>
/// Read only copy of the list of registered observers.
/// </returns>
IReadOnlyList<IMixedRealitySpatialAwarenessObserver> GetObservers();
/// <summary>
/// Get the collection of registered observers of the specified type.
/// </summary>
/// <typeparam name="T">The desired spatial awareness observer type (ex: <see cref="IMixedRealitySpatialAwarenessMeshObserver"/>)</typeparam>
/// <returns>
/// Readonly copy of the list of registered observers that implement the specified type.
/// </returns>
IReadOnlyList<T> GetObservers<T>() where T : IMixedRealitySpatialAwarenessObserver;
/// <summary>
/// Get the <see cref="IMixedRealitySpatialAwarenessObserver"/> that is registered under the specified name.
/// </summary>
/// <param name="name">The friendly name of the observer.</param>
/// <returns>
/// The requested observer, or null if one cannot be found.
/// </returns>
/// <remarks>
/// If more than one observer is registered under the specified name, the first will be returned.
/// </remarks>
IMixedRealitySpatialAwarenessObserver GetObserver(string name);
/// <summary>
/// Get the observer that is registered under the specified name matching the specified type.
/// </summary>
/// <typeparam name="T">The desired spatial awareness observer type (ex: <see cref="IMixedRealitySpatialAwarenessMeshObserver"/>)</typeparam>
/// <param name="name">The friendly name of the observer.</param>
/// <returns>
/// The requested observer, or null if one cannot be found.
/// </returns>
/// <remarks>
/// If more than one observer is registered under the specified name, the first will be returned.
/// </remarks>
T GetObserver<T>(string name) where T : IMixedRealitySpatialAwarenessObserver; After calling one of the GetObserver methods, applications are able to modify properties and control the activity of the spatial awareness observers. |
@davidkline-ms I am always causious when un-known text is used as identifiers for object recognition. Using the Friendly Name as an index into a list of objects can cause errors due to name collisions. I would like to see if the usage of Namespaces can be impemented in the when registering and un-regestering services by name or type. This would allow for multiple implementations of a service to be alive but unique. For example having multiple controllers available to be used at the same time. Scenario: When a student is running an application in WHMD or HoloLens an instructor may want to show the Student where to click or point them in a direction to assit in thier learning. The students could be using the Motion Controllers and the Instructor could be using an XBox One controller. Different Cursors and interaction can be defined for visuals. i.e bool RegisterService<T>(string "name", string "nameSpace) where<T> = baseClass or interface bool RegisterService<T>(Type typeWithNamspace) |
@hridpath, thanks for the feedback! |
I think everyone is overthinking a lot of this stuff, and there's a focus on "Scene" objects, when the fact of the matter is, none of this stuff exists in the scene. We're working with POCO objects. Classes and structures that should (in theory) be independent from Unity as much as possible. (Let's not even talk about how adding additional GameObjects that don't really do much of anything, could impact performance). I think taking a bigger focus on educating people how to understand and use the system would help. Yes, this new way of doing things is very different to traditional unity developers, but I think it's counterproductive to give into the pressure of such feedback without attempting to educate people. A bit nitpicky here with the terminology, but didn't we agree (months and months ago) that the term manager implied a single instance of something (and we ended up with system). Adding manager to the end of anything with System seems redundant, less descriptive, and more confusing. |
Just want to give a little extra context. This feedback is coming directly from partners building production HoloLens applications with MRTK. In fact many Microsoft employees close to MRTK worked directly with them to educate and guide them. The general feedback has been services and profiles are confusing, the system feels heavy and the MRTK Singleton is very aggressive. The feedback isn’t around POCO and decoupling services from MonoBehaviors. We’re in beta, we’ve received legitimate feedback, we shouldn’t brush it off, we should figure out how to make MRTK work better. Education/documentation is only part of the solution. |
I'm a huge fan of the increased scene presence. This will help me teach the folks I work with about how MRTK works. |
Big fan of this proposal. Directly addresses some of the loudest criticism / chatter I've been hearing from folks using the toolkit. I've been an advocate of the existing approach for a while but there's no shame in accepting that it didn't get the traction we'd hoped for. Like @radicalad says, we're in beta - now's the time. @StephenHodgson agreed that educating people should be our goal - and the best way to teach someone about a new system is to present in familiar terms. Increased scene presence for services is a win regardless of (frankly minimal) perf costs. Nobody likes to be told their ignorance is the reason something is hard to use, and who can blame them? @davidkline-ms This is just nitpicking but I do find the names hard to look at. I feel like there's got to be a better suffix than Manager - ServiceExecutor? ServiceLocator? ServiceHandler? |
While I can see that, the intent of these interfaces is to manage (load, unload, enumerate, etc) services. I'll give the interface names / service controllers (would that work?) some thought and get consensus from others before submitting any code. Hopefully the proposal's use of "manager" doesn't distract from the goal. Also, please note that the proposal does not include removing the current approach, just augmenting it with the ability to add a system specific scene presence as well as the ability for others to easily add support for MRTK systems in their own components. |
@davidkline-ms Agreed, the names are not a dealbreaker. |
Could we elaborate on this? There isn't much substantial objective criteria here to formulate an appropriate response.
💯% agree, and that wasn't exactly what I was trying to say, just that I think we should give people time to get familiar with it before deciding to fundamentally change the way it all works. It'll be interesting to see how much workflows will continue change once Unity finishes up with ECS and DOTS. Traditional Unity development pipelines are going to be fundamentally changing a lot here in the near future. Overall I think this is a step backwards, not forwards. |
The existing MixedRealityToolkit object will remain an option. This is about providing options based on customer feedback. |
I can very much elaborate on this one. We have an unwieldy and over-engineered set of nested profiles and a frustratingly restrictive architecture. Which basically leads to the inability for anyone to incorporate MRTK in an existing project. If I used it in a new project I would quickly run into an inflexible set of requirements that kill iteration times. In general quality in products is a function of evolutionary or iteration time steps. Ideally everything should be easily extensible and able to function as a standalone service in whatever structure a developer wants to incorporate it. Case study, use the toolkit with others at a game jam or hackathon and observe.
I couldn't disagree more. The phrase "give people time to get familiar" is an indicator that it's not intuitive. It's like a level designer saying that someone is "playing it wrong" only because they designed it for their golden path. Regardless of Unity's structural changes and features, if you rely on what their "new" infrastructures are you will always be on some shaky ground until they are proven and solidified. The step to having more namespaces than the library of congress and one ring to rule them all was a larger step backwards IMO. thanks, |
@StephenHodgson If your predictions about Unity's workflow are true then maybe this is just a case of a system being slightly ahead of its time. In which case it would be best to wait for Unity to boil the frog a bit longer and revisit the issue when devs are more receptive. You can't surf a wave that's still underwater. |
Agreed, that's my biggest fear with this proposal.
Ouch, yup. You're absolutely right 🤣 |
One thing that I'd like to note with the service locator object, it that it's really just a manifest for all of the services that are running. It doesn't really do much of anything else, besides doing some scene setup with the event system, and camera. I'm curious to know how this impacts everyone's thoughts on why it feels heavy handed and unweildy. The biggest problem it was trying to solve was ensuring that the object lifetimes were handled appropriately and MonoBehaviour events forwarded.
The first part I believe to already be true, but if you could elaborate on the other structures?
I wish I could have attended some, it would have been very interesting to see and learn from. The mrtk was supposed to handle 90% of the needs, while letting the developer get that last 10% For example:
Is there something above I missed? |
Love this idea @hridpath |
The TL;DR I'm for this proposal and anything that makes our "mangers" system more Unity-like and scene accessible. I 💯% agree for the need of system presence in the scene hierarchy. One of the reasons I believe Unity has become successful, especially among people new to game/3D development, is the accessibility of inspecting your app's state at runtime via the scene view. As it stands currently I can't really tell what state my systems are in and/or which ones are enabled without stepping though a debugger or plunging though profiles. I also agree with @Railboy about
A value I take into consideration when building new features in Unity is "does something akin to this featue already exist, and how can I make my feature behave as similar as possible to the way it's currently done?" When doing this you provided your users with familiarity and reduce friction when stepping into your new feature. The real win is when users can be productive right out of the gate because they have used a similar feature before. |
^ This |
Having a visual representation of the currently running systems is good feedback, but I'm not entirely convinced that we should use the scene as a representation of said information. The scene is only for UX/UI. It's a single layer of the application that should be reactive to the business level app logic. What about if we had another way to represent them without putting them in the scene? These services/managers don't exist in the scene in any way, nor should they (they're purely c#). I'm open to making a window that looks very similar to the scene window, with a hierarchy that shows the relationships between services, and their data models. Let's call it the service graph |
|
That's missing the point. I'm a Unity dev, and I have an incredibly powerful debugging tool that's constantly maintained and improved by one of the most accomplished game engine development teams in the world. Let me use that tool. Don't make me go without. Don't make me use Visual Studio. Don't make me use a home brewed version of that tool that only exists in MRTK. |
Service Registration (#3545) - Part 2 [Breaking Change for Service Implementors]
…ing Change for Service Implementors])
Service registration (#3545) part 3 - systems load data providers
Closing as the infrastructure work is complete. Prefabs for standalone service usage are to be added in an experimental namespace in the SDK. Configuration UX will be addressed via a separate set of work. |
Plan of Record: Support Service Specific Scene Presence
Microsoft Mixed Reality Toolkit v2
This document describes a design change for the Microsoft Mixed Reality Toolkit v2 concerning how developer customers can choose the MRTK and its services.
The Issue: Usability
The MRTK team has received feedback from multiple sources that the current, single object presence in the application scene is difficult to use with regards to feature discovery and modularization. Multiple customers, both internal and external, have requested an alternative to beta 2’s MixedRealityToolkit object in the form of system specific locator components (ex: MixedRealityInputLocator) that can be additively included.
One piece of feedback, heard from multiple sources, points out the promise of additive vs. subtractive consumption of MRTK. The comments largely center around two themes:
Solution: Enable Support for Individual Services to have Scene Presence
The solution defines the following changes:
Please see the Solution Details section of this document for information the described changes.
Goals
Non-Goals
Solution Details
Service Registration Interfaces
To enable developers to create custom service locators and/or extend an existing service locator to add support for MRTK services, a set of interfaces will be created to support the registration and retrieval of service instances.
It is anticipated that there will either be one or three interfaces that will be created. The following sections describe the pros and cons of each implementation.
Single Registrar Interface
In the single interface approach, the MRTK will define IMixedRealityServiceRegistrar. This interface would define explicit methods for supporting objects implementing the following service types (listed by interface):
Each method (Register, Unregister, Get, CheckRegistration) will have a version that is type safe to the listed interfaces.
Multiple Registrar Interfaces
In the multiple interface design, each type of service would have a corresponding registrar interface:
This approach would allow customers to support only the specific types of services necessary to build their component.
Base Class Implementations
As with much of the MRTK, base classes will be provided to provide robust, reusable implementations of the registrar interface(s).
Providing the Registrar Instance to Services
When the registrar instantiates a service instance, it will provide itself as a constructor argument. The following example shows the parameter to be added to each service constructor.
A similar pattern will occur for data providers.
When a service requests registration of a data provider, it calls RegisterDataProvider, handing a reference to itself.
The data provider's constructor is passed the provided reference in its constructor.
Service Facades
Service facades are an editor only monobehavior that exists in the application scene to give customers and easy, at-a-glance representation of the active services in the scene. When selected, the facade will display the service specific profile inspector and allow for easy configuration.
Backing these facades will be added to the scene and backed by the MRTK service locator. Developers not wishing these facades to be in their scene will be able to disable them in the MixedRealityToolkitConfiguration profile.
Hybrid Application Architecture
Hybrid applications architecture is a term intended to describe an application which utilizes any number of service locators and/or stand-alone service implementations.
To support hybrid architectures, MRTK will add a light-weight service registry that enables client code easy access to concrete service implementations.
Service Registry
The service registry in MRTK is an optional component that client code can use to acquire an instance of a desired service.
The registry can be thought of as a table that maps service interfaces to the object that manages the concrete implementation(s) .
The following table illustrates an example registry:
The component managing the service registry can be attached to client script(s) or developers can choose to bypass the registry and hard-code references to the object managing service registration.
For example:
Scene Hierarchy
To help keep the scene hierarchy uncluttered, the default MRTK configuration process will create a Mixed Reality Toolkit parent object. This object will be the parent for the service locator and any enabled facades.
It is recommended that this object be the parent of objects created by registered services (ex: spatial awareness mesh objects).
The following image illustrates the default hierarchy when the MRTK service locator is used with the input and spatial awareness system facades enabled.
Project Configuration UX
To make it easy and intuitive for customers to configure MRTK to suit their application's requirements, the Mixed Reality Toolkit menu's Configure item will display a selection dialog similar to the following illustration.
The text was updated successfully, but these errors were encountered: