UE4C++]错题本

UE C++错误与注意

通过使用中出错又解决之来逐渐学习Unreal Engin的框架边界,同时整理出自己在UE中的使用感悟与注意事项,使得自己使用起来得心应手而又游刃有余。

最上方是最新的哦!

画面所有图标从Z轴上扁平化,Shader编译有问题

报错参考图:
画面出现图标扁平.png

原因你根本想不到:
摄像机近处的裁剪距离设置为0
Engine > General Settings > Settings > Near Clip Plane设置平面

尽量不要使用此值太低,因为它会对 z 缓冲区精度产生不利影响。因为不仅仅影响PIE的相机,还影响游戏的相机

编译时直接报错-532462766

MSB3073 The command "E:\UE4_27Source\Engine\Build\BatchFiles\Build.bat -Target="xxxEditor Win64 Development -Project=\"E:\Unreal\xxx\xxx.uproject\"" -Target="ShaderCompileWorker Win64 Development -Quiet" -WaitMutex -FromMsBuild" exited with code -532462766.

不管是重新编译,还是删除了其他生成的中间文件,二进制文件,一样。
报错参考图[借用]:
image.png

Git的原因,因为git里有些冲突的内容。我就是没有去管理好git,没有及时去处理git状态。直接删除.git能解决,但是你懂得。。。所以请管理好git要么先别用,要用就别懒(说我自己呢)。

EnhanceInput报错

报错参考图:
EnhanceInpu报错界面.png

编辑器运行游戏时,弹出这种错误,也没有说在哪里,只有EnhanceInput相关内容。

解决方案:
InputMappingContext文件是否存在None项,原因就是这个引起的。
EnhanceInput的InputMappingContext有None内容.png

出现 Unable to instantiate module 'UnrealEd'问题

报错参考图:
1675855228402.png

解决方案:
是不是在Source下的XX.Build.cs引用模块引用了一个奇怪的模块,名字类似UnrealEd

或者参考其他的图片:
1675855334537.png

单独的小点看你有没有犯错

  • 不要在UE4编辑蓝图过程中编译c++代码,会导致热重载bug不同步,得重启引擎。
  • 不要在构造函数传递this指针使用权

输出UENUM的字符串值

如果枚举使用了UENUM宏定义的,那么可以通过如下直接获得字符串值

// 定义枚举
UENUM(BlueprintType)
enum class ENumType : uint8
{
    One,        
    Two,       
    MaxType
};

ENumType NumData = ENumType::One;
// 获取枚举指针
UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ENumType"), true);
// 传字符串
FString EnumStr = EnumPtr->GetNameByValue((int)NumData).ToString();
// 或者
FString EnumStr2 = EnumPtr->GetNameStringByValue((int)NumData);

打印当前函数名

void UTestObject::UTestFunc()
{
    UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__));
}

其中__FUNCTION__代表的主浊当前函数名。

UE4小数点只有6位

float FloatNum = 3.1415926;
FString Cast_FloatNum = FString::SanitizeFloat(FloatNum);
// 打印出来
UKismetSystemLibrary::PrintString(this,Cast_FloatNum);

◇ 生成的组件要写上名字,不能为空

CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionComponent"));

上边TEXT()内的名字为空的话,UE4编辑器直接崩溃

◇ 如果在C++中修改了默认的值,没效果

如果在修改前,已经使用C类生成了蓝图,那么蓝图对应的值的默认状态会变,但值不会改变,也就是如果当前值与c中的值不同,蓝图中对应值后面的设置默认黄箭头会出现。

◇ CreateWidget的第一个参数

可能报错

The given OwningObject is not of a supported type for use with CreateWidget.

CreateWidget第一个参数.png

CreateWidget第一个参数2.png

◇ 蓝图construst出错

[Compiler] Cannot construct objects of type '/Script/HttpReq.HttpServerBase' in  Construct Object from Class

主要出现在蓝图里进行construct时报错,主要是你这个类没有没有蓝图化标记,注意下图中箭头位置要添加,默认是会添加,插件好像不会,如果没有需要添加。

注意:如果没有添加时已经编译,那么添加编译完后,需要重新启动UE4编辑器才会看到效果。

蓝图中无法construct.png

◇ 使用游戏的主模块

每个游戏项目在C++工程里会生成一个与项目名称对应的.h.cpp文件,如果想使用游戏的主模块,可以在项目名.h文件下添加如下。

主模块名为:F+项目名+Module
项目名不用也不能首字母大写

// 项目名.h
#include "CoreMinimal.h"

