UE4/5C++Subsystem的底层源码分析解析学习【二、UE5.0.3,UEngineubsystem,UEditorSubsystem,UDynamicSubsystem】

目录

前提简介

UDynamicSubsystem相关解析:

回到之前我们就看的 FSubsystemCollectionBase::Initialize的源码:

FSubsystemModuleWatcher::InitializeModuleWatcher():

FSubsystemModuleWatcher::OnModulesChanged:

FSubsystemModuleWatcher::AddClassesForModule:

FSubsystemCollectionBase::AddAllInstances对象实例的创建:

FSubsystemModuleWatcher::RemoveClassesForModule

FSubsystemCollectionBase::RemoveAllInstances对象实例的销毁:

小总结:

后期动态加载

引用:


前提简介

详情可以看大钊的文章:

《InsideUE4》GamePlay架构(十一)Subsystems - 知乎 (zhihu.com)

大钊的图),其很好的讲解了Subsystem的不同生命周期:

之前作者介绍了UE4/5C++Subsystem的底层源码分析解析学习【一,UE5.0.3,UGameInstanceSubsystem,UWorldSubsystem,ULocalPlayerSubsystem】_多方通行8的博客-CSDN博客

3个subsystem的源码解析,现在作者将介绍UEngineubsystemUEditorSubsystem,以及他们所继承的UDynamicSubsystem.

UDynamicSubsystem相关解析:

在之前的讲解中,我们知道UEngineSubsystemUEditorSubsystem是继承于UDynamicSubsystem的,那么为什么要这么设计呢?

Dynamic,翻译为动态,就这两个字就足以形容为什么了。

既然是动态的对象,说明我们也会对其动态加载释放

首先我们需要了解一下项目的模块和项目的插件:

大象无形UE4笔记五:模块总结 - 知乎 (zhihu.com)

UE4/5C++模块与插件_多方通行8的博客-CSDN博客

简单来说,一个UProject项目或UPlugin插件可以包含多个Module模块,其中的每个Module都有一个Build.cs,每个模块可以被编译成一个Dll。

这样模块之间可以互相引用。

因此一个模块可能有多个依赖的其他模块,我们假如叫它:myModules。

引擎的机制是加载一个模块的时候会自动的加载myModules,

回到之前我们就看的 FSubsystemCollectionBase::Initialize的源码:

这里和之前讲的并无差别,只是有用过if来判断是不是UDynamicSubsystem的,也一样是添加和初始化Subsystem。

除此之外,还有这个函数:

FSubsystemModuleWatcher::InitializeModuleWatcher():

 代码注释:

void FSubsystemModuleWatcher::InitializeModuleWatcher()
{
	//non-thread-safe use of Global lists, must be from GameThread:
	check(IsInGameThread());

	check(!ModulesChangedHandle.IsValid());

	// Add Loaded Modules
	TArray<UClass*> SubsystemClasses;//获得所有UDynamicSubsystem的子类
	GetDerivedClasses(UDynamicSubsystem::StaticClass(), SubsystemClasses, true);
    
    //遍历
	for (UClass* SubsystemClass : SubsystemClasses)
	{
        //不为抽象类
		if (!SubsystemClass->HasAllClassFlags(CLASS_Abstract))
		{
            ///获得所属于的包
			UPackage* const ClassPackage = SubsystemClass->GetOuterUPackage();/
			if (ClassPackage)
			{
				const FName ModuleName = FPackageName::GetShortFName(ClassPackage->GetFName());
				if (FModuleManager::Get().IsModuleLoaded(ModuleName))
				{
					TArray<TSubclassOf<UDynamicSubsystem>>& ModuleSubsystemClasses = GlobalDynamicSystemModuleMap.FindOrAdd(ModuleName);
                    添加到DynamicSystemModuleMap
					ModuleSubsystemClasses.Add(SubsystemClass);
				}
			}
		}
	}
    
    //注册模块加载和释放事件
	ModulesChangedHandle = FModuleManager::Get().OnModulesChanged().AddStatic(&FSubsystemModuleWatcher::OnModulesChanged);
}

其中最重要的就是遍历了当前进程里的UDynamicSubsystem子类们,并按照模块划分存储进DynamicSystemModuleMap【就是遍历中的最后一行那里的Add】。

这样之后就知道当加载或释放某个模块的时候,应该去创建和销毁哪些Subsystem类型对象。

然后仍然是这个cpp文件里面,我们可以找到这个函数:

FSubsystemModuleWatcher::OnModulesChanged:

从这个代码我们可以看见,里面写的是一个枚举,分别是创建动态模块的类们销毁动态模块的类们

让我们详细查看这两个函数的实现:

FSubsystemModuleWatcher::AddClassesForModule:

我将注释写在代码中:

void FSubsystemModuleWatcher::AddClassesForModule(const FName& InModuleName)
{
	//non-thread-safe use of Global lists, must be from GameThread:
	check(IsInGameThread());

	check(! GlobalDynamicSystemModuleMap.Contains(InModuleName));

	// Find the class package for this module

    //前面的都是检测,无需在意
    //这里是找到该模块所定义的代码包
	const UPackage* const ClassPackage = FindPackage(nullptr, *(FString("/Script/") + InModuleName.ToString()));
	if (!ClassPackage)
	{
		return;
	}

	TArray<TSubclassOf<UDynamicSubsystem>> SubsystemClasses;
	TArray<UObject*> PackageObjects;
    //下面是得到该模块里定义的所有对象
	GetObjectsWithPackage(ClassPackage, PackageObjects, false);
	for (UObject* Object : PackageObjects)
	{
        //这里转换为UClass
		UClass* const CurrentClass = Cast<UClass>(Object);
        //在满足这些条件的情况下,为这个类创建对象实例【AddAllInstances的那个】
		if (CurrentClass && !CurrentClass->HasAllClassFlags(CLASS_Abstract) && CurrentClass->IsChildOf(UDynamicSubsystem::StaticClass()))
		{
			SubsystemClasses.Add(CurrentClass);
			FSubsystemCollectionBase::AddAllInstances(CurrentClass);
		}
	}
    //判断其内部有没有定义Subsystem类,有的可能有【有的话就需要登记一下】,有的可能没有
	if (SubsystemClasses.Num() > 0)
	{
		GlobalDynamicSystemModuleMap.Add(InModuleName, MoveTemp(SubsystemClasses));
	}
}

FSubsystemCollectionBase::AddAllInstances对象实例的创建:

 这里可以看见,里面的实现都是大同小异,添加并初始化对象。

FSubsystemModuleWatcher::RemoveClassesForModule

 我将注释写在代码中:

void FSubsystemModuleWatcher::RemoveClassesForModule(const FName& InModuleName)
{
	//non-thread-safe use of Global lists, must be from GameThread:
	check(IsInGameThread());

	TArray<TSubclassOf<UDynamicSubsystem>>* SubsystemClasses = GlobalDynamicSystemModuleMap.Find(InModuleName);
	if (SubsystemClasses)//这里是判断这里之前有没有被登记过,有则true,没有则false
	{
		for (TSubclassOf<UDynamicSubsystem>& SubsystemClass : *SubsystemClasses)
		{
            //在这里销毁所有的对象
			FSubsystemCollectionBase::RemoveAllInstances(SubsystemClass);
		}
        //移除登记
		GlobalDynamicSystemModuleMap.Remove(InModuleName);
	}
}

FSubsystemCollectionBase::RemoveAllInstances对象实例的销毁:

​这里可以看见,里面的实现都是大同小异,销毁对象。

小总结:

这里的关键其实是SubsystemCollections是个静态变量【从上面我们可以看见,所有类实现的地方是哪个cpp里面】,其引用了整个进程的所有定义的FSubsystemCollection的数量(2个在GEngineGEditor里,其他多个可能动态新增在GameInstanceWorldLocalPlayer里)

总而言之:MyPlugin模块在被加载的时候,会自动的触发OnModulesChanged事件,从而被自动的创建出内部的UMyPluginEngineSubsystemUMyPluginEditorSubsystem

后期动态加载

讲到这里,他并不能真正的展示所谓的动态,所以如果你想要在游戏或编辑器运行一段时间后然后动态的加载某个模块或插件,这个动态就可以体现出来了。

可以看看大钊大佬写的:

引用:

《InsideUE4》GamePlay架构(十一)Subsystems - 知乎 (zhihu.com)

Programming Subsystems in Unreal Engine | Unreal Engine 5.1 Documentation

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Epic Games今天宣布,正式发布“虚幻引擎4”(Unreal Engine 4/UE4),相关所有资源也一并放出。# h9 u6 O( p! y& D) q4 K7 P9 ~# N   只要每个月花19美元,你就能到全部资源,包括拿过来就能用的虚幻编辑器(Unreal Editor),GitHub上的完整C++源代码(支持微软Visual Studio/苹果Xcode),还有完整的生态系统:论坛、维基、问答、协作。8 t8 q& _* ?7 K. D) S6 W 一大波新游戏要来了 虚幻4引擎正式发布, s! f+ v' w9 M j3 y: ^   而在虚幻引擎4游戏的销售中,Epic将抽取5%的毛收入提升,也就是你的游戏赚了100万美元,就要交给Epic 5万美元。   回到技术方面,Epic号称虚幻引擎4是他们多年来心血的结晶,而且现在只是第一版,才刚刚开始。C++代码里你可以看到大量的创新,比如说支持虚拟立体偷窥Oculus VR,支持Linux操作系统,以及支持Valve SteamWorks、StreamBox,而且还可以通过HTML5在网页浏览器内开发游戏(页游)。   平台支持PC、PS4、Xbox One、iOS、Google等等。   虚幻引擎4基于DirectX 11,拥有新的材料流水线、蓝图视觉化脚本、直观蓝图调试、内容浏览器、人物动画、Matinee影院级工具集、全新地形和植被、后期处理效果、热重载(Hot Reload)、模拟与沉浸式视角、即时游戏预览、AI人工智能、音频、中间件集成等一系列全新特性。   虚幻引擎4现已开始提供授权。 现在提供网盘下载地址,毕竟到官方下载很麻烦,还要$,呵呵,10分很值得,代码风格很好,注释很爽!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多方通行8

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值