21uec++ multiplayer game [AI online]

In a word, the code related to blood loss is executed on the server side

Modify the game start function of the ball

On the server side, the ball automatically finds the path

void AASTrackerBot::BeginPlay()
{
	Super::BeginPlay();
	if (Role == ROLE_Authority)
	{
		NextPathPoint = GetNextPathPoint();
	}

	//伤害事件绑定函数
	HealthComp->OnHealthChanged.AddDynamic(this, &AASTrackerBot::HandleTakeAnyDamage);
}

Modify the SelfDestruct function

On the server side the ball will apply damage to itself

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

}

Modify every frame function

On the server side, the ball automatically finds the path

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

}

modify overlap function

On the server side, the countdown to the self-explosion of the ball

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

Modify the health component

	//当前生命值
	UPROPERTY(ReplicatedUsing = OnRep_Health, BlueprintReadOnly, Category = "HealthComponent")
	float Health;

Add network synchronization function

	//生命值同步函数
	UFUNCTION()
	void OnRep_Health(float OldHealth);

realize it

void USHealthComponent::OnRep_Health(float OldHealth)
{
	//触发自定义事件
	OnHealthChanged.Broadcast(this, Health, OldHealth - Health , nullptr, nullptr, nullptr);

}

Why do you need to synchronize like this?

 

 

Guess you like

Origin blog.csdn.net/zhang2362167998/article/details/128113543