溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Unity使用C++作為游戲邏輯腳本分析

發(fā)布時(shí)間:2021-11-24 11:36:24 來源:億速云 閱讀:149 作者:iii 欄目:大數(shù)據(jù)

這篇文章主要介紹“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í)用的文章!

向AI問一下細(xì)節(jié)

免責(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)容。

AI