UE-项目与文件结构

Posted 万物皆可休

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE-项目与文件结构相关的知识,希望对你有一定的参考价值。

UE4游戏项目工程目录的结构含义

Config文件夹,包含并控制着项目相关的设置(项目设置,键盘输入之类的配置文件),用于设置用来控制引擎行为的值。项目Config文件中设置的值会覆盖 Engine\\Config 目录中设置的值。

Content文件夹,包含游戏内容的文件夹,它包含项目的所有内容(资源包和贴图、模型、材质、蓝图等)。

DerivedDataCache文件夹,DDC 派生数据缓存, 项目编译完的保存的内容,是一种可加速项目启动的缓存。

Intermediate文件夹,用于中间步骤的临时文件和文件夹。有Build的中间文件,.obj和预编译头等。

Saved文件夹,Saved文件夹与Intermediate文件夹很类似,但是保存了一些更为重要的文件。存储自动保存文件,其他配置文件,日志文件,引擎崩溃日志,硬件信息,烘培信息数据等。 

Source文件夹,这是项目用于保存C++文件的源文件夹。

.uproject文件,项目启动文件,它是一个文本文件。

.vs文件夹(C++项目,专为Visual Studio存在,如有必要,可以删除它。

Binaries文件夹,Binaries是一个临时文件夹,保存编译好的二进制代码

● Build 包含构建引擎或游戏所需的文件,包括创建特定于平台的构建版所需的文件。

● Plugins- 包含项目中使用的插件。

● .sln-项目编译出的C++代码文件

一、Config文件夹 

Config文件夹十分重要,它包含并控制着项目相关的设置。

二、Content文件夹

Content文件夹就是包含游戏内容的文件夹,它包含项目的所有内容。
你不应该删除这个文件夹,否则会失去所有游戏内容。

Collections文件夹和Developers文件夹,它们都可以通过在内容浏览器中启用,
“显示集合”或“显示开发者内容”来访问,这些文件夹可以用来保存项目开发时的快捷文件或临时文件。

 三、DerivedDataCache文件夹

DDC 派生数据缓存, 项目编译完的保存的内容,是一种可加速项目启动的缓存。

四、  Intermediate文件夹

Intermediate文件夹,这个文件夹可以删除,它只是用来保存你在构建项目和使用引擎时,
用于中间步骤的临时文件和文件夹。

如果你删除了这个文件,项目下次打开会花费更长时间,
因为它必须重建这个文件夹,如果你删除这个文件夹,引擎每次都会重新创建这个文件夹替换掉丢失的对象。

五、Saved文件夹

Saved文件夹与Intermediate文件夹很类似,但是保存了一些更为重要的文件,最好不要删除。
除非我们确信可以删除,这些文件会根据情况被中心创建,但是一旦删除,它们就没法被重新创建。
Logs文件夹,它保存着游戏的运行日志,既有历史日志也有当前日志,对于找出编辑器的崩溃或错误原因非常有用。

Backups文件夹和Auto Saves文件夹如果地图崩溃或者引擎崩溃,你可以在这个文件夹中,恢复丢失文件。
引擎会在崩溃后查找Saved文件夹,并尝试恢复文件和文件夹。

 六、Source文件夹

Source文件夹,这是项目用于保存C++文件的源文件夹。
如果你删除这个文件夹,项目的C++源代就会全部丢失。项目没法被正确编译,

七、.uproject文件


项目启动文件,它是一个文本文件,本质上负责控制引擎与项目的交互方式。
版本、插件、C++模块,支持平台以及其他相关内容。

 八、.vs文件夹


专为Visual Studio存在,如有必要,可以删除它。
它只负责保存Visual Studio中“自动完成”和其他功能产生的临时数据。

九、 Binaries文件夹

Binaries是一个临时文件夹,如果打开它,会发现它保存着编译好的二进制代码。
以及与模块相关的.dll文件,也就是我们的C++源代码。
Binaries文件夹会在编译项目时被创建,如果你需要节省空间,请将它们删除。
下次打开项目时,引擎会重建它们。
如果你打包项目时遇到问题,你可以试着删除二进制文件夹,这样可以把项目还原到初始状态。 

UE4引擎目录结构含义:

Engine 引擎目录,包含构成引擎的所有源代码、内容等。

Samples 样例资源。

Templates 样例工程模块,创建新项目时可用的项目模板集合。

Setup.bat 只需运行一次。拉取引擎的三方依赖安装引擎运行环境 - 执行Engine\\Extras\\Redist\\en-us\\UE4PrereqSetup_x64.exe引擎注册 - 执行UnrealVersionSelector.exe

Setup 和 GenerateProjectFiles还有对应的 .sh 文件,作用与.bat相同,用于在Mac平台下是生成从xcode工程文件。.command是Mac平台下的一种快捷方式,可以支持双击打开,而不在命令行模式执行。

Plugin插件目录

Binaries - 包含可执行文件或编译期间创建的其他文件。
Content - 包含游戏内用到的插件资源目录。
Intermediate - 包含UnrealBuildTool生成的文件,如Visual Studio项目文件。这些文件可以删除并重新构建。
Resources - 插件额外资源目录,如插件图标。
ThirdParty - 插件依赖的三方库目录。
ScriptPlugin.uplugin 插件文件,包含这个文件的目录会被UE4识别为一个插件目录。

插件详解:UE4插件研发 So Easy_井底一蛤蟆的博客-CSDN博客_虚幻插件开发 

模块结构 

每个模块都有一个模块实现文件, Build.cs 用于告诉编译器模块的编译方式,这个文件不是C++文件,而是用C#编写的文件,这是因为我们的构建工具“虚幻构建工具”简称UBT 使用C#编写,UBT在每次编译项目时,解析并搜索项目中的所有目录,寻找"build.cs"文件,并构建所有可用模块的列表,然后它会编译这些“Build.cs”文件,并将它作为编译的一部分执行,

PublicDependencyModuleName:公有依赖项,它们会被重新公开给其他依赖于该模块的模块,

PrivateIncludePaths:字符串集合,必须手动指定它下面有哪些子目录,公有目录会自动检测

编辑模块本身时使用“专有依赖关系”。“公有依赖关系”将重新导出至依赖于该模块的其它模块。

UE4根据真实地图来生成行走道路

上一节我们完成了数据的基础获取,现在我们需要在UE4中新建一个空白插件类,然后把上一节python文件和txt文件放在该插件类里的Content文件夹里面(作用是让UE4只需要读取相对位置就行,便于打包和其他项目使用)。

创建好C++插件工程后,我们需要创建一个函数用于读取txt里面的数据,我们可以看到txt生成的数据是double型,UE4的FVector2D位置坐标结构体是float型,所以我们需要创建一个结构体储存数据里面的double型数据,而且我们在每个拐弯处都分了段,所以创建了一个简单的结构体,用于储存每段结构的数据:

技术图片
struct FVector2D_Double

    double X;
    double Y;

    FVector2D_Double operator-(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X - Other.X, Y - Other.Y);
    

    FVector2D_Double operator+(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X + Other.X, Y + Other.Y);
    

    FVector2D_Double operator/(const FVector2D_Double& Other) const
    
        return FVector2D_Double(X * Other.X, Y * Other.Y);
    

    FVector2D_Double operator*(const float& Other) const
    
        return FVector2D_Double(X * Other, Y * Other);
    

    FVector2D_Double operator/(const float& Other) const
    
        return FVector2D_Double(X / Other, Y / Other);
    

    FVector2D_Double operator/(const FVector2D& Other) const
    
        return FVector2D_Double(X / Other.X, Y / Other.Y);
    

    FVector2D_Double operator*(const FVector2D& Other) const
    
        return FVector2D_Double(X * Other.X, Y * Other.Y);
    

    FVector2D_Double()
        :X(0.f), Y(0.f)
    

    FVector2D_Double(double X,double Y)
        :X(X),Y(Y)
    

    double Size() const
    
        return sqrt(X * X + Y * Y);
    
;
.h
技术图片
struct LevelArray

    unsigned int ID = 0;
    TArray<FVector2D_Double> Array;
;
.h

其中我重载了一些运算符,便于后面需要的计算,现在我们已经有了储存数据的结构,现在就需要读取txt里面的数据,我使用的是C++原生库里面的读取方法:

技术图片
#include <iostream>
#include <fstream>
#include <cassert>
#include <string>
.h
技术图片
TArray<LevelArray> LevelBaiData;
TArray<int> BaiduDataTimeAndDistance;
std::string file = TCHAR_TO_UTF8(*FPaths::ProjectPluginsDir()) + std::string("XXXXPlugins/Content/walking.txt");
    
    std::ifstream infile;
    infile.open(file.data());   //将文件流对象与文件连接起来 

    unsigned int AID = 0;

    if (infile.is_open())
    

        std::string s;
        while (getline(infile, s))
        
            std::string s1, s2, s3;
            
            std::size_t pos = s.find(",");
            if (s._Equal("------"))
            
                LevelArray A;
                AID += 1;
                A.ID = AID;
                LevelBaiData.Add(A);
            
            if (pos != std::string::npos)
            
                s1 = s.substr(0, pos);
                s2 = s.substr(pos + 1, s.size());

                FVector2D_Double v2lf = FVector2D_Double(atof(s1.c_str()), atof(s2.c_str()));
                
                FVector2D_Double A = IBToXY(v2lf); // 把经纬度转化为平面坐标
                
                LevelBaiData[LevelBaiData.Num() - 1].Array.Add(A);
            
            std::size_t pos_1 = s.find(":");
            if (pos_1 != std::string::npos)
            
                s3 = s.substr(pos_1 + 1, s.size());
                BaiduDataTimeAndDistance.Add(atoi(s3.c_str()));
            
        
        infile.close();
    
.cpp

这样我们就可以把数据存储在结构体LevelBaiDataBaiduDataTimeAndDistance里面。

我还创建了一个函数,用于把经纬度坐标转化为平面坐标,我使用的是米勒投影转换:

FVector2D_Double MyClass::IBToXY(FVector2D_Double IB)


    double L = 6378000 * PI * 2;//地球周长
    double W = L;// 平面展开后,x轴等于周长 
    double H = L / 2;// y轴约等于周长一半  
    double Mill = 2.3;// 米勒投影中的一个常数,范围大约在正负2.3之间  
    double x = IB.X * PI / 180;// 将经度从度数转换为弧度  
    double y = IB.Y * PI / 180;// 将纬度从度数转换为弧度  
    
    y = 1.25 * log(tan(0.25 * PI + 0.4 * y));// 米勒投影的转换 

    // 弧度转为实际距离  
    x = (W / 2) + (W / (2 * PI)) * x;
    y = (H / 2) - (H / (2 * Mill)) * y;

    return FVector2D_Double(x,y);

现在我们已经取得地球上的坐标数据,然后把该数据转化为UE4里的的float型数据,我们只需要知道UE4中起点位置,和缩放比例就可以实现该效果,起点位置好找,直接可以用Actor世界位置,可是缩放比例就有点难,我们可以知道UE4终点终点位置求得,也可以知道UE4地图比例就得,我使用的是获取另一个点的终点位置求得:

技术图片
FVector Delate = EndActor - StartActor;
BaiduDataXY = UpDataLevelArrayData(LevelBaiData, Number, IsIgnoreSamllLen, Number <= 0);

    FVector2D_Double StartEndVector2D = (BaiduDataXY[BaiduDataXY.Num() - 1] - BaiduDataXY[0]); //米勒投影坐标向量

    double Scale = StartEndVector2D.Size() / FVector2D(Delate.X, Delate.Y).Size();
    
    for (auto &Item : BaiduDataXY)
    
        FVector2D_Double p = (Item - BaiduDataXY[0]) / Scale;
        /*
        p.X = DistanceLngLat(BaiduData[0].X, Item.X, BaiduData[0].Y, BaiduData[0].Y) / Scale;
        p.Y = DistanceLngLat(BaiduData[0].X, BaiduData[0].X, BaiduData[0].Y, Item.Y) / Scale;
        */
        UE4Data.Add(FVector2D(p.X, p.Y));
        
    
.cpp

UpDataLevelArrayData函数用于数据均匀分段,不会出现过多或者过少的拐点,这个算法不是当堂重点,当然你们需要参考可以在后面我贴出的源码里查看。

数据我们可以读取并且可在UE4中使用,但是如果我们需要在UE4中输入经纬度,然后C++调用python函数,获取的函数在UE4中显示出来,那就在下一节我讲解一下。

项目插件源码:https://github.com/a948022284/UE4RealRoadPlanning

以上是关于UE-项目与文件结构的主要内容,如果未能解决你的问题,请参考以下文章

UE-项目与文件结构

UE4学习笔记:在项目和插件里创建新C++模块的方法

深入浅出UE4网络

UE4的学习路线,自己个人能够开发一个完整的游戏的学习路线。零基础。

UE4 C++ UE4 C++ 入门(无参考项目)——技术宅阿棍儿 学习笔记 更新中~

UE4学习-初学者内容包-编辑界面讲解