Unity游戏状态脚本控制思考(二)

来源:互联网 发布:游乐网软件下载 编辑:程序博客网 时间:2024/05/29 11:18

最近忙着项目上线,一摊子事,好久没更了,于是乎补上一更。
上一篇聊到Unity的脚本控制,这一篇就细说下Unity的实现原理. 

核心点

C#脚本+Mono+C++
 
UnityEngine里的核心类似这么写的:

public class Component    {        private IntPtr native_handle=IntPtr.Zero;        [MethodImpl(MethodImplOptions.InternalCall)]        public extern static Component[] GetComponents();        [MethodImpl(MethodImplOptions.InternalCall)]        public extern static int get_id_Internal(IntPtr native_handle);        [MethodImpl(MethodImplOptions.InternalCall)]        public extern static int get_tag_Internal(IntPtr native_handle);        public int ID {             get {                return get_id_Internal(native_handle);                    }        }        public int Tag        {            get            {                return get_tag_Internal(native_handle);            }        }    }

关键的部分我们都是反编译看不到的,看不到的部分都是通过底层C++去实现的,然后通过Mono进行交互(托管代码与非托管代码之间的交互).

对应C++代码是这样的:
struct Component
{
int id;
int tag;
};

Component* Components;uint32_t num_Components;MonoClassField* native_handle_field;MonoDomain* domain;MonoClass* Component_class;//获取属性int ManagedLibrary_Component_get_id_Internal(const Component* component){    return component->id;} //获取tagint ManagedLibrary_Component_get_tag_Internal(const Component* component){    return component->tag;}//获取组件MonoArray* ManagedLibrary_Component_GetComponents(){    MonoArray* array = mono_array_new(domain, Component_class, num_Components);    for(uint32_t i = 0; i < num_Components; ++i)    {        MonoObject* obj = mono_object_new(domain, Component_class);        mono_runtime_object_init(obj);        void* native_handle_value = &Components[i];        mono_field_set_value(obj, native_handle_field, &native_handle_value);        mono_array_set(array, MonoObject*, i, obj);    }    return array;}int main(int argc, char* argv[]){//------------------------------------------------------------------------------------------------    //例子3:模仿Unity的实现方式    //mono运行时的配置      mono_set_dirs("C:\\Program Files\\Mono\\lib",        "C:\\Program Files\\Mono\\etc");      mono_config_parse(NULL);      const char* managed_binary_path = "E:\\test\\ManagedLibrary.dll";      //获取应用域     domain = mono_jit_init(managed_binary_path);     //加载程序集     MonoAssembly* assembly = mono_domain_assembly_open(domain, managed_binary_path);     MonoImage* image = mono_assembly_get_image(assembly);     //通过Mono的mono_add_internal_call方法将C#中的接口和C/C++中的具体实现关联起来     mono_add_internal_call("ManagedLibrary.Component::get_id_Internal",reinterpret_cast<void*>(ManagedLibrary_Component_get_id_Internal));     mono_add_internal_call("ManagedLibrary.Component::get_tag_Internal",reinterpret_cast<void*>(ManagedLibrary_Component_get_tag_Internal));     mono_add_internal_call("ManagedLibrary.Component::GetComponents",reinterpret_cast<void*>(ManagedLibrary_Component_GetComponents));     //Component.cs     Component_class =mono_class_from_name(image,"ManagedLibrary","Component");     native_handle_field =mono_class_get_field_from_name(Component_class,"native_handle");     num_Components =5;     Components = new Component[5];    for(uint32_t i = 0; i < num_Components; ++i)    {        Components[i].id = i;        Components[i].tag = i * 5;    }    // Main.cs     MonoClass* main_class = mono_class_from_name(image, "ManagedLibrary", "Main");     const bool include_namespace = true;    MonoMethodDesc* managed_method_desc = mono_method_desc_new("ManagedLibrary.Main:TestComponent()", include_namespace);    MonoMethod* managed_method = mono_method_desc_search_in_class(managed_method_desc, main_class);    mono_method_desc_free(managed_method_desc);    //执行    mono_runtime_invoke(managed_method, NULL, NULL, NULL);    //释放应用域    mono_jit_cleanup(domain);    //释放组件    delete[] Components;    return 0;//--------------------------------------------------------------------------}

着重理解下核心点“C#脚本+Mono+C++”,明白了这个就简单了。

附件

工程源代码

原创粉丝点击