// 下边是新加了
class F项目名Module:public FDefaultGameModuleImpl
{
public:
    // 模块加载时调用
	virtual void StartupModule() override;
    // 模块卸载时调用
	virtual void ShutdownModule() override;
};

然后对应的.cpp里,除了对应函数的书写,还要修改下宏IMPLEMENT_PRIMARY_GAME_MODULE的部分。

// 项目名.cpp

#include ...// 省略

void F项目名Module::StartupModule()
{
	FDefaultGameModuleImpl::StartupModule();
	UE_LOG(LogTemp,Warning,TEXT("主模块初始化"));
}


void F项目名Module::ShutdownModule()
{
	FDefaultGameModuleImpl::ShutdownModule();
	UE_LOG(LogTemp,Warning,TEXT("主模块注销"));
}

IMPLEMENT_PRIMARY_GAME_MODULE(/*原来是:FDefaultGameModuleImpl*/FhttptestModule, httptest, "httptest");

修改第一个参数,修改成主模块名,搞定。

ConstructorHelpers::FObjectFinder前加不加static

关键字static使变量成为静态的。这意味着每次调用时具有相同的值。
变量的确切值是在第一次调用方法时确定的。
例如,当一个actor的所有实例都应该有一个指向相同共享资产的指针时,这很有用。如果您将此类变量设为静态,引擎将只搜索一次资产 - 而不是每次生成角色时。
在您的代码中,每次调用您的方法时可能需要不同的资产引用,因此不需要静态。

Exhausted all retries!

编辑器崩溃后的错误弹框还没有关闭,就开始IDE编译。就会出现这种错误。

不能将 未区分范围的枚举 重新声明为 区分范围的枚举

.h文件名传枚举类型的参数时,可能在前面有enum前缀,需要删除,其他引用这个枚举来源。

编译引擎代码时出错的话,会导致部分模块有问题

Plugin OnlineSubsystemUtils failed.png
找到自编译对应的模块位置
E:\xx...xx\UnrealEngine-4.27\Engine\Plugins\Online\OnlineSubsystemUtils
删除Binaries文件夹,使用IDE打开引擎项目重新编译,此时项目会自己搜索到对应的位置然后重新生成对应文件
引擎项目就是对应着自编译ue4的项目
E:\xx...xx\UnrealEngine-4.27\UE4.sln

设置了GameModeDefaultPawnClass但是游戏不生成,而只生成SpectatorPawn

  1. 先检查简单的,看是不是在播放(Play)游戏时,选中的是模拟(Simulate),部分情况下有可能是这个原因。

  2. 如果使用的基于GameModeBase的游戏模式,不会出现这个问题。那原因可能如下:

    在使用基于GameMode的游戏模式的话,会比GameMode多一个状态控制的流程。其中有一个属性:

    bDelayedStart 默认为false

    如果一旦有玩家进入这个关卡,默认情况下GameModeMatchState会从WatingToStart(等待开始)直接进入到InProgress(游戏中)状态,直接进入游戏中玩,比如守望先锋的加入游戏机制。

    而有时候,如果不想让玩家玩,而是像手动控制,比如等人加入齐了,再手动开始,而这时候玩家只是个观察者,从而先生成Speactator,默认玩家可以自由飞行。比如CS里死亡后的控制视角。如果想达到此目的就需要将bDelayedStart=true;,这样刚进入GameMode的话会先生成观察者,等待GameMode进入InProgress状态时,被切换成DefaultPawnClass

BoxComponent等碰撞组件点击滑入滑出等回调失效。

原因:UI会阻止鼠标事件,可能是因为这个原因。

  1. 如果在点击地方覆盖着UI组件,而且这个组件设置了visible。这样会阻止点击滑入滑出的鼠标操作,对碰撞组件的响应。
  2. 如果点击处没有UI组件的话,有可能整个WidgetVisibility属性设置为visible,这样这个UI的空白区也会阻挡鼠标事件无法穿透。

解决方法
注意UMGVisibility的属性。

UMG的Visibility属性.png

  1. 默认应该设置为 Not Hit-Testable (Self only),对应c++里的ESlateVisibility::SelfHitTestInvisible 。这种模式如果有空白不阻断事件,如果是Visible空白处会阻断事件。

设置了Replicates,但是actor没有复制

如果是想生成一个大家都能看到的组件。但是设置了Replicates,只有主机能看到,客户端看不到。有可能是此actor设置了这个属性。
复制属性只和拥有者有关.png
这个属性表示只和自己的拥有者相关,所以也只有拥有者能看到。而发生这种情况下,应该不是拥有者生成此Actor,所以也只有服务器能看到。

没有添加UMG引用

没有添加UMG引用.png

评论