UnrealEngine小技巧

鼠标左键操作时固定视角

  • 说明:UE默认鼠标左键或右键按住时滑动鼠标则可旋转视角,如果鼠标左键做了其他拖拽功能又不想旋转视角
  • 方法:可设置是否忽略LookInput
    在这里插入图片描述

Game启动角色控制问题

  1. 启动Game后需要鼠标点击一下才能进入控制问题
  • 说明:启动Game后想要直接进入控制,但出现需要鼠标点击一下才能进入控制
  • 方法:进入Editor Preferences/Play,设置GameGetsMouseControl为true
    在这里插入图片描述
  1. 启动Game后视角会自动跟随鼠标移动而旋转问题
  • 说明:视图添加了UMG,启用了Controller的ShowMouseCursor,想要进入场景时需要按住鼠标键滑动来控制视角旋转,但是启动Game后发现不按鼠标键,视角旋转也自动跟随鼠标滑动控制了
  • 方法:BeginPlay时使用SetInputModeGameAndUI
    在这里插入图片描述

Pawn使用SpringArm

  1. 旋转控制问题
  • 说明:默认Pawn没有勾选UseControllerRotationPitch/Yaw/Roll,使用了SpringArm后,无法旋转控制
  • 方法:勾选SpringArm组件中的UsePawnControlRotation选项
    在这里插入图片描述
  1. 视角突然拉近目标问题
  • 说明:当有碰撞体距离Pawn的Camera距离在SpringArm组件设置的ProbeSize数值内将发生拉近目标问题
  • 方法:取消勾选SpringArm组件中的DoCollisionTest选项
    在这里插入图片描述

Game模式射线碰撞获取多维子材质

  • 说明:Game模式下,使用鼠标射线碰撞来获取模型中多个材质槽中对应的材质
  • 方法:通过LineTraceByChannel(取消勾选TraceComplex)来获得HitResult,此HitResult的TraceStart与TraceEnd作为参数再使用LineTraceByChannel(勾选TraceComplex)来获得HitResult,此HitResult中的HitComponent调用GetMaterialFromCollisionFaceIndex(FaceIndex作为参数)来获取对应材质槽Index和对应的材质
    在这里插入图片描述

TextRender应用中文

  • 说明:默认TextRender应用的字体不支持中文字符
  • 方法:通过创建字体并设置字体缓存类型为离线,设置Import Options属性(不使用UnicodeRange也可以手动添加Chars),设置完成后重新导入
    AlphaOnly: true
    Unicode Range: 4E00-9FA5
    在这里插入图片描述

蓝图中应用Touch现实单指滑动,双指缩放

  • 说明:触摸屏多指滑动会导致FingerIndex的累加,如果判断FingerIndex来处理逻辑会出问题
  • 方法:通过组数来管理激活的FingerIndex,超过2个则清空数组来做限制,后面通过数据数量来判断逻辑,
    在Moved分支中判断数组中更改FingerIndex对应的Location,最后调用对应的事件,以便自定义功能的实现
  • PlayerController(蓝图类)
    在这里插入图片描述
  • TouchIndexInfo(结构体)
    在这里插入图片描述
  • CheckFingerIndexs(宏)
    在这里插入图片描述
  • UpdateTouchLocation(函数)
    在这里插入图片描述

多人联机NavData在Client不存在

  • 说明:多人联机中,使用了Nav寻路系统,在Client端无效,Play状态下使用控制台命令Show Navigation显示NavData,发现NavData只存在于Server而不存在与Client
  • 方法:进入Project Settings/Navigation System,设置Allow Client Side Navigation为true
    在这里插入图片描述

VR模式运行画面模糊

  • 说明:在VR模式下运行,头显显示的画面较模糊
  • 方法:使用控制台命令
//确保开启VR模式
Stereo On
//设置分辨率
vr.PixelDensity 1.4
//或者
r.Screenpercentage 140

