Game Networking Challenge: C++/Blueprints

Game Networking Challenge: C++/Blueprints

Game Networking Challenge: C++/Blueprints

Game Networking Challenge: C++/Blueprints es el séptimo reto propuesto por el curso Unreal Engine 4 Mastery: Create Multiplayer Games with C++ de Tom Looman certificado por Epic Games disponible en la plataforma Udemy.

A lo largo del curso se desarrollarán dos juegos con base en C++ y extendiendo la funcionalidad con Blueprints. Los dos juegos son multijugador y se profundizará también en AI y para reforzar los diferentes temas se proponen distintos retos.

En este tema se ha modificado el código tanto en C++ como en BP para que funcione en red. Tenemos elementos y acciones que ejecutamos en el cliente, en el servidor y también replicamos en el resto de clientes como las armas, proyectiles, efectos, vida, etc…

El reto constaba de adaptar el barril explosivo del apartado anterior para que funcionara en red.

HealthComponent

.h
// On Health Change Event
DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnHealthChangedSignature, USHealthComponent*, HealthComp, float, Health, float, HealthDelta, const class UDamageType*, DamageType, class AController*, InstigatedBy, AActor*, DamageCauser);

UCLASS( ClassGroup=(COOP), meta=(BlueprintSpawnableComponent) )
class COOPGAME_API USHealthComponent : public UActorComponent

.cpp
// Called when the game starts
void USHealthComponent::BeginPlay()
{
  Super::BeginPlay();

  // Only hook if we are server
  if (GetOwnerRole() == ROLE_Authority)
  {
    AActor* MyOwner = GetOwner();

    if (MyOwner)
    {
      MyOwner->OnTakeAnyDamage.AddDynamic(this, &USHealthComponent::HandleTakeAnyDamage);
    }
  }

  Health = DefaultHealth;
}

void USHealthComponent::HandleTakeAnyDamage(AActor* DamagedActor, float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser)
{
  if (Damage <= 0.0f)
  {
    return;
  }

  // Update Health Clamped
  Health = FMath::Clamp(Health - Damage, 0.0f, DefaultHealth);

  UE_LOG(LogTemp, Log, TEXT("Health Changed: %s"), *FString::SanitizeFloat(Health));

  OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);
}

Character

.h
UFUNCTION()
void OnHealthChanged(USHealthComponent* OwningHealthComp, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);

/* Pawn died previously */
UPROPERTY(Replicated, BlueprintReadOnly, Category = "Player")
bool bDied;

.cpp

#include "Net/UnrealNetwork.h"

void ASCharacter::OnHealthChanged(USHealthComponent * OwningHealthComp, float Health, float HealthDelta, const UDamageType * DamageType, AController * InstigatedBy, AActor * DamageCauser)
{
  if (Health <= 0.0f && !bDied)
  {
    // Die!
    bDied = true;
    GetMovementComponent()->StopMovementImmediately();
    GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);

    DetachFromControllerPendingDestroy();
    SetLifeSpan(10.0f);
    
  }

}

void ASCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
  Super::GetLifetimeReplicatedProps(OutLifetimeProps);

  DOREPLIFETIME(ASCharacter, CurrentWeapon);
  DOREPLIFETIME(ASCharacter, PrimaryWeapon);
  DOREPLIFETIME(ASCharacter, SecondWeapon);
  DOREPLIFETIME(ASCharacter, bDied);

}

Weapon

.h
UFUNCTION(Server, Reliable, WithValidation)
void ServerFire();

.cpp
void ASWeapon::ServerFire_Implementation()
{
  Fire();
}

bool ASWeapon::ServerFire_Validate()
{
  return true;
}

A continuación os dejaré los enlaces al código, demo y al video en youtube para que podáis ver más. De momento me está gustando el curso pero al final compartiré una valoración general por si a alguien le pueda interesar que sepa más o menos que esperar del mismo.

Repositorio: Game Networking Challenge: C++/Blueprints [project]

Demo: Game Networking Challenge: C++/Blueprints [demo]

Curso: Unreal Engine 4 Mastery: Create Multiplayer Games with C++