つまり、失血に関するコードはサーバー側で実行される
ボールのゲーム開始機能を修正
サーバー側では、ボールが自動的にパスを見つけます
void AASTrackerBot::BeginPlay()
{
Super::BeginPlay();
if (Role == ROLE_Authority)
{
NextPathPoint = GetNextPathPoint();
}
//伤害事件绑定函数
HealthComp->OnHealthChanged.AddDynamic(this, &AASTrackerBot::HandleTakeAnyDamage);
}
SelfDestruct 関数を変更する
サーバー側では、ボールは自分自身にダメージを与えます
void AASTrackerBot::SelfDestruct()
{
//检查是否已经爆炸了
if (bExplored)
{
return;
}
bExplored = true;
//发生爆炸
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplorEffect, GetActorLocation());
//设置要忽略的actor
TArray<AActor * > IgnoredActors;
IgnoredActors.Add(this);
// UKismetSystemLibrary::PrintString(this, FString::SanitizeFloat(222.0f));
//伤害在服务器中执行
if (Role == ROLE_Authority)
{
//对自身进行伤害
UGameplayStatics::ApplyRadialDamage(this, ExplorDamage, GetActorLocation(), ExplorRadius, nullptr, IgnoredActors, this, GetInstigatorController(), true);
SetLifeSpan(2.0f);
}
//画出伤害范围
DrawDebugSphere(GetWorld(), GetActorLocation(), ExplorRadius, 12, FColor::Green, false, 2.0f, 0, 1.0f);
//发生爆炸声,在actor的位置
UGameplayStatics::PlaySoundAtLocation(this, ExploedSound, GetActorLocation());
//自毁
//Destroy();
MeshComponent->SetVisibility(false, true);
MeshComponent->SetSimulatePhysics(false);
MeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
フレームごとの機能を変更する
サーバー側では、ボールが自動的にパスを見つけます
void AASTrackerBot::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// UKismetSystemLibrary::PrintString(this, FString::SanitizeFloat(HealthComp->Health));
//得到小球自身与下一个点的距离
if (Role == ROLE_Authority && !bExplored)
{
float DistanceToTarget = (NextPathPoint - GetActorLocation()).Size();
//如果大于阈值,就继续滚
if (DistanceToTarget > RequiredDistanceToTarget)
{
//小球的移动方向
FVector ForceDirection = NextPathPoint - GetActorLocation();
ForceDirection.Normalize();
//小球的推力
ForceDirection *= MovementForce;
MeshComponent->ComponentVelocity.Size();
MeshComponent->AddImpulse(ForceDirection, NAME_None, bUseVelocityChange);
DrawDebugDirectionalArrow(GetWorld(), GetActorLocation(), GetActorLocation() + ForceDirection, 32, FColor::Red, false, 0.0f, 0, 1.0f);
}
//如果到达了路径点,就生成下一个点,继续移动
else
{
NextPathPoint = GetNextPathPoint();
DrawDebugString(GetWorld(), GetActorLocation(), "Target Reached!");
}
//在下一个目标点画一个球
DrawDebugSphere(GetWorld(), NextPathPoint, 20, 12, FColor::Yellow, false, 0.0f, 0, 1.0f);
}
}
オーバーラップ関数の修正
サーバー側では、ボールの自爆までのカウントダウン
void AASTrackerBot::NotifyActorBeginOverlap(AActor * OtherActor)
{
if (!bStartSelfDamge)
{
ASCharacter * PlayerPawn = Cast<ASCharacter>(OtherActor);
if (PlayerPawn)
{
if (Role == ROLE_Authority)
{
GetWorld()->GetTimerManager().SetTimer(TimerHandle_SelfDamage, this, &AASTrackerBot::DamageSelf, 0.5f, true, 0.0f);
}
bStartSelfDamge = true;
}
//将自爆警告声音绑定到根组件
UGameplayStatics::SpawnSoundAttached(SelfDestructSound, RootComponent);
}
}
健康コンポーネントを変更する
//当前生命值
UPROPERTY(ReplicatedUsing = OnRep_Health, BlueprintReadOnly, Category = "HealthComponent")
float Health;
ネットワーク同期機能を追加
//生命值同步函数
UFUNCTION()
void OnRep_Health(float OldHealth);
それに気付く
void USHealthComponent::OnRep_Health(float OldHealth)
{
//触发自定义事件
OnHealthChanged.Broadcast(this, Health, OldHealth - Health , nullptr, nullptr, nullptr);
}
なぜこのように同期する必要があるのですか?