编辑器蓝图工具获取Asset类型并放置Actor到场景

  • 说明:在编辑器工具类中获取自定义的Actor资产Class,并SpawnActor到场景
  • 方法:先在项目设置里添加一项PrimaryAssetTypesToScan,然后再蓝图工具中通过AsyncLoadClassAsset导入AssetClass并转换成ActorClass,提供给SpawnActor节点。
    请添加图片描述
    在这里插入图片描述

程序窗口失去焦点,没有声音

  • 说明:当程序窗口失去了焦点,默认会没有声音
  • 方法1:在其中一个配置文件中设置音量为1.0(打包前:YourProject/Config/DefaultEngine.ini ; 打包后:WindowsNoEditor/YourProject/Saved/Config/WindowsNoEditor/Engine.ini)
    [Audio]
    UnfocusedVolumeMultiplier=1.0
    
  • 方法2:C++中开放蓝图功能设置音量1.0
    UFUNCTION(BlueprintCallable, Category = MiscUtil, meta = (WorldContext = "WorldContextObject"))
    static void SetUnfocusedVolumeMultiplier(UObject* WorldContextObject, float Value)
    {
    	FApp::SetUnfocusedVolumeMultiplier(Value);
    }
    

C++声明,蓝图调用静态函数WorldContextObject免传参

  • 说明:C++继承蓝图函数库时,静态方法中需要传入WorldContextObject上下文对象,蓝图每次调用需要传参很麻烦
  • 方法:通过反射宏声明 meta = (WorldContext = “WorldContextObject”),蓝图中可免传参WorldContextObject
UFUNCTION(BlueprintPure, Category = CourseManager, meta = (WorldContext = "WorldContextObject"))
	static FString GetCourseMode(UObject* WorldContextObject, int32 InMode);

C++声明,蓝图调用函数TMap免传参

  • 说明:C++ 函数使用TMap参数,蓝图每次调用需要Make传参,不然无法编译通过
  • 方法:通过反射宏声明 meta = (AutoCreateRefTerm = “Headers”),蓝图中可免传参Headers
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true",AutoCreateRefTerm = "Headers", WorldContext = "WorldContextObject"))
	static UHttp* CreateHttpRequest(UObject* WorldContextObject, FString Url, const TMap<FString, FString>& Headers, FString Body);

C++声明,变量暴露编辑器和Spawn节点

  • 说明:C++声明类的变量暴露给蓝图,且变量需要暴露给编辑器和Spawn节点
  • 方法:通过反射宏声明 meta=(InstanceEditable=true, ExposeOnSpawn=true)
UPROPERTY(EditAnywhere, meta=(InstanceEditable=true, ExposeOnSpawn=true))
	FString ID;

C++ FSlateDrawElement 绘制旋转文字

  • 说明:在OnPaint中使用FSlateDrawElement绘制旋转文字
  • 方法:通过旋转Transform构建文字绘制的Geometry
//主要记录Geometry与Transform的处理,部分变量声明不在
int32 SGraphBase::DrawLabelText(const FOnPaintHandlerParams& InParams) const
{
	int32 DrawLayer = InParams.Layer + 1;

	//获取对应控件,文字绘制在此控件中心位置
	TSharedPtr<SWidget> WidgetPtr;
	FChildren* Children = HorBox->GetChildren();

	for (int32 Index = 0; Index < Children->Num(); ++Index)
	{
		WidgetPtr = Children->GetChildAt(Index);
		FVector2D WidgetSize = WidgetPtr->GetPaintSpaceGeometry().GetAbsoluteSize();
		FVector2D WidgetPos = WidgetPtr->GetPaintSpaceGeometry().GetAbsolutePosition() + WidgetSize * 0.5;

		//获取文字内容
		const FString LabelString = Labels[Index];

		//测量文字尺寸
		const TSharedRef< FSlateFontMeasure > FontMeasureService = FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
		FVector2D TextSize = FontMeasureService->Measure(LabelString, TextFont);

		//创建旋转Geometry
		FSlateRenderTransform TextRenderTransform = TransformCast<FSlateRenderTransform>(FQuat2D(FMath::DegreesToRadians(LableTextRot)));
		const FGeometry TextRenderGeometry = InParams.Geometry.MakeChild(TextRenderTransform);
		
		FVector2D PaintPos = TextRenderGeometry.AbsoluteToLocal(WidgetPos);

		//绘制文字
		FSlateDrawElement::MakeText
		(
			InParams.OutDrawElements,
			InParams.Layer,
			TextRenderGeometry.ToPaintGeometry(FVector2D(PaintPos.X, PaintPos.Y - TextSize.Y * 0.5), TextSize),
			LabelString,
			LabelFont,
			ESlateDrawEffect::None,
			LabelColor.GetSpecifiedColor()
		);
	}

	return DrawLayer;
}

