千家信息网

Unity使用C++作为游戏逻辑脚本分析

发表于:2024-10-02 作者:千家信息网编辑
千家信息网最后更新 2024年10月02日,这篇文章主要介绍"Unity使用C++作为游戏逻辑脚本分析",在日常操作中,相信很多人在Unity使用C++作为游戏逻辑脚本分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家
千家信息网最后更新 2024年10月02日Unity使用C++作为游戏逻辑脚本分析

这篇文章主要介绍"Unity使用C++作为游戏逻辑脚本分析",在日常操作中,相信很多人在Unity使用C++作为游戏逻辑脚本分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Unity使用C++作为游戏逻辑脚本分析"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、C#和C++的通信

c#和c++的交互,也是非常类似的,c#可以直接的通过P/Invoke的方式来调用c++的函数,而C++调用C#的函数,C++的函数是被封装成DLL来放在Unity的工程文件中的Plugins中,则需要基于.NET来操作,利用Marshal.GetFunctionPointerForDelegate来获取函数的指针,然后传递到c++中进行操作。

二、编辑器下实现实时的编译和脚本更新

在Unity中,我们可以在打开的Unity中,直接编译c#的文件,这样不需要每次都关闭工程再打开来执行编译,而C++由于通过DLL来调用,每次更新的C++都需要关闭工程,然后更新DLL,然后打开工程,这样的操作,对于编辑器下的开发是极其耗费的。

对于上面提到的反复开关工程执行DLL的更新,可以利用[DllImport]的属性来实现在编辑器下的更新。

该属性是基于OS的,所以不会存在跨平台的问题。

三、示例代码展示

show the code

c# code part:

using System;using System.IO;using System.Runtime.InteropServices;using UnityEngine;class TestScript:MonoBehaviour{#if UNITY_EDITOR    // pointer handle to the C++ DLL    public IntPtr libarayHandle;    public delegate void InitDelegate(IntPtr gameObjectNew,    IntPtr gameObjectGetTransform, IntPtr transformSetPosition);#endif}#if UNITY_EDITOR_OSX || UNITY_EDITOR_LINUX    //OSX 和Linux下的导入    [DLLImport("__Internal")]    public static extern IntPtr dlopen(string path, int flag);    [DllImport("__Internal")]    public static extern IntPtr dlsym(IntPtr handle, string symbolName);    [DllImport("__Internal")]    public static extern int dlclose(IntPtr handle);    public static IntPtr OpenLibrary(string path)    {        IntPtr handle = dlopen(path, 0);        if(handle == IntPtr.Zero)        {           throw new Exception("Couldn't open native library: "+ path);        }        return handle;    }        public static void CloseLibrary(IntPtr libraryHandle)    {         dlclose(libraryHandle);    }        public static T GetDelegate(IntPtr libraryHandle, string functionName)    where T: class    {         IntPtr symbol = dlsym(libraryHandle, functionName);         if(symbol == IntPtr.Zero)         {            throw new Exception("Couldn't get function:" + functionName);          }         return Marshal.GetDelegateForFunctionPointer(symbol, typeof(T)) as T;    }#elif UNITY_EDITOR_WIN    // win 编辑器下    [DllImport("kernel32")]    public static extern IntPtr LoadLibrary(string path);    [DllImport("kernel32")]    public static extern IntPtr GetProcAddress(IntPtr libraryHandle,     string symbolName);         [DllImport("kernel32)]    public static extern bool FreeLibrary(IntPtr libraryHandle);    public static IntPtr OpenLibrary(string path)    {        IntPtr handle = LoadLibrary(path);        if(handle == IntPtr.Zero)        {           throw new Exception("Couldn't open native library: "+ path);        }        return handle;    }        public static void CloseLibrary(IntPtr libraryHandle)    {         FreeLibrary(libraryHandle);    }        public static T GetDelegate(IntPtr libraryHandle, string functionName)     where T: class    {         IntPtr symbol = GetProcAddress(libraryHandle, functionName);         if(symbol == IntPtr.Zero)         {            throw new Exception("Couldn't get function:" + functionName);          }         return Marshal.GetDelegateForFunctionPointer(symbol, typeof(T)) as T;    }#else    //本地加载    [DllImport("NativeScript")]    static extern void Init(IntPtr gameObjectNew,    IntPtr gameObjectGetTransform, IntPtr transformSetPosition);    [DllImport("NativeScript")]    static extern void MonoBehaviourUpdate();#endif    delegate int GameObjectNewDelegate();    delegate int GameObjectGetTransformDelegate(int thisHandle);    delegate void TransformSetPositionDelegate(int thisHandle, Vector3 position);#if UNITY_EDITOR_OSX    const string LIB_PATH = "/NativeScript.bundle/Contents/MacOS/NativeScript";#elif UNITY_EDITOR_LINUX    const string LIB_PATH = "/NativeScript.so";#elif UNITY_EDITOR_WIN    const string LIB_PATH = "/NativeScript.dll";#endif    void Awake()   {#if UNITY_EDITOR     //open the native library     libraryHandle = OpenLibrary(Application.dataPath + LIB_PATH);     InitDelegate Init = GetDelegate(libraryHandle, "Init");     MonoBehaviourUpdate = GetDelegate(     libraryHandle,"MonoBehaviourUpdate");#endif     //init the C++ Library     ObjectStore.Init(1024);     Init(     Marshal.GetFunctionPointerForDelegate(new GameObjectNewDelegate(GameObjectNew)),     Marshal.GetFunctionPointerForDelegate(new GameObjectGetTransformDelegate(GameObjectGetTransform)),     Marshal.GetFunctionPointerForDelegate(new TransformSetPositionDelegate(TransformSetPosition))    );    }       void Update()    {        MonoBehaviourUpdate();    }    void OnApplicationQuit()    {#if UNITY_EDITOR       CloseLibrary(libraryHandle);       libraryHandle = IntPtr.Zero;#endif    }    //c# function for c++ call    static int GameObjectNew()    {        GameObject go = new GameObject();        return ObjectStore.Store(go);    }       static int GameObjectGetTransform(int thisHandle)    {        GameObject go = (GameObject)ObjectStore.Get(thisHandle);        Transform transform = go.transform;         return ObjectStore.Store(transform);    }    static void TransformSetPosition(int handle, Vector3 position)    {         Transform t =(Transform)ObjectStore.Get(handle);         t.position = position;    }}

c++ code part:

#ifdef _WIN32   #define DLLEXPORT __declspec(dllexport)#else   #define DLLEXPORT#endifextern "C"{    //C# VECTOR STRUCT   struct Vector3   {       float x;       float y;       float z;   }   //c# function for c++ to call   int(*GameObjectNew)();   int(*GameObjectGetTransform)(int thisHandle);   void(*TransformSetPosition)(int thisHandle, Vector3 position);   //c++ functions for c# to call   int numCreated;     DLLExport void Init(   int(*gameObjectNew)(),   int(*gameObjectGetTrasform)(int),   void(*transformSetPosition)(int, Vector3)){      GameObjectNew = gameObjectNew;      GameObjectGetTransform = gameObjectGetTransform;      TransformSetPosition = trasformSetPosition;      numCreated = 0;}    //    DLLEXPORT void MonoBehaviourUpdate(int thisHandle)    {        if( numCreated < 10)        {             //获取函数handle,然后操作             int goHandle = GameObjectNew();             int transformHandle = GameObejctGetTransform(goHandle);             float comp = 10.0f * (float)numCreated;             Vector3 position = {comp, comp, comp};             TransformSetPosition(transformHandle, position);             numCreated++;        }    }}

到此,关于"Unity使用C++作为游戏逻辑脚本分析"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0