Search Unity

[WSA/UWP] MonoBehaviour exposes m_InstanceID and m_CachedPtr fields as public

Discussion in 'Windows' started by bboydaisuke, Jun 10, 2016.

  1. bboydaisuke

    bboydaisuke

    Joined:
    Jun 14, 2014
    Posts:
    67
    Hello,
    Is this a known issue?

    PROBLEM:
    MonoBehaviour exposes m_InstanceID and m_CachedPtr fields as public on WSA/UWP.
    Those fields are hidden, even not exposed as non-public on other platforms.

    REPRO CODE:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Reflection;
    4.  
    5. public class NewBehaviourScript : MonoBehaviour {
    6.     public void PropertyCheck()
    7.     {
    8.         Debug.Log("Show public fields:");
    9.         PropertyCheckImpl(BindingFlags.Instance | BindingFlags.Public);
    10.     }
    11.  
    12.     void PropertyCheckImpl(BindingFlags bindingFlags)
    13.     {
    14.         System.Text.StringBuilder builder = new System.Text.StringBuilder();    // Log buffer
    15.  
    16.         // Get FieldInfo list of MonoBehavior inherited class
    17.         var type = this.GetType();
    18.         FieldInfo[] fieldInfoArray = type.GetFields(bindingFlags);
    19.  
    20.         // List all fields, and values
    21.         foreach (var fieldInfo in fieldInfoArray)
    22.         {
    23.             if (fieldInfo.GetValue(this) != null)
    24.                 builder.AppendLine("Field: " + fieldInfo.Name + ", Value: " + fieldInfo.GetValue(this).ToString());
    25.             else
    26.                 builder.AppendLine("Field: " + fieldInfo.Name + ", Value: null");
    27.         }
    28.  
    29.         Debug.Log(builder.ToString());
    30.     }
    31. }
    REPRO STEPS:
    1. Create C# script and paste the code above.
    2. Create a GameObject in scene and add the script to it.
    3. Make it to call NewBehaviourScript.PropertyCheck().
    4. Build the project to Visual Studio project as WSA/UWP.
    5. Open the exported Visual Studio project and run.
    EXPECTED BEHAVIOR:
    You will see no fields are exposed as public field.

    ACTUAL RESULT:
    You will see two fields are exposed as public field as follows:
    ENVIRONMENT:
    • Unity 5.3.4p1, Unity 5.3.5p1
    • Visual Studio 2015 14.0.25123.00 Update 2
    • Windows 10 x64
    • Platform: Windows Store
    • SDK: Universal 10
     
  2. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    Is that a problem? That is kind of by design: on .NET scripting backend, we depend on being able to set this field from outside.

    On IL2CPP scripting backend and other platforms they are private.
     
  3. bboydaisuke

    bboydaisuke

    Joined:
    Jun 14, 2014
    Posts:
    67
    This behavior caused a problem for my project. Though it takes a while to find a root cause, I isolated the problem and root cause is this.

    I'm afraid that I don't understand what this "design" depends on. I looked into UnityEngine.dll and found Object class (which is MonoBehavior's base class) has m_InstanceID, m_CachedPtr as public field.
     
  4. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,736
    What kind of issue have you experienced? Did you have your own fields with the same name?
    They are public on .NET scripting backend because of implementation details, that are specific to this backend. Mono/Il2cpp backends allow them to be private.
     
  5. bboydaisuke

    bboydaisuke

    Joined:
    Jun 14, 2014
    Posts:
    67
    My project has a process that copy settings (public fields' value) from prefab to the objects in scene. Objects in the scene has child objects which are required to work while prefab don't. The process results to copy m_CachedPtr on WSA which means all objects in the scene refers prefab, child objects are gone, and end up to fail to work due to lack of required child objects. So I fixed the problem by skipping those two fields.
    At least the change is one of "breaking changes".

    I know it is public only on Windows Store platform because our code have worked for years on the other platforms.
    I checked UnityEngine.dll under "\Unity\Editor\Data\" and found Object class' member m_InstanceID, m_CachedPtr is implemented as public.

    If the change is intentional, in other words "by design", I don't understand the intention and necessity. If this is unintentional and unnecessary, this breaking change should not be said "by design" IMO.
     
    Last edited: Jun 13, 2016
  6. Tautvydas-Zilys

    Tautvydas-Zilys

    Unity Technologies

    Joined:
    Jul 25, 2013
    Posts:
    10,680
    The change is intentional. On .NET scripting backend, these fields need to be accessed from 2 places:

    1. From WinRTBridge.winmd managed assembly: this is how our native code extracts these values from UnityEngine.Object.
    2. From all the managed assemblies in injected constructors. We invoke those constructors when constructing Objects where we know the cached ptr up front (basically always when constructing these managed objects from native code). They set the cachedPtr and then invoke the default object constructor.

    Is there any reason you cannot use Instantiate to copy your objects?
     
  7. bboydaisuke

    bboydaisuke

    Joined:
    Jun 14, 2014
    Posts:
    67
    Real reason is I'm too busy to re-architect it with following reasons:
    • Want to share code among platforms as much as possible
    • Avoid hard-coding
    I decided to add code for only WSA to skip copying those two fields which is hard-coded.
    Thanks for the explanation. I may predict what will happen on WSA port.
     
    Last edited: Jun 30, 2016