1.给物体施加一个径向力

定义一个径向力:

URadialForceComponent* RadialForceComp;

在构造函数里赋默认值:

RadialForceComp = CreateDefaultSubobject<URadialForceComponent>(TEXT("RadialForceComp"));
RadialForceComp->SetupAttachment(MeshComp);
RadialForceComp->Radius = 250.0f; //力影响的半径范围
RadialForceComp->bImpulseVelChange = true;//作用力速率变化为真
RadialForceComp->bAutoActivate = false;//prevent component from ticking, and only use fireImpulse() instead把自动激活关闭,用fireimpulse的方法来代替
RadialForceComp->bIgnoreOwningActor = true;//是否忽略自身

触发:

RadialForceComp->FireImpulse();

 

 

2.创建一个ActorComponent处理主角掉血事件

新建一个类 继承自UActorComponent:

class COOPGAME_API USHealthComponent : public UActorComponent

定义一个OnHealthChanged的事件:

UPROPERTY(BlueprintAssignable,Category = "Events")
FOnHealthChangedSignature OnHealthChanged;

在UCLASS的上面声明这个事件:

DECLARE_DYNAMIC_MULTICAST_DELEGATE_SixParams(FOnHealthChangedSignature, USHealthComponent*, HealthComp, float, Health, float, HealthDelta, const class UDamageType*, DamageType, class AController*, InstigatedBy, AActor*, DamageCauser);//定义一个动态、多播、委托、六个参数的事件

定义一个HandleTakeAnyDamage的事件来处理受到的伤害:

UFUNCTION()
void HandleTakeAnyDamage(AActor* DamagedActor ,float Damage, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);

将主角受到的伤害动态绑定到HandleTakeAnyDamage上:

AActor* MyOwner = GetOwner();

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

实现HandleTakeAnyDamage方法:

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

//update helth clamped
Health = FMath::Clamp(Health - Damage, 0.0f, DefaultHealth);

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

OnHealthChanged.Broadcast(this, Health, Damage, DamageType, InstigatedBy, DamageCauser);//将参数广播给OnHealthChanged
}

 

 

3.若要让服务器和客户端同时表现一样的效果,需要让服务器通知客户端该做什么,但代码依然在服务器端执行

将是否爆破的UPROPERTY加上ReplicatedUsing = OnRep_Exploded:

UPROPERTY(ReplicatedUsing = OnRep_Exploded)
bool bExploded;

定义一个事件OnRep_Exploded将上述实现

UFUNCTION()
void OnRep_Exploded();

在血量为0时,同时执行 OnRep_Exploded() 函数,目的是为了让客户端表现和服务器端一样的状态:

void ASExplosiveBarrel::OnHealthChanged(USHealthComponent * OwningHealthComp, float Health, float HealthDelta, const UDamageType * DamageType, AController * InstigatedBy, AActor * DamageCauser)
{
if (bExploded)
{
return;
}
if (Health <= 0.0f)
{
bExploded = true;
OnRep_Exploded();
FVector BoostIntensity = FVector::UpVector * ExplosionImpulse;
MeshComp->AddImpulse(BoostIntensity, NAME_None, true);

UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionEffect, GetActorLocation());
MeshComp->SetMaterial(0, ExplodedMaterial);
RadialForceComp->FireImpulse();
}
}

void ASExplosiveBarrel::OnRep_Exploded()
{
UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplosionEffect, GetActorLocation());
MeshComp->SetMaterial(0, ExplodedMaterial);
}

接下来记得在生命周期中复制bExploded给客户端,在cpp中引入头文件#include"Net/UnrealNetwork.h"后即可直接添加GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const 方法,后面的参数可保持不变:

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

DOREPLIFETIME(ASExplosiveBarrel,bExploded);
}

 

4.客户端服务器端同步

在构造函数中设置可重复为true:

SetReplicates(true);

定义一个服务器开火的事件,设置UFUNCTION里面的内容:

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

接着在cpp里添加服务器开火函数的_Implementation和_Validate,直接在ServerFire后添加(Validate有时候不需要):

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

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

判断Role是否在服务器上:

if (Role < ROLE_Authority) //判断Role是否在服务器上
{
ServerFire();                       //Role < ROLE_Authority,说明不在服务器上,让Server处理这个开火
}

else{}          //在服务器上,自己处理开火

 

 

 

 

 

 

源码贴:

 1 // Fill out your copyright notice in the Description page of Project Settings.
 2 
 3 #pragma once
 4 
 5 #include "CoreMinimal.h"
 6 #include "GameFramework/Character.h"
 7 #include"Public/SWeapon.h"
 8 #include "SCharacter.generated.h"
 9 
10 class UCameraComponent;
11 class USpringArmComponent;
12 class ASWeapon;
13 class USHealthComponent;
14 
15 UCLASS()
16 class COOPGAME_API ASCharacter : public ACharacter
17 {
18     GENERATED_BODY()
19 
20 public:
21     // Sets default values for this character's properties
22     ASCharacter();
23 
24 protected:
25     // Called when the game starts or when spawned
26     virtual void BeginPlay() override;
27 
28     void MoveForward(float value);
29 
30     void MoveRight(float value);
31 
32     void BeginCrouch();
33 
34     void EndCrouch();
35     UFUNCTION(BlueprintImplementableEvent)
36     void JumpFromAction();
37 
38     UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = "Components")
39     UCameraComponent* CameraComp;
40 
41     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
42     USpringArmComponent* SpringArmComp;
43 
44     UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
45     USHealthComponent* HealthComp;
46 
47     bool bWantsToZoom;
48 
49 
50     UPROPERTY(EditDefaultsOnly, Category = "Player")
51     float ZoomedFOV;
52 
53     UPROPERTY(EditDefaultsOnly, Category = "Player",meta = (ClampMin = 0.1,ClampMax = 100))
54     float ZoomInterpSpeed;
55 
56     /*default FOV set during begin play*/
57     float DefaultFOV;
58 
59     void BeginZoom();
60 
61     void EndZoom();
62 
63     UPROPERTY(Replicated)
64     ASWeapon* CurrentWeapon;
65 
66     UPROPERTY(EditDefaultsOnly,Category = "Player")
67     TSubclassOf<ASWeapon> StarterWeaponClass;
68 
69     UPROPERTY(VisibleDefaultsOnly,Category = "Player")
70     FName WeaponAttachSocketName;
71     void StartFire();
72 
73     void StopFire();
74 
75     UFUNCTION()
76     void OnHealthChanged(USHealthComponent* OwingHealthComp, float Health, float HealthDelta, const class UDamageType* DamageType, class AController* InstigatedBy, AActor* DamageCauser);
77 
78     UPROPERTY(Replicated,BlueprintReadOnly,Category = "Player")
79     bool bDied ;
80 public:    
81     // Called every frame
82     virtual void Tick(float DeltaTime) override;
83 
84     // Called to bind functionality to input
85     virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
86 
87     virtual FVector GetPawnViewLocation() const;
88     
89 };
SCharacter.h

相关文章:

  • 2021-11-26
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-05
  • 2022-01-04
  • 2022-12-23
猜你喜欢
  • 2021-07-09
  • 2021-12-28
  • 2021-12-18
  • 2021-11-21
  • 2021-10-05
  • 2021-12-24
  • 2022-12-23
相关资源
相似解决方案