UE4 总结十四

1.模块加载的顺序问题

在引入插件时,会报错,可以看出是编辑器启动时,WidgetTree没有识别到该控件

解决方法:

在插件的uplugin文件中将插件的加载顺序从Default改成PreDefault,这样先加载模块,再加载引擎,就不会报错了

 

1 获得鼠标在世界坐标下的位置和方向,在PlayerController中的ProjectMousePositionToWorld方法,计算猪脚和鼠标的位置差来得到方向向量,让猪脚随着鼠标移动

 

UPROPERTY(BlueprintAssignable)  //  蓝图可以动态地为委托赋予事件  
    FOnKingDeathSignature OnKingDeath;// 多播委托实例,在Broadcast之后调用该委托上的方法  

 

3

https://blog.csdn.net/luomogenhaoqi/article/details/88994343

 

4

多客户端中勾选actor的replicated movement且开启物理模拟时,可能会出现位置来回闪动的情况,建议关闭replicated movement

 

5 一个很怪的bug,在服务端生成技能actor,技能多播怪物动画,发现怪物走了很远时,客户端突然不播放怪物动画,调试时发现,怪物走到很远的某个点时,该客户端的技能都不打印日志了

解决办法:

在网络复制中有个Net Cull Distance Squared,当技能actor离怪物很远时,就不会进行网络同步了,要么把距离设的很大,要么把该actor绑到怪物类上,要么勾选Always Relevant,不管距离远近都更新网络同步

 

6

对于一个mesh而言,我们也可以拿到Mesh在动画某个时刻的垂直于mesh的右侧方向量,前向向量,上侧向量

 

如果要做两个向量的叉积,用 cross函数

 

8

bool foundObject = (Object == NULL);
    return foundObject;

 

9

#define FSTRING_TO_INT(FStringValue)		FCString::Atoi(*FStringValue)


#define ACreateTimer(Handle, Obj, Method, Rate, bLoop)\
	GetWorldTimerManager().SetTimer(Handle, Obj, Method, Rate * GetActorTimeDilation(), bLoop)

 

10

报错

找到FSlateColor类,发现缺少了SlateCore模块,在build.cs中加入该模块即可

 

11

在UE4源码中有很多类继承了S开头的类,主要集中在Slate模块中,负责渲染功能,而U开头的类继承了UObject偏上层,主要负责游戏逻辑业务,为了保证垃圾回收,反射专门添加的机制,如果是F开头,是纯粹的c++类,是最底层的

 

12

发现一个奇怪bug,在写slate时报错,然而在build.cs中加了Slate,SlateCore和UMG三个模块还是报错

报错信息

2>MyEditableText.cpp.obj : error LNK2019: unresolved external symbol "public: static class FMoveCursor __cdecl FMoveCursor::ViaScreenPointer(struct FVector2D,float,enum ECursorAction)" (?ViaScreenPointer@FMoveCursor@@SA?AV1@UFVector2D@@MW4ECursorAction@@@Z) referenced in function "public: void __cdecl UMyEditableText::ShowMouseLight(void)" (?ShowMouseLight@UMyEditableText@@QEAAXXZ)
2>C:\UE4\Project\TestProject\aaa\Binaries\Win64\UE4Editor-aaa-Win64-DebugGame.dll : fatal error LNK1120: 1 unresolved externals 

解决方法

FMoveCursor没有暴露出来,他前面需要加一个SLATE_API才能被其他Module使用。

不过值得注意的是SLATE_API只有在Slate模块中才能使用,不能把该宏标记放到自己的模块中使用,会报编译错误

 

还有一次也是报链接错误,不过这次加上"UnrealEd"模块编译就过了

 

13 

在调用ProcessEvent第二个参数传入函数指针对应函数的参数,如果该函数有多个参数,封装到一个自定义的struct中,带一个return,用这个返回值来判断是否调用该函数成功的标识

这种方法很怪,为什么不直接调该函数,而是先拿到函数指针,再通过函数指针调函数?

原因:比如某个类继承了actor是在蓝图创建的,并且该函数写在了蓝图里,c++获取不到,那么可以用这种方式在c++拿到该蓝图类的某个函数

