Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Question Get <T> reference from QueryResults (SynthesizedTrait<T> ?)

Discussion in 'Unity MARS' started by Jared_playstudios, Apr 26, 2021.

  1. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    I think I'm looking for a way to get a component (ie. Transform, GameObject, Foo, etc) from an object that matches a Proxy's QueryResult.

    I'm trying to write an Action that will allow me to move UI under the correct RectTransform without a scene reference. I've seen the Walkthrough Sample, which is good, but seems to require some scene references. AssetBundles and building these at runtime would allow for some more scalable experiences.

    So, what I have is
    • A Canvas in a scene that has a SynthesizedObject, SynthesizedReferencePoint, SynthesizedPose, and SynthesizedSemanticTag.
    • A Proxy in a prefab with a SemanticTagCondition to match the object, and my action component to try and get any information about the Canvas that matches the Semantic Tag.

    And... typing this up, I think I see that I need a SynthesizedCanvas, or a SynthesizedRectTransform... I can get the Pose from the SynthesizedPose. Is that how this is supposed to work? Am I looking for a SynthesizedTrait<RectTransform> ?
     
  2. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    Looks like I can get everything except the associated RectTransform itself, using Synthesized elements, and Traits, an IMatchAcquireHandler. I can pass the position, and the sizeDelta, and other floats, Vector2, etc.

    I'm having trouble now getting a custom struct to adhere to the same pattern as the internal Pose class. I think it is because MARS has defined Traits that exist somewhere internal or in an AOT way within the namespace. Is it possible to add new Structs to the FunctionalityProviders?

    Getting lots of errors from IProvidesTraits.cs line 47 and line 52

    Here's a representation of my code:
    Code (CSharp):
    1. [Serializable]
    2. public struct CustomData : IEquatable<CustomData>
    3. {
    4.     public Vector2 size;
    5.     //... IEquatable stuff
    6. }
    7.  
    8. public class SynthesizedCustomData : SynthesizedTrait<CustomData>, IUsesCameraOffset
    9. {
    10.     public override string TraitName { get { return "customdata"; } }
    11.     public override bool UpdateWithTransform { get { return true; } }
    12.     IProvidesCameraOffset IFunctionalitySubscriber<IProvidesCameraOffset>.provider { get; set; }
    13.  
    14.     public override CustomData GetTraitData()
    15.     {
    16.         // I actually populate the CustomData, but, psuedo code here
    17.         return new CustomData();
    18.     }
    19. }
    20.  
    21. public class CustomDataAction : MonoBehaviour, IMatchAcquireHandler, IRequiresTraits
    22. {
    23.         static readonly TraitRequirement[] k_RequiredTraits = {
    24.             new TraitRequirement(new TraitDefinition("customdata", typeof(CustomData)), true)
    25.         };
    26.  
    27.         public void OnMatchAcquire(QueryResult queryResult)
    28.         {
    29.             if (!queryResult.TryGetTrait("customdata", out CustomData customData))
    30.                 return;
    31.  
    32.             Debug.Log("yay!");
    33.         }
    34. }
     
    Last edited: Apr 27, 2021
  3. jmunozarUTech

    jmunozarUTech

    Unity Technologies

    Joined:
    Jun 1, 2020
    Posts:
    295
    hello @Jared_playstudios, could you share with us your stack trace to see what errors specifically you have?
     
  4. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    Thanks for the help. I'm using MARS 1.3, and Unity 2020.2.7. I've tried a few things, but the simplest way to repro is to copy this code into a script, and add the component to a synthesizedObject, and press play:

    Code (CSharp):
    1. using Unity.MARS.Data.Synthetic;
    2. using Unity.MARS.Providers;
    3. using Unity.XRTools.ModuleLoader;
    4.  
    5. public class CustomData
    6. {
    7.     int v = 1;
    8. }
    9.  
    10. public class SynthesizedCustomData : SynthesizedTrait<CustomData>, IUsesCameraOffset
    11. {
    12.     public override string TraitName => "customdata";
    13.     public override bool UpdateWithTransform { get { return true; } }
    14.  
    15.     IProvidesCameraOffset IFunctionalitySubscriber<IProvidesCameraOffset>.provider { get; set; }
    16.  
    17.     public override CustomData GetTraitData()
    18.     {
    19.         return new CustomData();
    20.     }
    21. }
    My results complain once when it loads:
    And then every frame, it complains again:
     
  5. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    I've also gone pretty far down SynthesizedTrackable, IProviderTraits (and how they are registered with MARSDatabase), as well as IUsesMARSTrackableData, and SimulatedProviders. I've tried developing this functionality within a Packages Directory, as well as in Assets. It seems that the Generated.cs file containing the partial MARSDatabase defines the types that are supported. I appreciate that these are no longer Internal, however I'm not seeing an easy extensible way to add our own Trackables or Traits. And Debugging through the interfaces is fairly tedious.

    Near as I can tell, the AddTrait<T> or AddOrUpdateTrait<T> methods (defined in the IProvidesTraitsMethods class) have an internal getter that isn't retrieving my classes SynthesizedTrait<T> values. Not quite clear why.
     
  6. unity_andrewm

    unity_andrewm

    Unity Technologies

    Joined:
    Jun 25, 2015
    Posts:
    73
    Hi Jared,

    If you're looking to get components that are on the proxy itself, you should just be able to call regular GetComponent - proxies and actions are all monobehaviours under the hood and have access to those functions.

    If you're looking to get at components on the SynthesizedObject, it stores a reference to itself in the MARS data. (It implements the IUsesMARSData interface) - it is also a monobehaviour and you should be able to use that for component access.
    In this case you would make an action that inherits IUsesMARSData<SynthesizedObject> and then calling ResolveValue on the QueryResult will give you the SynthesizedObject reference
     
  7. jmunozarUTech

    jmunozarUTech

    Unity Technologies

    Joined:
    Jun 1, 2020
    Posts:
    295
    @Jared_playstudios

    interesting; could you try deleting
    Code (CSharp):
    1. Assets/MARS/Generated
    and see if that fixes it?
     
  8. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    I've tried the suggested:
    The files that got regenerated were the same (Only diff was new meta guids), and the errors I saw were the same as well. Didn't pick-up or include my CustomData class from the example above.
     
  9. mtschoen

    mtschoen

    Unity Technologies

    Joined:
    Aug 16, 2016
    Posts:
    187
    Hey @Jared_playstudios, sorry to hear that you're still having trouble. I was really hoping that re-generating code would fix it!

    Are you able to submit your project folder in a bug report so we can try it on our end? If not, a simple project that replicates the issue will also work. If you're willing to share, you can simply go to Help > Report a Bug... and fill out the form. Make sure that you don't remove anything from the files section below.

    Thanks for reporting this issue; hopefully we can help you resolve it!
     
  10. Jared_playstudios

    Jared_playstudios

    Joined:
    Mar 27, 2019
    Posts:
    11
    Bug Filed (Case# 1333546): https://fogbugz.unity3d.com/default.asp?1333546_20ccdvk59fvhp45k

    Or this can be duplicated by copying this simple script (SynthesizedCustomData.cs):
    Code (CSharp):
    1. using Unity.MARS.Data.Synthetic;
    2. using Unity.MARS.Providers;
    3. using Unity.XRTools.ModuleLoader;
    4. public class CustomData
    5. {
    6.     int v = 1;
    7. }
    8. public class SynthesizedCustomData : SynthesizedTrait<CustomData>, IUsesCameraOffset
    9. {
    10.     public override string TraitName => "customdata";
    11.     public override bool UpdateWithTransform { get { return true; } }
    12.     IProvidesCameraOffset IFunctionalitySubscriber<IProvidesCameraOffset>.provider { get; set; }
    13.     public override CustomData GetTraitData()
    14.     {
    15.         return new CustomData();
    16.     }
    17. }
    And adding SynthesizedObject component, and the above component (SynthesizedCustomData) to a gameObject in a MARS scene. Then press play.

    Unity 2020.1.9f1, Unity MARS 1.3.0, Import Samples, Open a MARS sample scene, add the script.
     
    jmunozarUTech likes this.