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:
using UnityEngine;
using System.Collections;
using System.Reflection;
public class NewBehaviourScript : MonoBehaviour {
public void PropertyCheck()
{
Debug.Log("Show public fields:");
PropertyCheckImpl(BindingFlags.Instance | BindingFlags.Public);
}
void PropertyCheckImpl(BindingFlags bindingFlags)
{
System.Text.StringBuilder builder = new System.Text.StringBuilder(); // Log buffer
// Get FieldInfo list of MonoBehavior inherited class
var type = this.GetType();
FieldInfo[] fieldInfoArray = type.GetFields(bindingFlags);
// List all fields, and values
foreach (var fieldInfo in fieldInfoArray)
{
if (fieldInfo.GetValue(this) != null)
builder.AppendLine("Field: " + fieldInfo.Name + ", Value: " + fieldInfo.GetValue(this).ToString());
else
builder.AppendLine("Field: " + fieldInfo.Name + ", Value: null");
}
Debug.Log(builder.ToString());
}
}
REPRO STEPS:
- Create C# script and paste the code above.
- Create a GameObject in scene and add the script to it.
- Make it to call NewBehaviourScript.PropertyCheck().
- Build the project to Visual Studio project as WSA/UWP.
- 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
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.
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.
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.
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.
The change is intentional. On .NET scripting backend, these fields need to be accessed from 2 places:
- From WinRTBridge.winmd managed assembly: this is how our native code extracts these values from UnityEngine.Object.
- 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?
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.