bool UCWMaker::IsMatchSituation(const FString& InFuncName)
{
	// Check Func is valid
	UFunction* Function = FindFunction(FName(*InFuncName));
	if (nullptr == Function)
	{
		CWG_ERROR(">> %s::IsMatchSituation, Function[%s] is nullptr!!!", *CWG_NAME(this), *InFuncName);
		return false;
	}

	// define a container
	struct FDynamicArgs
	{
		bool Return = false;
	};

	// create the container
	FDynamicArgs Args = FDynamicArgs();
	ProcessEvent(Function, &Args);

	return Args.Return;
}

 

14 vs2017代码自动补齐

在Tools->Options

 

15 寻找到指定文件夹下的所有文件的代码

// 遍历文件夹下指定类型文件
// OutFiles 保存遍例到的所有文件
// FilePath 文件夹路径  如 "D:\\MyCodes\\LearnUE4Cpp\\Source\\LearnUE4Cpp\\"
// Extension 扩展名(文件类型) 如 "*.cpp"
void Test::ScanDirectory(TMap<FString, FString>& OutFiles, const FString& InFilePath, const FString& InExtension)
{
	//IFileManager::Get().FindFilesRecursive(FindedFiles, *InFilePath, TEXT("*.uasset"), true, false);
	FindFilesRecursive(OutFiles, *InFilePath, *InExtension, true, false);
}

void Test::FindFilesRecursive(TMap<FString, FString>& FileNames, const TCHAR* StartDirectory, const TCHAR* Filename, bool Files, bool Directories, bool bClearFileNames /*= true*/)
{
	if (bClearFileNames)
	{
		FileNames.Reset();
	}
	FindFilesRecursiveInternal(FileNames, StartDirectory, Filename, Files, Directories);
}

void Test::FindFilesRecursiveInternal(TMap<FString, FString>& FileNames, const TCHAR* StartDirectory, const TCHAR* Filename, bool Files, bool Directories)
{
	FString CurrentSearch = FString(StartDirectory) / Filename;

	TArray<FString> Result;
	IFileManager::Get().FindFiles(Result, *CurrentSearch, Files, Directories);
	for (int32 i = 0; i < Result.Num(); i++)
	{
		const FString& RFileName = Result[i];
		const FString& RFullPath = FString(StartDirectory) / RFileName;
		FileNames.Add(RFileName, RFullPath);
	}

	TArray<FString> SubDirs;
	FString RecursiveDirSearch = FString(StartDirectory) / TEXT("*");
	IFileManager::Get().FindFiles(SubDirs, *RecursiveDirSearch, false, true);
	for (int32 SubDirIdx = 0; SubDirIdx < SubDirs.Num(); SubDirIdx++)
	{
		FString SubDir = FString(StartDirectory) / SubDirs[SubDirIdx];
		FindFilesRecursiveInternal(FileNames, *SubDir, Filename, Files, Directories);
	}
}

 

16

像这种遍历数组,删除其实很容易出错的,我们说遍历时候remove某个元素要非常注意,这种用法是错误的

 

17

ue4 vs的配置和番茄插件的基本配置教程

https://www.bilibili.com/video/av61492085/

 

18 

UE4材质_运用数学计算制作深洞效果

https://www.bilibili.com/video/av61206165

 

19

UE4超大地图的无缝加载和卸载

https://www.bilibili.com/video/av61987764

 

20

Open world optimization(LOD层面的优化)

https://www.bilibili.com/video/av59682722

https://www.youtube.com/watch?v=e0lK4DNtA9E

 

21

如果场景中有大量的树,如何选取所有同样的树?右键其中一棵树->选择->选择所有具有同样材质的项

 

22

Tweakptr和TSoftPtr的区别,为什么要引入这两个概念?

Tweakptr是引擎对于智能指针的一个弱引用的实现,就是不记录智能指针的引用计数,这样真正的指针不会因为这个 Tweakptr的指向而不能被释放。对应的是智能指针是TSharedPtr。

另外引擎还有一个TWeakObjectPtr,是表示不真正引用UObject,而导致这个UObject不能被GC,因为GC是通过查找引用关系来决定是否要GC。

TSoftPtr的作用不实际引用一个资源,而是记录这个资源的路径,这样这个类型不会一开始就把资源加载到内存里,而是可以让用户手动决定加载时机。

 

23

 

24.

1  这个节点是该物件从创建后开始计算,经历的时间

 

25.加载关卡时不填绝对路径的关卡名是很不好的,这样会遍历所有的地图资源,很影响性能

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值