结构体同步
UE可以同步结构体变量,如果server上有个结构体A,声明如下:
struct FA
{
UPROPERTY(NotReplicated)
int b;
int c;
UPROPERTY(EditAnywhere)
int d;
}
上面结构中只有d会同步给客户端。如果数组元素中的d发生变化,但b,c属性依赖d的话,就可能出现b,c缓存的老的d对应的值。比如d 为道具ID,b为根据ID查找的Name,但Name会缓存。一帧内删增道具,会误判为d属性变化。进而Name和ID出现不对应的情况。
UE 编译
UE的编译需要VS,目前最新的VS2022-17.10版本会打不开sln。使用17.08可以打开。
https://aka.ms/vs/17/release.ltsc.17.8/vs_professional.exe
.NET Framework 4.7.2 Developer Pack
Visual Studio 2022 发行历史记录 | Microsoft Learn
导出属性到文本
如果想批量打印属性值,利用UE的反射比较方便。方式是获取class/struct,遍历它的Property,通过调用ExportTextItem_InContainer,得到值字符串。
// 遍历所有属性
for (TFieldIterator<FProperty> PropIt(FSkyCreatorWeatherSettings::StaticStruct()); PropIt; ++PropIt)
{
FProperty* Property = *PropIt;
FString PropertyName = Property->GetName();
// 获取属性值
FString PropertyValue;
Property->ExportTextItem_InContainer(PropertyValue, &SkyCreator->WeatherSettings, nullptr, nullptr, PPF_IncludeTransient | PPF_Copy);
// 打印属性名称和值
UE_LOG(LogTemp, Log, TEXT(" [Weather] '%s' : '%s'"), *PropertyName, *PropertyValue);
}
ExportTextItem_InContainer和ExportTextItem_Direct的区别在于前者会将地址作为基址,根据FProperty内部记录的偏移计算属性的基址;后者则需要直接提供属性基址。
注:如果属性的数值和对应类型默认构造函数产生的值相同,则不会导出。如果将Default值地址传入则会导出,但对于包含TMap属性,传入Default值地址会crash
比如:
struct A
{
float B = 0.f;
int C = 0;
bool D = false;
};
上面属性B,C,D 的数值和对应构造函数float(),int(),boo() 的数值相同,所以无法导出。
可以参考代码:
virtual bool Identical( const void* A, const void* B, uint32 PortFlags=0 ) const override
{
// RHS is the same as TTypeFundamentals::GetOptionalPropertyValue(B) but avoids an unnecessary copy of B
return TTypeFundamentals::GetPropertyValue(A) == (B ? TTypeFundamentals::GetPropertyValue(B) : TTypeFundamentals::GetDefaultPropertyValue());
}
template<typename InTCppType>
class TPropertyTypeFundamentals
{
static FORCEINLINE TCppType GetDefaultPropertyValue()
{
return TCppType();
}
}
bool FProperty::ExportText_Direct
(
FString& ValueStr,
const void* Data,
const void* Delta,
UObject* Parent,
int32 PortFlags,
UObject* ExportRootScope
) const
{
if( Data==Delta || !Identical(Data,Delta,PortFlags) )
{ ExportText_Internal
(
ValueStr,
(uint8*)Data,
EPropertyPointerType::Direct,
(uint8*)Delta,
Parent,
PortFlags,
ExportRootScope
);
return true;
}
return false;
}
Actor Overlap事件
问题:地图里在玩家出生位置摆放了一个Trigger,玩家刚出生时Trigger无法检测到玩家的Overlap事件,之后在内移动也无法触发。但换个简单图,或者摆放远处让玩家进去都能触发。
原因:地图有LevelStreaming关卡,触发Overlap时正在LevelStreaming,这时会判断Trigger上的bGenerateOverlapEventsDuringLevelStreaming配置,默认是False。勾选即可。
Simulation 开启
问题:Actor里的Mesh 设置物理模拟不起作用。
原因:Mobility 应该设成Movable。