Hazel game engine (122) C# separates game and core library code

If there are errors in the code, terminology, etc. in the text, please correct me

foreword

  • of this program

    Use the C# game code as a new workspace project and reference the C# core library project

    • 1 C# core library project

    • 1 C# script project

      The script inside calls the function of the C# core library to realize the script function

    Like Unity development, Unity has its own set of dll, we need to write script using UnityEngine;, call the Unity library dll to achieve the corresponding effect

  • How to achieve

    Use premake5 to make quickly

  • implementation details

    • When the C# game code and the core library code are separated, the C++ loading dll changes from one to two

    • Get the Mono class of the C# dll

      It should be distinguished that it is the Mono class that obtains the C# core library assembly

      Or get the Mono class of the C# application set

Project structure related

new workspace new script project

  • new workspace file path

    Under the GameEngine-Editor editor project

    Please add a picture description

  • Premake of the new Sandbox script project

    local UnifyRootDir = "../../../.."
    
    workspace "Sandbox"
    	architecture "x86_64"
    	startproject "Sandbox"
    	configurations{
          
          
    		"Debug",
    		"Release",
    		"Dist"
    	}
    	flags{
          
          
    		"MultiProcessorCompile"
    	}
    
    outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}"
    
    project "Sandbox"
    	kind "SharedLib"
    	language "C#"
    	dotnetframework "4.7.2"
    
    	targetdir ("Binaries")
    	objdir ("Intermediates")
    
    	files{
          
          
    		"Source/**.cs",
    		"Properies/**.cs"
    	}
    	links{
          
          
    		"GameEngine-ScriptCore"
    	}
    	filter "configurations:Debug"
    		optimize "Off"
    		symbols "Default"
    
    	filter "configurations:Release"
    		optimize "On"
    		symbols "Default"
    
    	filter "configurations:Dist"
    		optimize "Full"
    		symbols "Off"
    
    group "Unify"
    	include (UnifyRootDir .. "/GameEngine-ScriptCore")
    group ""
    

New Sandbox script project structure

  • The Sandbox project references the GameEngine-ScriptCore project
  • The Sandbox project contains the Player.cs game logic script code moved from the GameEngine-ScriptCore project

New Sanbox script project generates dll

Please add a picture description

  • build directory set by premake

    targetdir ("Binaries")
    objdir ("Intermediates")
    
  • Since the Sandbox project references the GameEngine-ScriptCore project

    So the generation will not only generate Sandbox.dll but also GameEngine-ScriptCore.dll

project code changes

The changes made to the project code are to load two dlls and reflect different classes according to different dlls

ScriptEngine.h

//ScriptClass(const std::string& classNamespace, const std::string& className);
ScriptClass(const std::string& classNamespace, const std::string& className, bool isCore = false);
static void LoadAppAssembly(const std::filesystem::path& filepath);
//static void LoadAssemblyClasses(MonoAssembly* assembly);
static void LoadAssemblyClasses();

ScriptEngine.cpp

struct ScriptEngineData {
    
    
    MonoAssembly* CoreAssembly = nullptr;
    MonoImage* CoreAssemblyImage = nullptr;
	// 新增,因加载脚本dll,需保存这两个
    MonoAssembly* AppAssembly = nullptr;
    MonoImage* AppAssemblyImage = nullptr;
};
LoadAssembly("Resources/Scripts/Hazel-ScriptCore.dll");
LoadAppAssembly("SandboxProject/Assets/Scripts/Binaries/Sandbox.dll");
s_Data->EntityClass = ScriptClass("Hazel", "Entity", true);

void ScriptEngine::LoadAssemblyClasses()
{
    
    
    // Entity类在核心库
    MonoClass* entityClass = mono_class_from_name(s_Data->CoreAssemblyImage, "Hazel", "Entity");
    // 从游戏逻辑脚本库里加载脚本类
    const char* nameSpace = mono_metadata_string_heap(s_Data->AppAssemblyImage, cols[MONO_TYPEDEF_NAMESPACE]);
    const char* name = mono_metadata_string_heap(s_Data->AppAssemblyImage, cols[MONO_TYPEDEF_NAME]);
	MonoClass* monoClass = mono_class_from_name(s_Data->AppAssemblyImage, nameSpace, name);
}
void ScriptEngine::LoadAppAssembly(const std::filesystem::path& filepath)
{
    
    
    // Move this maybe
    s_Data->AppAssembly = Utils::LoadMonoAssembly(filepath);
    auto assemb = s_Data->AppAssembly;
    s_Data->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly);
    auto assembi = s_Data->AppAssemblyImage;
    // Utils::PrintAssemblyTypes(s_Data->AppAssembly);
}
ScriptClass::ScriptClass(const std::string& classNamespace, const std::string& className, bool isCore)
    : m_ClassNamespace(classNamespace), m_ClassName(className)
{
    
    
    /*
    得到C# dll的Mono类
    应该**区分**是获取C#核心库程序集的 Mono类
    还是获取C#应用程序集的 Mono类
    */
   m_MonoClass = mono_class_from_name(s_Data->CoreAssemblyImage, classNamespace.c_str(), className.c_str());
   m_MonoClass = mono_class_from_name(isCore ? s_Data->CoreAssemblyImage : s_Data->AppAssemblyImage, classNamespace.c_str(), className.c_str());
}

Encountered bugs

  • GameEngine-ScriptCore.dll could not be loaded

    GameEngine-ScriptCore.dll is generated in the GameEngine-Editor\SandboxProject\Assets\Scripts\Binaries folder

    Instead of in the GameEngine-Editor\Resources\Scripts folder

    • reason

      The new Sandbox project contains a reference to the GameEngine-ScriptCore project

      The generated file path written by Sandbox's premake is

      targetdir ("Binaries")
      objdir ("Intermediates")
      

      And the premake of GameEngine-ScriptCore writes

      targetdir ("%{wks.location}/GameEngine-Editor/Resources/Scripts")
      objdir ("%{wks.location}/GameEngine-Editor/Resources/Scripts/Intermediates")
      

      Pay attention to the code %{wks.location}, it gets the location of **.sln**

      • Originally the GameEngineLightWeight workspace contained it

        %{wks.location} = GameEngineLightWeight

        So the generated directory is:

        GameEngineLightWeight\GameEngine-Editor\Resources\Scripts

      • But the new Sandbox also has its own new workspace , and also contains this GameEngine-ScriptCore project

        %{wks.location} = GameEngineLightWeight\GameEngine-Editor\SandboxProject\Assets\Scripts

        So this build directory becomes:

        GameEngineLightWeight\GameEngine-Editor\SandboxProject\Assets\Scripts\GameEngine-Editor\Resources\Scripts

    • The path is generated as follows

      Please add a picture description

      The generated path is different from the path where the code loads the dll, so an error will be reported

    • How to solve

      Modify the build path in the premake of the GameEngine-ScriptCore project

      -- 获取的是.sln所在的位置
      --targetdir ("%{wks.location}/GameEngine-Editor/Resources/Scripts")
      --objdir ("%{wks.location}/GameEngine-Editor/Resources/Scripts/Intermediates")
      targetdir ("../GameEngine-Editor/Resources/Scripts")
      objdir ("../GameEngine-Editor/Resources/Scripts/Intermediates")
      

      %{wks.location} replaced by .../

    • regenerate path

Please add a picture description

Guess you like

Origin blog.csdn.net/qq_34060370/article/details/132266539