1、我们想让人物碰到石柱,碰一次扣10滴血,然而在石柱的hit回调函数里,当人物碰到一次石柱时,回调了多次,原因是由于接触到的0.2秒时间内触发了多次回调
解决方法:用石柱的OnComponentBeinOverlap和EndOverLap,进入时用个actor的tarry保存这个actor,查看是否包含,包含就不扣血,不包含就扣血,人物离开时array.remove这个actor
2、ue4中 Map的用法
for (auto Pa:SpawnActorAndGenerateRateMap)
{
AllRateNum = Pa.Value + AllRateNum;
}
3、命名规范
类 | 继承于UObject的类使用前缀U,i.e. UTexture 继承于AActor的类使用前缀A,i.e. AGameMode 继承于SWidget的类使用前缀S,i.e. SClientName |
|||
其它类 | 模板类前缀带T,i.e. TArray, TMap, TQueue |
|||
枚举常量 | 命名空间内,类内部枚举类型名称,以字母E开头, 且枚举值名称,以”枚举标识_枚举名称”命名 全局枚举值名称,以“模块_枚举标识_枚举名称”命名 |
|||
每个变量都应该初始化 |
|
|||
4、如果变量设置为
UPROPERTY(Replicated, BlueprintReadWrite, EditAnywhere)
float fDestructActorHP;
那么蓝图中变量的右侧属性可以设置,且在蓝图里也可以设置
否则如果没有EditAnyWhere在属性中变量不可编辑,但可以在蓝图中设置
变量设置了EditAnyWhere,那么蓝图中选中根组件
在右侧可以配置所有设置EditAnyWhere的变量值
5、让一个c++类可以创建蓝图子类
解决方法:
在Uclass中添加Blueprintable
UCLASS(Blueprintable,BlueprintType, ClassGroup=(Custom), meta=(BlueprintSpawnableComponent))
ue4中含义是这样解释的
/// Exposes this class as a type that can be used for variables in blueprints
BlueprintType,
/// Prevents this class from being used for variables in blueprints
NotBlueprintType,
/// Exposes this class as an acceptable base class for creating blueprints. The default is NotBlueprintable, unless inherited otherwise. This is inherited by subclasses.
Blueprintable,
/// Specifies that this class is *NOT* an acceptable base class for creating blueprints. The default is NotBlueprintable, unless inherited otherwise. This is inherited by subclasses.
NotBlueprintable,
6、如何用c++将FVctor转成FString类型
调用UKismetStringLibrary类里的静态函数,里面封装了字符串拼接等许多函数
如果实在不知道,在蓝图中也可以看到
7、有时候vs编译后再ue编译器热加载可能会加载失败,最保险的办法debug启动vs的ue4
8、对于给物体施加一个力,必须要把该actor开启物理模拟,否则失效
9、实现这种效果的c++关键代码
如代码所示,施加力的方向是当前踏板平面的Rotation取得.Pitch平面加上一定角度,然后取得这个Rotator的单位向量乘以速度
事实上一个Rotator包括三个float变量,保存绕pitch,yaw和roll平面各多少角度,Rotator就是最后的欧拉角,Rotator.Vector是取得最终的的向量
对人(Character)和其他物体分别处理,人调用LaunchCharacter函数,其他物体先判断是否开启物理模拟,然后才对其施加力。
这里需要注意的是Rotator.Yaw拿到的是一个float值表示绕水平面的旋转角度,Rotator.Yaw.Vector拿到的向量只会在x和y坐标有值,表示在水平面的向量的x,y坐标
10、LookAtRotation的作用
会把一个向量转成一个Rotator,这个向量是目标位置减自己的位置,然后SetActorRotation,把这个Rotator当做参数传进去,自己就会旋转到目标位置
当然,一般让自己在地上左右旋转,最后转成的Rotator还要把它的.Pitch=0.0f,它的.Roll=0.0f
这样就只会在xy平面旋转,其他平面不会旋转
11、AI的逻辑只会在服务端执行
12、如果是uint8,那么它没有负数,只有正的
13、
float CurrentFOV = bWantsToZoom ? ZoomFov : DefaltFov;
14、相机抖动
在蓝图或c++中都是在PlayerController调用Client Play Camera Shake函数
如果蓝图指定这个shake类即可
创建一个蓝图类继承CameraShake类
里面包含了许多参数用于旋转信息等等
如果是c++调用,先创建一个TSubClassOf让其在蓝图中指定
UPROPERTY(EditDefaultsOnly, Category = "Weapon")
TSubclassOf<UCameraShake> FireCamShake
然后调用这个函数
14、对于组件和Actor的重叠关系
可以用GetOwner和SetOwner来获取组件的父类Actor
15、创建一个处理角色或怪物伤害的组件
在该组件中拿到父类Actor(角色或怪物)的Take Damage回调
Actor* MyOwner = GetOwner();
if(MyOwner)
{
MyOwener.OnTakeAnyDamage.AddDynamic(this,&USHealthComponent::HandleTakeAnyDamage);
}
于是,伤害的处理都放在了组件的HandleTakeAnyDamage函数中了
16、对于网络同步
第一种方法,在服务端处理数据,该多播就调用多播函数
第二种,在服务端处理数据,需要多播的时候看哪个数据发生变化,并设为ReplicatedUsing状态
UPROPERTY(ReplicatedUsing=OnRep_HitScanTrace)
FHitSCanTrace HitScanTrace;
UFUNCTION()
void OnRep_HitScanTrace();
回调函数中处理需要多播的逻辑
void ASWeapon::OnRep_HitScanTrace()
{
PlayFireEffects(HitScanTrace.TraceTo);
}
记得加上复制变量的条件
17、在多人射击游戏中有个bug:
其他人1秒开5枪时,自己看到的5个弹痕延迟很高
原因:UE4的动态更新速度按每Actor为单位进行,如果单个Actor没有发生太大变化,更新特定网络连接的更新频率也会动态降低
在UE4的Actor中设置的默认
NetUpdateFrequency = 100.0f;
MinNetUpdateFrequency = 2.0f;
在角色的构造函数中我们可以设置让其更新快点
NetUpdateFrequency = 66.0f;
MinNetUpdateFrequency = 33.0f;
18、记得组件需要复制的时候要SetReplicated
但是在Component逻辑中判断是否是在服务端执行的
不应当是
if(Role()== ROLE_Authority)
应当是
if(GetOwnerRole()== ROLE_Authority)
原因是Component不是一个Actor,没有Role,因此先GetOwner,再拿到Role(GetOwnerRole是这样封装的)
19、ue4.20中static mesh一定要给它一个默认材质颜色,如果是空会引起各种bug
20、
在调用延时时,如果要执行的函数是个带参数的,会报错
FTimerHandle AllHitLifeActorTimerHandle;
GetWorldTimerManager().SetTimer(AllHitLifeActorTimerHandle, this, &AGOARotatingBlade::RemoveLifeActorFromArray(OtherActor), 0.01f, true);
原因,第三个参数是个函数地址,把函数参数传进去语法错误
解决方法:设置一个委托,委托把函数和参数绑在一起,在调用延时函数
//延时0.5秒从数组中移除
FTimerHandle AllHitLifeActorTimerHandle;
FTimerDelegate TDelegate;
TDelegate.BindUObject(this, &AGOARotatingBlade::RemoveLifeActorFromArray, OtherActor);
GetWorldTimerManager().SetTimer(AllHitLifeActorTimerHandle,TDelegate, 0.5f, false);
void AGOARotatingBlade::RemoveLifeActorFromArray(AActor* OtherActor)
{
AllHitLifeActor.Remove(OtherActor);
}
21、
GetWorldTimerManager().SetTimer(FirstUpToSecondUpTimerHandle, this, &GroundThorns::GroundThornSecondUpFunction, fFirstUpToSecondUpTime, false);
报错:
void FTimerManager::SetTimer(FTimerHandle &,TFunction<void (void)> &&,float,bool,float)': cannot convert argument 3 from 'void (__cdecl GroundThorns::* )(float)' to 'void (__cdecl GroundThorns::* )(void)'
原因:
说的意思是GroundThorns::GroundThornSecondUpFunction这个函数是带参数的,但是这里应该传无参函数。
22、bug描述:
但是服务端和客户端都会打印
原因:该actor勾选Replicated,但是拖到地图中,不是在服务端生成,而是客户端和服务端都会生成,那么每个客户端的Role都等于Role_Authority
解决方法:
Is Server函数在KismetSystemLibrary封装,这样判断只会在服务端打印