您好,登錄后才能下訂單哦!
這篇文章主要介紹“Unity使用C++作為游戲邏輯腳本分析”,在日常操作中,相信很多人在Unity使用C++作為游戲邏輯腳本分析問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Unity使用C++作為游戲邏輯腳本分析”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
一、C#和C++的通信
c#和c++的交互,也是非常類似的,c#可以直接的通過P/Invoke的方式來調(diào)用c++的函數(shù),而C++調(diào)用C#的函數(shù),C++的函數(shù)是被封裝成DLL來放在Unity的工程文件中的Plugins中,則需要基于.NET來操作,利用Marshal.GetFunctionPointerForDelegate來獲取函數(shù)的指針,然后傳遞到c++中進(jìn)行操作。
二、編輯器下實(shí)現(xiàn)實(shí)時(shí)的編譯和腳本更新
在Unity中,我們可以在打開的Unity中,直接編譯c#的文件,這樣不需要每次都關(guān)閉工程再打開來執(zhí)行編譯,而C++由于通過DLL來調(diào)用,每次更新的C++都需要關(guān)閉工程,然后更新DLL,然后打開工程,這樣的操作,對(duì)于編輯器下的開發(fā)是極其耗費(fèi)的。
對(duì)于上面提到的反復(fù)開關(guān)工程執(zhí)行DLL的更新,可以利用[DllImport]的屬性來實(shí)現(xiàn)在編輯器下的更新。
該屬性是基于OS的,所以不會(huì)存在跨平臺(tái)的問題。
三、示例代碼展示
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下的導(dǎo)入 [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<T>(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<T>(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<InitDelegate>(libraryHandle, "Init"); MonoBehaviourUpdate = GetDelegate<MonoBehaviourUpdateDelegate>( 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 #endif extern "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) { //獲取函數(shù)handle,然后操作 int goHandle = GameObjectNew(); int transformHandle = GameObejctGetTransform(goHandle); float comp = 10.0f * (float)numCreated; Vector3 position = {comp, comp, comp}; TransformSetPosition(transformHandle, position); numCreated++; } } }
到此,關(guān)于“Unity使用C++作為游戲邏輯腳本分析”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。