C++ 多播代理属性供给蓝图绑定

  • 说明:多播代理属性有数组数据时在蓝图绑定代理事件使用时会出现:No value will be returned by reference
  • 方法:在UPROPERTY中添加:meta = (AllowPrivateAccess = true)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FAlarmInfoRequestCompleteDelegate, bool, bSuccess, int32, Code, FString, Message, const TArray<FAlarmInfo>&, AlarmInfos);

UPROPERTY(BlueprintAssignable, Category = "NetworkManager", meta = (AllowPrivateAccess = true))
		FAlarmInfoRequestCompleteDelegate AlarmInfoCompleteDelegate;

C++ 指定蓝图调用函数返回子类类型

  • 说明:提供给蓝图调佣,UE管理父类对象时,有时需要接口返回参数中指定的子类类型
  • 方法:在UPROPERTY中添加:meta = (DeterminesOutputType= “ManagerClass”)
UFUNCTION(BlueprintCallable, Category = "ManagerManager", meta = (DeterminesOutputType = "ManagerClass"))
		AManagerActor* GetManager(TSubclassOf<AManagerActor> ManagerClass);

C++ 异步任务

  • 说明:可以将一些简单的任务扔到UE的线程池中去进行,不必关心具体的线程同步问题
  • 方法:AsyncTask
AsyncTask(ENamedThreads::GameThread, [=]()
{
      //具体任务
});

C++ 字符串与其他类型互转

  • 说明:不同场景下需要把字符串类型与其他类型互转
  • 方法:使用特定代码转换
//std::string 转 FString
{
	std::string msg= "HelloWorld"; 
	FString Result (msg.c_str());
}

//FString转 std::string
{
	FString Message = TEXT("HelloWorld");
	std::string Result (TCHAR_TO_UTF8(*Message));
}

//FString 转 const char*
{
	FString Message = TEXT("HelloWorld");
	std::string msg(TCHAR_TO_UTF8(*Message));
	const char* Result  = msg.c_str();
}

//const char* 转 FString
{
	const char* msg = "HelloWorld";
	FString Result = FString(UTF8_TO_TCHAR(msg));
}

//FString 转 FName
{
	FString Message = TEXT("HelloWorld");
	FName Result = FName(*Message );
}

//FString 转 Integer
{
	FString Message = TEXT("123.456");
	int32 Result = FCString::Atoi(*Message );
}

//FString 转 Float
{
	FString Message = TEXT("123.456");
	float Result = FCString::Atof(*Message );
}

//Integer 转 FString
{
	int32 Data = 123;
	FString Result = FString::FromInt(Data);
}

//Float 转 FString
{
	float Data = 123.456;
	FString Result = FString::SanitizeFloat(Data);
}

//Array<uint8> 转 FString
{
	TArray<uint8> Data;
	const std::string msg(reinterpret_cast<const char*>(Data.GetData()), Data.Num());  
	FString Result = msg.c_str();  
}

//FArrayReaderPtr 转 FString
{
	uint8 Data[512];  
	FMemory::Memzero(Data, 512);    
	FMemory::Memcpy(Data, ArrayReaderPtr->GetData(), ArrayReaderPtr->Num());  
	FString Result = ((const char*)Data);  
}

