Add SerializeField private field support

This commit is contained in:
2026-04-03 16:19:56 +08:00
parent d4d825e1b1
commit 2b19b4bece
10 changed files with 333 additions and 17 deletions

View File

@@ -173,6 +173,7 @@ private:
bool ApplyContextFields(const ScriptRuntimeContext& context, MonoObject* instance);
bool ApplyStoredFields(const ScriptRuntimeContext& context, const ClassMetadata& metadata, MonoObject* instance);
MonoObject* CreateManagedGameObject(uint64_t gameObjectUUID);
bool HasSerializeFieldAttribute(MonoClassField* field) const;
bool TryExtractGameObjectReference(MonoObject* managedObject, GameObjectReference& outReference) const;
bool TrySetFieldValue(MonoObject* instance, const FieldMetadata& fieldMetadata, const ScriptFieldValue& value);
bool TryReadFieldValue(MonoObject* instance, const FieldMetadata& fieldMetadata, ScriptFieldValue& outValue) const;
@@ -198,6 +199,7 @@ private:
MonoClass* m_behaviourClass = nullptr;
MonoClass* m_gameObjectClass = nullptr;
MonoClass* m_monoBehaviourClass = nullptr;
MonoClass* m_serializeFieldAttributeClass = nullptr;
MonoMethod* m_gameObjectConstructor = nullptr;
MonoClassField* m_managedGameObjectUUIDField = nullptr;
MonoClassField* m_gameObjectUUIDField = nullptr;

View File

@@ -1665,6 +1665,7 @@ void MonoScriptRuntime::Shutdown() {
m_behaviourClass = nullptr;
m_gameObjectClass = nullptr;
m_monoBehaviourClass = nullptr;
m_serializeFieldAttributeClass = nullptr;
m_gameObjectConstructor = nullptr;
m_managedGameObjectUUIDField = nullptr;
m_gameObjectUUIDField = nullptr;
@@ -2219,6 +2220,15 @@ bool MonoScriptRuntime::DiscoverScriptClasses() {
return false;
}
m_serializeFieldAttributeClass = mono_class_from_name(
m_coreImage,
m_settings.baseNamespace.c_str(),
"SerializeField");
if (!m_serializeFieldAttributeClass) {
SetError("Failed to locate the managed SerializeField attribute type.");
return false;
}
m_gameObjectUUIDField = mono_class_get_field_from_name(m_componentClass, "m_gameObjectUUID");
m_scriptComponentUUIDField = mono_class_get_field_from_name(m_behaviourClass, "m_scriptComponentUUID");
if (!m_gameObjectUUIDField || !m_scriptComponentUUIDField) {
@@ -2264,7 +2274,14 @@ void MonoScriptRuntime::DiscoverScriptClassesInImage(const std::string& assembly
void* fieldIterator = nullptr;
while (MonoClassField* field = mono_class_get_fields(monoClass, &fieldIterator)) {
const uint32_t fieldFlags = mono_field_get_flags(field);
if ((fieldFlags & MONO_FIELD_ATTR_PUBLIC) == 0 || (fieldFlags & MONO_FIELD_ATTR_STATIC) != 0) {
if ((fieldFlags & MONO_FIELD_ATTR_STATIC) != 0
|| (fieldFlags & MONO_FIELD_ATTR_LITERAL) != 0
|| (fieldFlags & MONO_FIELD_ATTR_INIT_ONLY) != 0) {
continue;
}
const bool isPublicField = (fieldFlags & MONO_FIELD_ATTR_PUBLIC) != 0;
if (!isPublicField && !HasSerializeFieldAttribute(field)) {
continue;
}
@@ -2299,6 +2316,26 @@ bool MonoScriptRuntime::IsMonoBehaviourSubclass(MonoClass* monoClass) const {
return false;
}
bool MonoScriptRuntime::HasSerializeFieldAttribute(MonoClassField* field) const {
if (!field || !m_serializeFieldAttributeClass) {
return false;
}
MonoClass* ownerClass = mono_field_get_parent(field);
if (!ownerClass) {
return false;
}
MonoCustomAttrInfo* attributes = mono_custom_attrs_from_field(ownerClass, field);
if (!attributes) {
return false;
}
const mono_bool hasAttribute = mono_custom_attrs_has_attr(attributes, m_serializeFieldAttributeClass);
mono_custom_attrs_free(attributes);
return hasAttribute != 0;
}
MonoScriptRuntime::FieldMetadata MonoScriptRuntime::BuildFieldMetadata(MonoClassField* field) const {
FieldMetadata metadata;
metadata.field = field;