Hi everyone !
I’m working in a save system using reflection.
Recently discovered that calling “property.GetValue”, not only returns the current value but it creates new instances of its materials, meshes, etc. Perhaps someone knows how to avoid this.
Here is a little example code.
void Start(){
PropertyInfo[] properties = renderer.GetType().GetProperties();
foreach( PropertyInfo property in properties ){
Debug.Log(" > > > Prop Name: " + property.Name + " / Value: " + property.GetValue( renderer, null ) );
}
}
What do you mean it’s creating new instances? Are you saying it’s creating a copy of the material objects rather than referencing them? It shouldn’t be, it should be the exact same behaviour as though you directly accessed it. How are you determining that it’s creating new instances?
'Cause in the inspector I can see “MyMaterial (Instance)” for example, I’m thinking its a problem with the Binding Flags.
In fact, I belive its creating instances of each property for example a Light, a Rigidbody, a GuiTexture etc. Sure this is imposible, but if check property is null I always get false.
if( (property.GetValue( components[j], null ) is Rigidbody ) ){
Debug.Log("Is Rigibody, null: " + ( property.GetValue( components[j], null ) == null ) );
}
I don’t think the BindingFlags will do anything (just help to filter which properties are found, I think)
Try doing this:
var rigidBodyReference = components[j].rigidbody;
Debug.Log("Is RigidBody Reference Null: " + (rigidBodyReference == null));
var rigidBodyReflection = property.GetValue(components[j], null);
Debug.Log("Is RigidBody Reflection Null: " + (rigidBodyReflection == null));
Both cases returns true wich was what I was expecting, and means its working good.
Anyway, still creating instances of components properties such as meshes, physics materials, etc. It does by only getting the property value
.
Do the same test for the other properties.
I’m really finding it difficult to believe that it’s doing this, all PropertyInfo.GetValue does is invoke the getter as though you directly did in your code. The only possibility I can think of is that the getters are doing that on their own regardless of it being invoked via code or by reflection.
I did before posting the reply.
I find hard too, you can test it yourself, duplicate a cube, ask for it properties and then change the material color, you will see that now are different instances.
Isn’t important now, 'cause the scripts are working fine. But I prefer this doesn’t happen every time a user saves its game.
No, I mean, do a similar test like with the rigid body:
var materialReference = components[j].material;
Debug.Log("Is material Reference Null: " + (materialReference == null));
var materialReflection = property.GetValue(components[j], null);
Debug.Log("Is material Reflection Null: " + (materialReflection == null));
Did some similar tests, still getting new instances of some values.
But it’s producing new instances even for the direct reference, not the reflection, correct?
Can you do me a favour and post a list of the properties that are being instantiated? I’m thinking that this possibly might be by design.
I’m doing something very similar to EZ Game Saver, so depends on what user has choosen.
I just figured it out reading the renderer references, it depends on how the property work. For example, render.materials, not only returns the materials but creates new instances and starts using it. The same with the collider material.
Well, “materials” definitely would. It returns an array of materials. If there are none, it would still return an array but it would be empty.
I think, but I am not sure, that materials tend to be set to a “defaultmaterial” if none is explicitly assigned.
I think the defaults materials are only used with the primitive game objects (Cube, Cylinder, etc), if you create a gameobject by scripting it cames all empty.
I feel really happy now, can’t believe I didn’t figured it out yesterday. At the end will depend of the gameplay and whats necesary to be save.
Cheeeerrrsss 