//Enum 转 FString
{
	UENUM(BlueprintType)
	enum class EImageFmt : uint8
	{
		JPG			UMETA(DisplayName = "JPG"),
		PNG		UMETA(DisplayName = "PNG")
	};
	
	/* 获取枚举值的字符串*/
	template<class EnumType>
	FString GetEnumAsString(EnumType InEnumValue)
	{
		UEnum* Enum = StaticEnum<EnumType>();
		return Enum->GetNameStringByValue((uint8)InEnumValue);
	}
	
	//使用
	EImageFmt ImageFmt = EImageFmt::JPG;
	FString Result = GetEnumAsString<EImageFmt>(ImageFmt );
}

//中文字符转码
{	
	std::string ConvertTCHARToChar(const TCHAR* Ptr)
	{
		std::string strOut;
		if (Ptr != NULL)
		{
			int nInputStrLen = wcslen(Ptr);
			int nOutputStrLen = WideCharToMultiByte(CP_ACP, 0, Ptr, nInputStrLen, NULL, 0, 0, 0) + 2;
			strOut.resize(nOutputStrLen, 0);
			char* pBuffer = (char*)strOut.c_str();
			WideCharToMultiByte(CP_ACP, 0, Ptr, nInputStrLen, pBuffer, nOutputStrLen, 0, 0);
		}
		return strOut;
	}
}

编辑器Actor执行Tick函数

  • 说明:默认Actor在编辑器下不执行Tick函数
  • 方法:重写方法ShouldTickIfViewportsOnly,并设置PrimaryActorTick.bCanEverTick = true;

TestActor.h

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TestActor.generated.h"

UCLASS()
class ATestActor : public AActor
{
	GENERATED_BODY()

public:
	ATestActor();
	
	UPROPERTY(EditAnywhere, Category = "Debug")
		bool bUpdateInEditor = true;

	UPROPERTY(EditAnywhere, Category = "Debug")
		float TickCount;
		
public:
	virtual bool ShouldTickIfViewportsOnly() const override;
	virtual void Tick(float DeltaTime) override;
};

//TestActor.cpp

#include "TestActor.h"
ATestActor::ATestActor()
{
	PrimaryActorTick.bCanEverTick = true;
	PrimaryActorTick.TickGroup = ETickingGroup::TG_PostUpdateWork;
}

bool ATestActor::ShouldTickIfViewportsOnly() const
{
	return this->bUpdateInEditor;
}

void ATestActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	TickCount += DeltaTime;
}

C++ 插件模块使用Editor模块

  • 说明:Runtime插件模块使用Editor模块功能时编译会报无法解析外部符号错误
  • 方法:加入UnrealEd模块,并在使用位置引入对应头文件,并用宏判断包裹
//xx.Build.cs
if (Target.bBuildEditor == true)
{
    PublicDependencyModuleNames.AddRange(
        new string[] {
            "UnrealEd",
        }
    );
}
//ACustomActor.cpp

#if WITH_EDITOR
#include "Editor.h"
#include "EditorViewportClient.h"
#include "LevelEditorViewport.h"
#endif

#if WITH_EDITOR
bool ACustomActor::GetEditorActivedCamera(FOsgbCamera& OsgbCamera) {
	if (!GEditor) {return false;}
	UWorld* pWorld = this->GetWorld();
	if (!IsValid(pWorld)) {return false;}

	// Do not include editor cameras when running in a game world (which includes Play-in-Editor)
	if (pWorld->IsGameWorld()) {
		return false;
	}
	return true;
}
#endif

UE插件加载第三方dll并打包项目在其他电脑运行时崩溃

  • 说明:插件加载了其他dll打包后,在其他电脑上运行崩溃(开发环境与运行环境不同)
  • 方法:
    1. 下载VisualStudioSetup2022并安装组件 MSVC v143 -VS 2022 C++ x64/x86 生成工具(最新版)
      在这里插入图片描述
    2. 若第一步安装后无效,则下载安装DirectX

UE编译第三方库插件代码报错

说明:UE编译第三方库代码报错
方法:在插件Build.cs中添加对应的宏

//报错 error C4668: 没有将“......”定义为预处理器宏,用“0”替换“#if/#elif”
bEnableUndefinedIdentifierWarnings

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值