Calmer的文章

  • 首页
  • 文章归档
  • 关于页面

  • 搜索
体验游戏 笔记 推荐 工具链 工具使用 小游戏 插件 UI 软件 教程

UE5开发问题记录(二)2023.3.15_2023.6.6

发表于 2023-05-27 | 分类于 游戏开发 | 0 | 阅读次数 1467

前言

这是近段时间开发遇到的一些比较典型的问题


实例

1. 在UE5里需要Spawn一个对象,怎么能让其Spawn的位置一定合理

例如:上坐骑的问题,周边地形生成actor的策略,很可能生成出来的位置是一个非法的位置
解决方案:引擎World.h中提供了一个FindTeleportSpot方法

2. 使用GAS时如果出现了LogAbilitySystem: Warning: Can't activate LocalOnly or LocalPredicted ability %s when not local!这样的警告消息,意味着ASC没有在Client端完成OwnerActor和AvatarActor的初始设定。

可以在PossessdBy中进行初始化

void AnMountBase::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);
	if(AbilitySystemComponent)
	{
		AbilitySystemComponent->InitAbilityActorInfo(this, this);
	}
	SetOwner(NewController);
	InitializeAttributes();
	AddStartupEffects();
	AddMountAbilities();
}

参考:https://stonelzp.github.io/ue4-gameplay-ability-system/

3. GAS的一些痛点,统一计算规则

详细见GEEC,MMC的封装和使用文章

4. UE在Possess的时候,产生瞬移的情况

答:是因为在服务器上创建的Character还未复制到客户端,但是Possess中RPC又已经提前到客户端了。虽然最终也能possess正确,其实是因为引擎在Tick中来确保客户端执行正确。
image.png

例如,网络游戏中,服务器会创建初始玩家角色,同时也会在服务器上进行Possess操作

5. UE5的反射应用

怎么通过UE5的反射动态添加字段或查询字段复制

  • 遍历一个类的所有属性
for (TFieldIterator<FProperty> It(UCaAttributeSetBase::StaticClass()); It; ++It)
	{
		FGameplayAttribute GameplayAttribute = FGameplayAttribute(*It);
		if(GameplayAttribute.IsValid())
		{	RelevantAttributesToCapture.Add(FGameplayEffectAttributeCaptureDefinition(GameplayAttribute,EGameplayEffectAttributeCaptureSource::Source, true));
			RelevantAttributesToCapture.Add(FGameplayEffectAttributeCaptureDefinition(GameplayAttribute,EGameplayEffectAttributeCaptureSource::Target, true));
		}
		UE_LOG(LogTemp,Log,TEXT("AttrbuteName:%s"), *It->GetName());
	}
  • 遍历一个类的所有方法
    可以参考UObject中的 CallFunctionByNameWithArguments

  • 遍历一个方法的所有参数
    可以参考UObject中的 CallFunctionByNameWithArguments

  • 怎么通过UE的反射动态添加字段或查询字段复制
    如何动态获取CPP的属性,并设置其值呢(反射)

6. UE5的元数据

  • 无侵入代码的修改部分枚举元数据
#if WITH_EDITOR
	UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("EGameplayEffectAttributeCaptureSource"), true);
	if(EnumPtr)
	{
		EnumPtr->SetMetaData(TEXT("DisplayName"), TEXT("攻击者"), 0);
		EnumPtr->SetMetaData(TEXT("DisplayName"), TEXT("受击者"), 1);
	}
#endif

参考:https://docs.unrealengine.com/4.27/zh-CN/ProgrammingAndScripting/GameplayArchitecture/Metadata/

7. UE5的加载(重点)

LoadObject
LoadClass
StaticLoadObject
StaticLoadClass

AssetManager
LoadAsset_Blocking
LoadClassAsset_Blocking
AsyncLoadAsset
AsyncLoadClassAsset

8. UE5中的WorldContext(上下文)

为什么蓝图中创建的BlueprintFunctionLibrary和Cpp创建的有区别,蓝图的多了WorldContext参数。

因此导致,在不正确的WorldContext下,没法调用蓝图创建的BlueprintFunctionLibrary,而Cpp的没问题

9.蓝图的蜜糖陷阱

image.png

image.png

这两种写法会导致完全不一样的结果
image.png
小心Blueprintpure函数, 其实每次都会去产生新的值,导致之前的修改值无效化

image.png

image.png
而如果是非blueprint,对返回值可以做修改。

区别在于,非BlueprintPure,只会在流程中依次执行,且只是执行一次,返回值会作为一个临时变量。
而BlueprintPure可能会执行多次,每次都是一个新的值,之前做的修改会丢失,除非将其存在一个临时变量中,对临时变量做修改。

10. GAS中GA怎么触发press相关的task,即怎么把GameplayAbility和InputId bind起来?

UE5中GAS接入增强输入(EnhancedInput)

11. UObject如果集成Tick?

  1. 方案一: 继承FTickableGameObject
UCLASS(Blueprintable,BlueprintType)
class TICKOBJECT_API UTickTestObject : public UObject, public FTickableGameObject
{
	GENERATED_BODY()

public:
	virtual void Tick(float DeltaTime) override;
	virtual TStatId GetStatId() const override;
};
#include "TickTestObject.h"
void UTickTestObject::Tick(float DeltaTime)
{
	UE_LOG(LogTemp, Log, TEXT("UTickTestObject: Do"));
}

TStatId UTickTestObject::GetStatId() const
{
	return Super::GetStatID();
}
  1. 方案二: AddTicker
UCLASS(Blueprintable, BlueprintType)
class TICKOBJECT_API UTickTestObject2 : public UObject
{
	GENERATED_BODY()
	virtual void BeginDestroy() override;

public:
	UFUNCTION(BlueprintCallable)
	void StartTick();

	UFUNCTION(BlueprintCallable)
	void EndTick();

	UFUNCTION(BlueprintNativeEvent)
	bool Tick(float DeltaTime);

private:
	FTSTicker::FDelegateHandle TickHandler;
};
#include "TickTestObject2.h"

void UTickTestObject2::StartTick()
{
	TickHandler = FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UTickTestObject2::Tick));
}

void UTickTestObject2::EndTick()
{
	if(TickHandler.IsValid())
	{
		FTSTicker::GetCoreTicker().RemoveTicker(TickHandler);
	}
}

bool UTickTestObject2::Tick_Implementation(float DeltaTime)
{
	UE_LOG(LogTemp, Log, TEXT("UTickTestObject2, Tick"));
	return true;
}

void UTickTestObject2::BeginDestroy()
{
	UObject::BeginDestroy();
	EndTick();
}

动画位移,如何把人物的碰撞也跟随动画一起移动?

  1. 方案一:根运动
    image.png
    若需要修改位移距离:
    • 美术修改动画资源重新导入
    • 使用AdditiveLayerTracks对骨骼进行简单调整
  2. 方案二:非根运动
    image.png
    如需要产生位移距离:
    • 程序设置移动Actor
  • 本文作者: Calmer
  • 本文链接: https://mytechplayer.com/archives/ue5开发问题记录二2023315202366
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
# 笔记
初探探索CI/CD
UE5中GAS GE属性计算(GE优化)
  • 文章目录
  • 站点概览
Calmer

Calmer

88 日志
7 分类
10 标签
RSS
Creative Commons
0%
© 2020 — 2025 Calmer
由 Halo 强力驱动
蜀ICP备20010026号-1川公网安备51019002006543
Copyright © 2020-2025 Calmer的文章