第一个完整UE项目总结
C++委托蓝图注册
//声明委托 必须声明多播委托
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FRefresh);
//声明委托字段
{
UPROPERTY(BlueprintAssignable)
FRefresh dTest;
}
蓝图使用
C++方法蓝图调用
UFUNCTION(BlueprintCallable)
FString GetTitle();
资产文件
类被自动生成出来后把cpp文件删掉,不然会导致资产文件不能识别头文件,仅识别cpp文件然后导致资产加载失败。配了半天,资产加载失败,也是很奔溃的,但是只要我们把cpp文件删掉,重写编译即可。
USTRUCT(BlueprintType)
struct FStateData
{
GENERATED_BODY()
public:
/**
* @brief id
*/
UPROPERTY(BlueprintReadWrite, EditAnywhere)
uint8 uiStateID;
};
/**
*
*/
UCLASS()
class M1_API UD_State : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
/**
* @brief 状态合集
*/
UPROPERTY(BlueprintReadWrite, EditAnywhere)
TArray<FStateData> aStates;
};
配置表
配置表单行资源的结构体要继承FTableRowBase类
USTRUCT(BlueprintType)
struct FHospitalData :public FTableRowBase
{
GENERATED_BODY()
/**
* @brief 单位ID
*/
UPROPERTY(BlueprintReadWrite, EditAnywhere)
uint8 uiUnitID;
};
//加载配置表
UDataTable* const table = LoadObject<UDataTable>(nullptr,*sATPath);
table->GetAllRows<FAssetsTable>("hhhh",OUT outHDarr);//第一个参数只在获取失败的时候用于打印报错,更利于定位问题
添加组件,移除组件,获取组件,查找actor
//添加组件并把组件显示在编辑器里
{
UInitStart* init=NewObject<UInitStart>(this,TEXT("init"));
this->AddInstanceComponent(init);
init->RegisterComponent();
this->AttachToComponent(RootComponent,FAttachmentTransformRules::SnapToTargetIncludingScale);
break;
}
//移除组件 在ue4里没有移除组件这个功能,应该是不允许任何组件在没有父物体的时候存在
//在蓝图里不允许组件后面连线销毁自身,会提示不应该被销毁。不惯着,去c++里销毁
{
DestroyComponent();
}
//当你已经获取Actor的时候可以这样获取
//用被注释的方法不能正确获取到组件(UE5不可以)
{
line =(USplineComponent*)GetComponentByClass(USplineComponent::StaticClass());
//line =reinterpret_cast<USplineComponent*>(GetComponentByClass(TSubclassOf<USplineComponent>()));
}
//根据类获取对象
{
ahha = (Ahha*)(UGameplayStatics::GetActorOfClass(GetWorld(),Ahha::StaticClass()));
}
动态加载基于AActor蓝图类并实例化(2023/1/3增)
路径可以直接右击资源点击复制资源引用,如果是蓝图在后缀上加上_C
如:WidgetBlueprint'/Game/UI/SelectTool.SelectTool' Path=WidgetBlueprint'/Game/UI/SelectTool.SelectTool_C'
UClass* tempa= LoadClass<AActor>(nullptr,path);//加载
if(tempa) GetWorld()->SpawnActor(tempa); //动态生成
蓝图引用传递参数蓝图函数
(点击方法)
字符串比较
直接使用FString的==重载即可,这个重载会根据大小写是否敏感和字符类型选择合适的方法。下面的是宽字符比较两个字符串是否相等的方法。
//MicrosoftPlatformString.h
static FORCEINLINE int32 Strcmp( const WIDECHAR* String1, const WIDECHAR* String2 )
{
return _tcscmp(String1, String2);
}
延时执行方法和循环执行方法
循环执行,在SetTimerManager根据参数改。
FTimerHandle mTinmeHandle; //计时器委托句柄
GetWorld()->GetTimerManager().SetTimer(mTinmeHandle,this,&UOrientationState::Swap,5.0f,false); //一次性延时方法执行
GetWorld()->GetTimerManager().ClearTimer(mTinmeHandle); //清理计时器句柄
3DUI
1.首先创建一个用户控件
2.创建一个蓝图继承自Actor类
3.添加控件组件,并在控件组件的控件类里设置目标用户控件
碰撞检测
碰撞检测的监听使用委托,新建一个参数匹配的委托并注册就可以了。
//.h文件
UFUNCTION() //一定要加
void OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent,AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
//.cpp
void AHospitalActor::OnComponentBeginOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
UE_LOG(LogTemp,Warning,TEXT("碰撞检测,物体名称:%S"),OtherActor->GetName());
}
//BeginPlay里注册
reinterpret_cast<UStaticMeshComponent*>(this->GetComponentByClass(UStaticMeshComponent::StaticClass()))->OnComponentBeginOverlap.AddDynamic(this,&AHospitalActor::OnComponentBeginOverlap);
C++接口
最近看到DX12库文件里有一个接口的实现方案,这样实现和在一个正常类里声明虚函数差不多。
THIS_ INTERFACE FAR* This //combaseapi.h
//d3dcommon.h 接口声明
typedef interface ID3DInclude ID3DInclude;
DECLARE_INTERFACE(ID3DInclude)
{
STDMETHOD(Open)(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID *ppData, UINT *pBytes) PURE;
STDMETHOD(Close)(THIS_ LPCVOID pData) PURE;
};
//接口实现
class Dx12ShaderInclude : public ID3DInclude
{
public:
Dx12ShaderInclude();
virtual ~Dx12ShaderInclude();
STDMETHOD(Open)(THIS_ D3D_INCLUDE_TYPE IncludeType, LPCSTR pFileName, LPCVOID pParentData, LPCVOID* ppData, UINT* pBytes);
STDMETHOD(Close)(THIS_ LPCVOID pData);
private:
MMap<MString, MString> m_FileMap;
};
路径动画(样条线)
准备工作:给Aector加样条线组件(spline)
//.h
UCLASS()
class SIYIDA_API ARouteActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ARouteActor();
USplineComponent* m_Line;
/**
* @brief 获取当前位置
* @param temp 时间*速度
* @param v3 返回位置
* @param reverse 是否反向
*/
void GetPosition(float temp,FVector& v3,bool reverse);
//获取旋转
FRotator GetRotate(float temp);
//是否完成
bool IsFinish(float temp);
UPROPERTY(EditAnywhere)
float f_Length; //样条线长度
float temp;
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
//.cpp
void ARouteActor::GetPosition(float temp,FVector& v3,bool reverse)
{
if(reverse) temp=f_Length-temp;
v3 = m_Line->GetLocationAtDistanceAlongSpline(temp, ESplineCoordinateSpace::World);
}
FRotator ARouteActor::GetRotate(float temp)
{
return m_Line->GetRotationAtDistanceAlongSpline(temp, ESplineCoordinateSpace::Local);
}
bool ARouteActor::IsFinish(float temp)
{
return (temp / f_Length) < 1.0f;
}
射线检测
float UCarrierComponent::Detection()
{
FHitResult hitResult(ForceInit);
FVector beginPos = GetOwner()->GetActorLocation();
FVector posEnd = beginPos -GetOwner()->GetActorUpVector()*1000.f;
GetWorld()->LineTraceSingleByChannel(hitResult, beginPos, posEnd, ECC_WorldStatic);
return hitResult.Distance;
}
加载并实例化物体
static AActor* LoadAndInstance(UObject* obj, FString path)
{
UClass* tempa= LoadClass<AActor>(nullptr,path.operator*());
if(tempa!=nullptr&&obj!=nullptr)
return obj->GetWorld()->SpawnActor(tempa);
return nullptr;
}
UI-列出视图
item
必须要继承用户列表条目接口,才可以在列表里设置子项目。
列表
这是一个被封装的刷新函数
1.清除列表
2.遍历数组,并中断数组的目标元素--结构体
3.创建item
4.构建item的数据(一个普通类,里面有数据字段)
5.添加到列表里
bug(待解决)
每一个item都可以被点击,然后item里有一个文本的数字会增加。当item数量多了后往后面滑动,前面的item数据会被刷掉。
解决方案(2023/1/16)
在ItemData里多记录一个字段,当数据被点击操作改变的时候,把改变的数据也记录下来。
Unity与UE对比
这两个引擎的操作上没什么太大的区别,基本上unity上的大部分使用经验都可以在ue里使用,如果只使用蓝图不使用c++去做内容,甚至感觉ue还更简单一些,我基本能用c++去完成绝不使用蓝图的情况下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)