0.UPROPERTY中的BlueprintPure,即工具类纯函数,无需执行引脚,只需输入输出。
1.想要复制某个属性时,使用Replicated,或使用ReplicatedUsing=函数名+UFUNCTION() void OnRep_属性名()的方法搭配,可实现变量复制/客户端成功接收复制数据时触发通知的效果。
2.标记复制的变量需要在GetLifetimeReplicatedProps函数中配置才可生效
void AThirdPersonMPCharacter::GetLifetimeReplicatedProps(TArray <FLifetimeProperty> & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
//复制当前生命值。
DOREPLIFETIME(AThirdPersonMPCharacter, CurrentHealth);
}
3.变量更新时对服务端与客户端提供不同的行为(该函数在OnRep_变量名中调用)
void AThirdPersonMPCharacter::OnHealthUpdate()
{
//客户端特定的功能
if (IsLocallyControlled())
{
FString healthMessage = FString::Printf(TEXT("You now have %f health remaining."), CurrentHealth);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, healthMessage);
if (CurrentHealth <= 0)
{
FString deathMessage = FString::Printf(TEXT("You have been killed."));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, deathMessage);
}
}
//服务器特定的功能
if (GetLocalRole() == ROLE_Authority)
{
FString healthMessage = FString::Printf(TEXT("%s now has %f health remaining."), *GetFName().ToString(), CurrentHealth);
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, healthMessage);
}
//在所有机器上都执行的函数。
/*
因任何因伤害或死亡而产生的特殊功能都应放在这里。
*/
}
4.仅在服务器端可以更改变量的值,更改后顺便调用OnHealthUpdate函数(因为服务器端复制数据之后不会调用OnRep_系列函数,需要在更新变量时手动调用操作的函数)
void AThirdPersonMPCharacter::SetCurrentHealth(float healthValue)
{
if (GetLocalRole() == ROLE_Authority)
{
CurrentHealth = FMath::Clamp(healthValue, 0.f, MaxHealth);
OnHealthUpdate();
}
}
5.TakeDamage整体流程:
- 外部Actor或函数对角色调用
CauseDamage,而角色又调用其TakeDamage函数。 TakeDamage调用SetCurrentHealth以在服务器上更改玩家的当前生命值。SetCurrentHealth在服务器上调用OnHealthUpdate,导致执行功能,响应玩家生命值的更改。CurrentHealth复制到所有已连接的客户端的角色副本。- 各个客户端从服务器收到
CurrentHealth的新值时,会调用OnRep_CurrentHealth。 OnRep_CurrentHealth调用OnHealthUpdate,确保各个客户端以相同方式响应CurrentHealth的新值。
6.用代码将某个Actor设置为复制:当 bReplicates 设为 True,只要Actor的权威副本存在于服务器上,就会尝试将该Actor复制到所有已连接的客户端。
7.子弹的初始化API,碰撞预设的设置: SphereComponent->SetCollisionProfileName(TEXT("BlockAllDynamic")); FobjectFinder<>按路径查找资产,若成功(finder.Succeeded()返回true),则将结果(finder.Object)设置给StaticMeth。
8.撞击函数/撞击函数绑定碰撞组件/销毁子弹产生爆炸效果
void AThirdPersonMPProjectile::Destroyed()
{
FVector spawnLocation = GetActorLocation();
UGameplayStatics::SpawnEmitterAtLocation(this, ExplosionEffect, spawnLocation, FRotator::ZeroRotator, true, EPSCPoolMethod::AutoRelease);
}
void AThirdPersonMPProjectile::OnProjectileImpact(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
if ( OtherActor )
{
UGameplayStatics::ApplyPointDamage(OtherActor, Damage, NormalImpulse, Hit, GetInstigator()->Controller, this, DamageType);
}
Destroy();
}
if (GetLocalRole() == ROLE_Authority)
{
SphereComponent->OnComponentHit.AddDynamic(this, &AThirdPersonMPProjectile::OnProjectileImpact);
}
9.生成投射物的RPC函数
10.Fire函数+定时器处理+FActorSpawnParameters的配置
void AThirdPersonMPCharacter::StartFire()
{
if (!bIsFiringWeapon)
{
bIsFiringWeapon = true;
UWorld* World = GetWorld();
World->GetTimerManager().SetTimer(FiringTimer, this, &AThirdPersonMPCharacter::StopFire, FireRate, false);
HandleFire();
}
}
void AThirdPersonMPCharacter::StopFire()
{
bIsFiringWeapon = false;
}
void AThirdPersonMPCharacter::HandleFire_Implementation()
{
FVector spawnLocation = GetActorLocation() + ( GetControlRotation().Vector() * 100.0f ) + (GetActorUpVector() * 50.0f);
FRotator spawnRotation = GetControlRotation();
FActorSpawnParameters spawnParameters;
spawnParameters.Instigator = GetInstigator();
spawnParameters.Owner = this;
AThirdPersonMPProjectile* spawnedProjectile = GetWorld()->SpawnActor<AThirdPersonMPProjectile>(spawnLocation, spawnRotation, spawnParameters);
}
StartFire 是玩家在本地机器上调用的函数,用于初始化发射流程,它基于以下条件限制用户调用 HandleFire 的频率:
- 若用户正在发射投射物,则不可发射。这是用
bFiringWeapon指派的,在调用StartFire时,bFiringWeapon设为true。 - 调用
StopFire时,bFiringWeapon仅可设为false。 - 时长为
FireRate的定时器结束时,会调用StopFire。
这意味着用户发射投射物时,必须等待数秒(等于 FireRate),之后方可继续发射。无论 StartFire 绑定到何种输入,这种情况始终一致。例如,若用户将"Fire"命令绑定到滚轮或类似的不当输入,或用户反复狂按按钮,此函数仍会按可接受的时间间隔执行,不会使 HandleFire 调用导致用户的可靠函数队列溢出。
因为 HandleFire 是服务器RPC,其在CPP文件中的实现必须在函数名前面添加前缀 _Implementation。
本指南中的实施使用角色的控制旋转获取摄像机的朝向,然后生成面朝该方向的投射物,以便玩家瞄准。接下来,投射物的投射物移动组件使其朝该方向移动。