- Home /
Unity custom editor when i modify byteArray field with reflection whitout SerializedProperty, it can not save.
I need some feature in my custom class, like intValue ,stringValue, floatValue and so on. But i don’t define many field for save only one data everytime. So i want to use byte[]. I know it not safe,but i need. I try to test below. This is my Class:
using UnityEngine;
using System.Collections;
using System;
public class Test : MonoBehaviour {
[SerializeField]
private CustomData _data;
}
[System.Serializable]
public class CustomData
{
public byte[] bytes;
public static byte[] GetByte(int i)
{
return BitConverter.GetBytes(i);
}
public static int ToInt(byte[] bytes)
{
return BitConverter.ToInt32(bytes,0);
}
//public ToString()
//public ToFloat()
//public ToSomeCustomClass
}
And this is it editor class:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(Test))]
public class TestEditor : Editor {
private SerializedProperty _data;
private SerializedProperty _bytes;
private FieldInfo _entryField;
private void OnEnable()
{
_data = serializedObject.FindProperty("_data");
_bytes = _data.FindPropertyRelative("bytes");
_entryField = typeof(Test).GetField("_data", BindingFlags.NonPublic | BindingFlags.Instance);
}
public override void OnInspectorGUI()
{
serializedObject.Update();
//I use one size of array to save one byte
//---- This is so slow, because it assgin with iteration,if not int but custom data(some big data like more than 200 size of byte array)----
//int intSize = sizeof(int);
//if (_bytes.arraySize != intSize)
// _bytes.arraySize = intSize;
//byte[] intSrcBytes = new byte[intSize];
//for (int i = 0; i < intSize; ++i)
// intSrcBytes[i] = (byte)_bytes.GetArrayElementAtIndex(i).intValue;
//int result= EditorGUILayout.IntField(CustomData.ToInt(intSrcBytes));
//byte[] intEndBytes = CustomData.GetByte(result);
//for (int i = 0; i < intSize; ++i)
// _bytes.GetArrayElementAtIndex(i).intValue = intEndBytes[i];
//------------------------------------------------------------------
//---- This is fast.I get the bytes with reflection. ----
CustomData data = _entryField.GetValue(target) as CustomData;
byte[] intFastSrcBytes = data.bytes;
int resultOfFastSrc = EditorGUILayout.IntField(CustomData.ToInt(intFastSrcBytes));
data.bytes= CustomData.GetByte(resultOfFastSrc);
_entryField.SetValue(target, data);
//--------------------------------------------------------
serializedObject.ApplyModifiedProperties();
}
}
At First, i use SerializedProperty to byte[] and byte[] to SerializedProperty at part of annotation.I test it with type of int. Result is fine.But when i use this way to test a custom data of more than 200 size. It so slow.Because it iteration all element from SerializedProperty to byte[] and iteration all element from byte[] to SerializedProperty. Result in slow at Editor on Windows.
And Second. I want to get byte[] directly with reflection. It very good when i get byte[]. But the problem is when i SetValue. I see when i change value with keyboard,and GUI of IntField content in Inspector is changed too. But Editor not display i can go to save this change( not appear "*" any where ). In other word, Editor not think it have been modified. So now i close and restart Unity. My changed content not save. Test show me another, if i do any can save opertion,such as i click the SetActive check box of gameobject at Inspector, it appear "*" ,and i save,then i close an restart Unity,previours changed content will be save.
I need the way of Second.the Problem is when i setValue,but not appear any save tip,i can not to save.I how to solve it,or have other easy solution ?
Answer by Bunny83 · Sep 19, 2017 at 02:57 AM
First of all you shouldn't mix using serializedObject and using target directly. Especially calling "ApplyModifiedProperties" after you did manual direct changes doesn't make sense.
To tell the serialization system to serialize the object you want to use Undo.RecordObject right before you edit it. Note that in your code you actually don't need to use SetValue as the monobehaviour still references the same object. You just change / replace the byte array in that class.
If RecordObject doesn't work, you can try calling "EditorUtility.SetDirty" after the changes. However SetDirty usually doesn't work for scene objects anymore. You can also try using SceneManagement.EditorSceneManager.MarkSceneDirty() and pass in the current loaded scene.
Your answer
Follow this Question
Related Questions
Unity Editor SerializedProperty how to assign to array with larger data directly. 1 Answer
Using UniFileBrowser and LoginPro to upload file = zero bytes uploaded? 0 Answers
Losing serialized data after play button pressed. 0 Answers
Aspect ratio changing on play button hit 0 Answers
How to Install Unity different version 0 Answers