21uec++ マルチプレイヤーゲーム【AIオンライン】

つまり、失血に関するコードはサーバー側で実行される

ボールのゲーム開始機能を修正

サーバー側では、ボールが自動的にパスを見つけます

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);

}

なぜこのように同期する必要があるのですか?

 

 

おすすめ

転載: blog.csdn.net/zhang2362167998/article/details/128113543