今天,在单步调试程序时,对照引擎,突然有了些想法。以前没注意到,是因为以前都是用引擎的dll,并没有这么调试过。
1,每个引擎都是有自己的初始化和帧循环,使用引擎的过程,就是相当于把引擎当做工厂,自己的数据相当于原材料,进行加工的过程。不同的引擎有不同的加工流水线。
2,加工过程,要遵循引擎的流水线流程,而不是自己创造一个,如果只用引擎的类初始化,而没有用引擎的帧循环,很可能没有掌握住精髓。前几年,有个项目,用OSG,架构师自己写了个帧循环过程,结果,由于是单线程,最后卡的一笔,项目失败。
3,如何使用引擎的帧循环过程?一个方法是用该类,或者继承抽象类,用父类调用子类的方式,把自己的东西嵌套进去,狸猫换太子,即父类转小圈,子类替代父类转大圈。而不是只看这个引擎一个循环多么热闹,却无从下手。
使用UE4时,
1,在PreInit()
(1)首先动态加载自定义工程的dll,(这里隐藏了,其实应该到项目的dll)
(2),调用动态链接库中派生类的构造函数,这里解释下,其实就是UCLASS()派生类,既然要用父类调用子类的方式,起码要知道有哪些子类
比如
UClass()
class myActor : public AACtor
{
GENERATED_BODY()
public:
myActor ();
}
这里就是要调用
myActor::myActor()了。
单步调试:(这里应该跟踪到myActor::myActor(),隐藏了)
这里的ClassDefaultObject就是派生类,如myActor,ParentDefaultObject即为父类AActor,只是前面加了个前缀Default_。
接下来,就是工程动态链接库中的一系列UCLASS()派生类。
这时候,可以趁机把一系列的游戏中用到的类都派生出来,比如,AActor,APawn,AGameModeBase,UGameViewportClient,
在构造函数中可以加点私货,自己的自定义类。在此时调用构造函数中干点自己的事。
2,在FEngineLoop::init()阶段,进行初始化了
这里上面也隐藏了,注意,这个this是什么,这个this是FEngineLoop,也就是说,在这里,可以不失时机地派生一个类
UCLASS()
class myGameEngine : public UGameEngine
{
GENERATED_BODY()
public:
virtual void Init(class IEngineLoop* InEngineLoop) override;
}
去实现自定义的myGameEngine::Init(class IEngineLoop* InEngineLoop)
可以只写UGameEngine::Init(),也可以加一些自定义的东西,UGameEngine类其实比较全了。成员变量有
/** Maximium delta time the engine uses to populate FApp::DeltaTime. If 0, unbound. */
UPROPERTY(config)
float MaxDeltaTime;
/** Maximium time (in seconds) between the flushes of the logs on the server (best effort). If 0, this will happen every tick. */
UPROPERTY(config)
float ServerFlushLogInterval;
UPROPERTY(transient)
UGameInstance* GameInstance;
/** The game viewport window */
TWeakPtr<class SWindow> GameViewportWindow;
/** The primary scene viewport */
TSharedPtr<class FSceneViewport> SceneViewport;
/** The game viewport widget */
TSharedPtr<class SViewport> GameViewportWidget;
/** Handle to a movie capture implementation to create on startup */
FMovieSceneCaptureHandle StartupMovieCaptureHandle;
/** Last time the logs have been flushed. */
double LastTimeLogsFlushed;
以及相关的方法,由于太多了,所以不列出了。
主要进行一些初始化
先调基类(UGameEngine派生与UEngine)
游戏设置
游戏实例
编辑器模式下视频捕捉
如果是客户端,则开个客户端视口
看到这里,想到什么?是的,派生,再派生出一个自定义的客户端视口类
UCLASS()
class myGameViewportClient : public UGameViewportClient
{
GENERATED_BODY()
。。。
}
这样,客户端视口也为我所用了,而不是干瞪眼看着UE4自己玩了。
将视口放在视口界面里,创建视口所在的窗口。
3,现在初始化完毕了,该启动引擎了。
依照惯例,也要把gameInstance派生出来,为我所用
UCLASS()
class myGameInstance : public UGameInstance
{
GENERATED_BODY()
.......
}
在这里,照样 UGameInstance::StartGameInstance()不是纯虚函数,所以还要除了自定义的外,还要用一用。这里的初始化主要就是业务内容的初始化了。也就是开始游戏了。
(1)加载游戏地图,得到gameMode
可以回忆下,fps模板中,生成默认pawn,初始化弹簧手臂和摄像机一类的。
很明显,这里要派生个pawn类,到这里,就和ue4编辑器的c++模板连贯起来了。
(2)