Как воткнуться в процесс десериализации Unity-ресурсов?

Программирование на Юнити.

Как воткнуться в процесс десериализации Unity-ресурсов?

Сообщение Albeoris 22 дек 2016, 02:57

Доброго времени суток.

У ничего не подозревающей игры один из типов, наследников MonoBehaviour переезжает в другую сборку. В оригинальной остаётся ссылка, с пометкой ExportedType. Этот грязный хак используется для её модификации.

Начинается процесс загрузки скриптов. Дело доходит до нашего типа.
Помимо родительских полей он содержит в себе:
public string GroupName = string.Empty;
public HelpDetail2 Help2;

Первое поле успешно десериализуется. Всё, на этом процесс обрывается.
В логах видим:
A script behaviour (probably ButtonGroupState?) has a different serialization layout when loading. (Read 64 bytes but expected 68 bytes)
Did you #ifdef UNITY_EDITOR a section of your serialized properties in any of your scripts?

Тип HelpTetail2 помечен аттрибутом [Serializable], на который движок плюет с высокой колокольни. Object is null.
Стоит отнаследовать его от UnityEngine.Object или MonoBehaviour - случается чудо, объект десериализуется! Правда, не слишком успешно, что логично, но тем не менее.

Вопрос - как этот демонский движок определяет - какие объекты, помеченные Serializable, ему нужно десериализовать, а какие нет?
Схожий вопрос касается методов Awake, OnLoad и т.д. - движок не будет вызывать те методы, которые отсутствовали в сборке в момент компиляции.
Где хранится эта информация? Кого нужно отревёрсить и распотрошить? [curved_hands]

---Update:
Пока удалось найти только интефейс ISerializationCallbackReceiver. Он предоставляет два метода - BeforeSerialization и AfterDeserialization. Не вижу явных вызовов. Возможно, дёргается из нативного кода? К сожалению, не позволяет переопределить механизмы десериализации и не предоставляет доступа потоку данных. :( Сам вызов летит из нативного кода:
at System.Environment.get_StackTrace()
at ButtonGroupState.OnAfterDeserialize()
---Конец стека---

---Update 2:
Нашёл такой код:
Синтаксис:
Используется csharp
  internal static class ClassLibraryInitializer
  {
    private static void Init()
    {
      UnityLogWriter.Init();
      if (!Application.platform.ToString().Contains("WebPlayer"))
        return;
      BinaryFormatter.set_DefaultSurrogateSelector((ISurrogateSelector) new UnitySurrogateSelector());
    }
  }

Смущает то, что справедливо только для WebPlayer'а.
Эх, не хотелось лезть в UnityEngine/mscorlib. :(

---Update 3:
Нет, увы, если бы всё было так просто. Подмена форматтера ни к чему не привела - он просто не вызывается.
Albeoris
UNIт
 
Сообщения: 146
Зарегистрирован: 19 окт 2013, 13:12

Re: Как воткнуться в процесс десериализации Unity-ресурсов?

Сообщение Albeoris 22 дек 2016, 17:16

Нашёл статью замечательного человека, который долго пилил собственные механизмы сериализации для Unity объектов, но потом забросил это гиблое дело.
http://answers.unity3d.com/questions/72 ... -cant.html

У него много толковых статей по этой теме, включая DLL Injection для перехвата вызовов:
http://answers.unity3d.com/users/146979/vexe.html

Буду разбираться.
Albeoris
UNIт
 
Сообщения: 146
Зарегистрирован: 19 окт 2013, 13:12


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 13