ue4总结十

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
抽象接口类使用前缀I,i.e. ITransaction
大多数的其他类使用前缀F,包括结构体,i.e. FName, Fvector
枚举类型使用前缀E,i.e. ESelectionMode
bool类型,使用前缀b,i.e. bEnabled

   
枚举常量

命名空间内,类内部枚举类型名称,以字母E开头,

且枚举值名称,以”枚举标识_枚举名称”命名

全局枚举值名称,以“模块_枚举标识_枚举名称”命名

   
每个变量都应该初始化

成员变量不必在构造函数赋值,可直接在申明处赋值

class A

{

    int Param1 = 0;

    float Param2 = 0;

    int ParamArray[10] = {0};

};

   
       

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封装,这样判断只会在服务端打印

猜你喜欢

转载自blog.csdn.net/zhangxiaofan666/article/details/82192894