当前位置: 首页 > news >正文

UE5学习笔记9-创建一个小窗口提示人物是否和武器重叠

一、目标

        创建一个UsrWidget去显示如果人物和武器重叠显示窗口,如果人物和武器不重叠将窗口隐藏

二、创建窗口并显示

        1.创建一个窗口蓝图类,命名为PickUpWidget,这个蓝图类不需要C++类,在对应文件夹中单机右键选择用户界面的控件蓝图

        2.在界面蓝图类中添加一个text控件,将字体设置为front,居中显示,可以在右侧栏找到对应设置,将控件命名为PickUpText

         3.在之前创建的武器的C++类中绑定text控件 ,在头文件中声明一个界面组件的指针在cpp文件中的构造函数中初始化这个指针

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Weapon.generated.h"// 一个枚举类 作为蓝图的类型
UENUM(BlueprintType) /* 可以将此枚举用作蓝图中的一种类型 */
enum class EWeaponState : uint8
{EWS_Initial UMETA(DisplayName = "Initial State"),EWS_Equipped UMETA(DisplayName = "Equipped"),EWS_Dropped UMETA(DisplayName = "Dropped"),EWS_MAX UMETA(DisplayName = "DefaultMAX")
};UCLASS()
class BLASTER_API AWeapon : public AActor
{GENERATED_BODY()public:// Sets default values for this actor's propertiesAWeapon();// Called every framevirtual void Tick(float DeltaTime) override;/** 设置何时显示提示框 是否角色和武器重叠 */void ShowPickupWidget(bool bShowWidget);
protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public:private:UPROPERTY(VisibleAnywhere, Category = "Weapon Properties") // 设置在任何地方都可以看见,类别设置为武器属性USkeletalMeshComponent* WeapomMesh;	/* 骨骼网格 */UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class USphereComponent* AreaSphere; /* 球形组件 判断人物模型和武器模型是否重叠 */UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")EWeaponState WeaponState;UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class UWidgetComponent* PickWidget; /* 界面组件 */
};
// Fill out your copyright notice in the Description page of Project Settings.#include "Weapon.h"
#include "Components/SphereComponent.h"
#include "Components/WidgetComponent.h"
#include "Net/UnrealNetwork.h"
#include "Blaster/Character/BlasterCharacter.h"// Sets default values
AWeapon::AWeapon()
{// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = false;bReplicates = true; //将执行组件复制到远程计算机 //由于想要将武器在服务器上判断是否碰撞,需要将武器作为一个actor复制到服务器上WeapomMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WeaponMesh")); //创建骨骼网格提成员,名字是WeaponMesh//WeapomMesh->SetupAttachment(RootComponent); //一个组件附加到另一个组件上SetRootComponent(WeapomMesh);//设置根组件// 当拿起武器时设置为完全阻止SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block)// 当丢掉武器时设置为设置为忽略,即没有碰撞SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore)// 当武器在地上时设置无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision) WeapomMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block); //将碰撞响应设置为完全阻止WeapomMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);//当放下武器时将任务设置为忽略,即没有碰撞WeapomMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);//设置无碰撞 // 想在服务器上检测当前碰撞区域是否和角色重叠// 将碰撞区域设置为SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore)不要碰撞// 设置为在所有机上都是无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision); // 在服务器上设置为启用碰撞 不在构造函数中设置,在游戏开始时BeginPlay()设置AreaSphere = CreateDefaultSubobject<USphereComponent>(TEXT("AreaSphere"));AreaSphere->SetupAttachment(RootComponent);AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);PickWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("PickUpWidget"));PickWidget->SetupAttachment(RootComponent);
}void AWeapon::ShowPickupWidget(bool bShowWidget)
{if (PickWidget){PickWidget->SetVisibility(bShowWidget);}
}// Called when the game starts or when spawned
void AWeapon::BeginPlay()
{Super::BeginPlay();// (GetLocalRole() == ENetRole::ROLE_Authority) == HasAuthority()	作用相同//	GetLocalRole() 获得本地角色 ENetRole::ROLE_Authority 是否具有角色权威if ( HasAuthority() ){ //如果当前是在服务器上,将碰撞设置为查询物理碰撞AreaSphere->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);//设置当前的碰撞是胶囊碰撞ECC_Pawn,并将碰撞设置为重叠ECR_OverlapAreaSphere->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn,ECollisionResponse::ECR_Overlap);}
}// Called every frame
void AWeapon::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}

         4.编译代码,打开武器的蓝图类可以在左侧栏看见刚添加的组件,选中当前组件在右侧谢绝栏中的用户界面下拉框中将空间改成屏幕,将空间类选择成刚才创建的pickupwidget的蓝图类的名字,将以所需大小绘制勾选,最后将提示框放到你想放到的位置上,如图。

        5.显示完成可以运行查看,若没有按照正确的位置显示请查看武器类的构造函数中这两行代码是否有设置跟组件,请将武器的骨骼设置为跟组件将另一行代码注释或删除

        WeapomMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WeaponMesh")); //创建骨骼网格提成员,名字是WeaponMesh
    //WeapomMesh->SetupAttachment(RootComponent); //一个组件附加到另一个组件上
    SetRootComponent(WeapomMesh);//设置根组件 

三、创建一个重叠部分判断的功能

        1.在头文件中添加一个函数用来判断是否发生重叠

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Weapon.generated.h"// 一个枚举类 作为蓝图的类型
UENUM(BlueprintType) /* 可以将此枚举用作蓝图中的一种类型 */
enum class EWeaponState : uint8
{EWS_Initial UMETA(DisplayName = "Initial State"),EWS_Equipped UMETA(DisplayName = "Equipped"),EWS_Dropped UMETA(DisplayName = "Dropped"),EWS_MAX UMETA(DisplayName = "DefaultMAX")
};UCLASS()
class BLASTER_API AWeapon : public AActor
{GENERATED_BODY()public:// Sets default values for this actor's propertiesAWeapon();// Called every framevirtual void Tick(float DeltaTime) override;/** 设置何时显示提示框 是否角色和武器重叠 */void ShowPickupWidget(bool bShowWidget);
protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;UFUNCTION()virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent,// UPrimitiveComponent重叠组件类AActor* OtherActor,UPrimitiveComponent* OtherComp,int32 OtherBodyIndex,bool bFromSweep,const FHitResult& SweepResult	//碰撞检测结果);public:private:UPROPERTY(VisibleAnywhere, Category = "Weapon Properties") // 设置在任何地方都可以看见,类别设置为武器属性USkeletalMeshComponent* WeapomMesh;	/* 骨骼网格 */UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class USphereComponent* AreaSphere; /* 球形组件 判断人物模型和武器模型是否重叠 */UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")EWeaponState WeaponState;UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class UWidgetComponent* PickWidget; /* 界面组件 */
};
// Fill out your copyright notice in the Description page of Project Settings.#include "Weapon.h"
#include "Components/SphereComponent.h"
#include "Components/WidgetComponent.h"
#include "Net/UnrealNetwork.h"
#include "Blaster/Character/BlasterCharacter.h"// Sets default values
AWeapon::AWeapon()
{// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = false;bReplicates = true; //将执行组件复制到远程计算机 //由于想要将武器在服务器上判断是否碰撞,需要将武器作为一个actor复制到服务器上WeapomMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WeaponMesh")); //创建骨骼网格提成员,名字是WeaponMesh//WeapomMesh->SetupAttachment(RootComponent); //一个组件附加到另一个组件上SetRootComponent(WeapomMesh);//设置根组件// 当拿起武器时设置为完全阻止SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block)// 当丢掉武器时设置为设置为忽略,即没有碰撞SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore)// 当武器在地上时设置无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision) WeapomMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block); //将碰撞响应设置为完全阻止WeapomMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);//当放下武器时将任务设置为忽略,即没有碰撞WeapomMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);//设置无碰撞 // 想在服务器上检测当前碰撞区域是否和角色重叠// 将碰撞区域设置为SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore)不要碰撞// 设置为在所有机上都是无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision); // 在服务器上设置为启用碰撞 不在构造函数中设置,在游戏开始时BeginPlay()设置AreaSphere = CreateDefaultSubobject<USphereComponent>(TEXT("AreaSphere"));AreaSphere->SetupAttachment(RootComponent);AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);PickWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("PickUpWidget"));PickWidget->SetupAttachment(RootComponent);
}void AWeapon::ShowPickupWidget(bool bShowWidget)
{if (PickWidget){PickWidget->SetVisibility(bShowWidget);}
}// Called when the game starts or when spawned
void AWeapon::BeginPlay()
{Super::BeginPlay();// (GetLocalRole() == ENetRole::ROLE_Authority) == HasAuthority()	作用相同//	GetLocalRole() 获得本地角色 ENetRole::ROLE_Authority 是否具有角色权威if ( HasAuthority() ){ //如果当前是在服务器上,将碰撞设置为查询物理碰撞AreaSphere->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);//设置当前的碰撞是胶囊碰撞ECC_Pawn,并将碰撞设置为重叠ECR_OverlapAreaSphere->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn,ECollisionResponse::ECR_Overlap);}if (PickWidget){PickWidget->SetVisibility(false);}
}void AWeapon::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{ABlasterCharacter* BlasterCharacter = Cast<ABlasterCharacter>(OtherActor);if (BlasterCharacter && PickWidget ){PickWidget->SetVisibility(true);}
}// Called every frame
void AWeapon::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}

四、当前效果

        在服务器上发生重叠可以看见提示,在客户端中看不见,当客户端发生重叠时客户端看不见提示在服务器上可以看见

五、创建一个当结束重叠时将提示款设置不可见

        一点说明:定义一个函数OnSphereEndOverlap代表结束重叠将会去实现的功能,在beginplay函数中通过之前定义的class USphereComponent* AreaSphere;指针调用OnComponentBeginOverlap 去绑定重叠开始的函数,调用OnComponentEndOverlap去绑定重叠结束的函数,参数可以在OnComponentBeginOverlap/OnComponentEndOverlap通过F12转到定义去查看。

        定义中FComponentBeginOverlapSignature OnComponentBeginOverlap;对FComponentBeginOverlapSignature转定义DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams( FComponentBeginOverlapSignature, UPrimitiveComponent, OnComponentBeginOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult);可以看见是一个宏函数有10个参数(为啥我有7个现在我也没整明白,视频中是这么写的,之后在研究)

        xxx.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Weapon.generated.h"// 一个枚举类 作为蓝图的类型
UENUM(BlueprintType) /* 可以将此枚举用作蓝图中的一种类型 */
enum class EWeaponState : uint8
{EWS_Initial UMETA(DisplayName = "Initial State"),EWS_Equipped UMETA(DisplayName = "Equipped"),EWS_Dropped UMETA(DisplayName = "Dropped"),EWS_MAX UMETA(DisplayName = "DefaultMAX")
};UCLASS()
class BLASTER_API AWeapon : public AActor
{GENERATED_BODY()public:// Sets default values for this actor's propertiesAWeapon();// Called every framevirtual void Tick(float DeltaTime) override;/** 要标记要复制的内容,我们使用 UPROPERTY 中的 Replicated 说明符。在将某个内容标记为 Replicated 之后,我们必须定义一个名为 GetLifetimeReplicatedProps 的新            函数 *//** 返回用于网络复制的属性,这需要被所有具有本机复制属性的 actor 类覆盖 */virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;/** 设置何时显示提示框 是否角色和武器重叠 */void ShowPickupWidget(bool bShowWidget);
protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;UFUNCTION()virtual void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent,// UPrimitiveComponent重叠组件类AActor* OtherActor,UPrimitiveComponent* OtherComp,int32 OtherBodyIndex,bool bFromSweep,const FHitResult& SweepResult	//碰撞检测结果);/** 重叠结束 */UFUNCTION()virtual void OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent,// UPrimitiveComponent重叠组件类AActor* OtherActor,UPrimitiveComponent* OtherComp,int32 OtherBodyIndex);private:UPROPERTY(VisibleAnywhere, Category = "Weapon Properties") // 设置在任何地方都可以看见,类别设置为武器属性USkeletalMeshComponent* WeapomMesh;	/* 骨骼网格 */UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class USphereComponent* AreaSphere; /* 球形组件 判断人物模型和武器模型是否重叠 */UPROPERTY(ReplicatedUsing = OnRep_WeaponState, VisibleAnywhere, Category = "Weapon Properties")EWeaponState WeaponState;UFUNCTION()void OnRep_WeaponState();UPROPERTY(VisibleAnywhere, Category = "Weapon Properties")class UWidgetComponent* PickWidget; /* 界面组件 */public:void SetWeaponState(EWeaponState state);
};

        xxx.cpp

// Fill out your copyright notice in the Description page of Project Settings.#include "Weapon.h"
#include "Components/SphereComponent.h"
#include "Components/WidgetComponent.h"
#include "Net/UnrealNetwork.h"
#include "Blaster/Character/BlasterCharacter.h"// Sets default values
AWeapon::AWeapon()
{// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = false;bReplicates = true; //将执行组件复制到远程计算机 //由于想要将武器在服务器上判断是否碰撞,需要将武器作为一个actor复制到服务器上WeapomMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WeaponMesh")); //创建骨骼网格提成员,名字是WeaponMesh//WeapomMesh->SetupAttachment(RootComponent); //一个组件附加到另一个组件上SetRootComponent(WeapomMesh);//设置根组件// 当拿起武器时设置为完全阻止SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block)// 当丢掉武器时设置为设置为忽略,即没有碰撞SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore)// 当武器在地上时设置无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision) WeapomMesh->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block); //将碰撞响应设置为完全阻止WeapomMesh->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Ignore);//当放下武器时将任务设置为忽略,即没有碰撞WeapomMesh->SetCollisionEnabled(ECollisionEnabled::NoCollision);//设置无碰撞 // 想在服务器上检测当前碰撞区域是否和角色重叠// 将碰撞区域设置为SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore)不要碰撞// 设置为在所有机上都是无碰撞SetCollisionEnabled(ECollisionEnabled::NoCollision); // 在服务器上设置为启用碰撞 不在构造函数中设置,在游戏开始时BeginPlay()设置AreaSphere = CreateDefaultSubobject<USphereComponent>(TEXT("AreaSphere"));AreaSphere->SetupAttachment(RootComponent);AreaSphere->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);PickWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("PickUpWidget"));PickWidget->SetupAttachment(RootComponent);
}void AWeapon::ShowPickupWidget(bool bShowWidget)
{if (PickWidget){PickWidget->SetVisibility(bShowWidget);}
}// Called when the game starts or when spawned
void AWeapon::BeginPlay()
{Super::BeginPlay();// (GetLocalRole() == ENetRole::ROLE_Authority) == HasAuthority()	作用相同//	GetLocalRole() 获得本地角色 ENetRole::ROLE_Authority 是否具有角色权威if ( HasAuthority() ){ //如果当前是在服务器上,将碰撞设置为物理碰撞AreaSphere->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);//设置当前的碰撞是胶囊碰撞ECC_Pawn,并将碰撞设置为重叠ECR_OverlapAreaSphere->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn,ECollisionResponse::ECR_Overlap);// 绑定一个重叠区域处理函数AreaSphere->OnComponentBeginOverlap.AddDynamic(this,&AWeapon::OnSphereOverlap);AreaSphere->OnComponentEndOverlap.AddDynamic(this, &AWeapon::OnSphereEndOverlap);}if (PickWidget){PickWidget->SetVisibility(false);}
}void AWeapon::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{ABlasterCharacter* BlasterCharacter = Cast<ABlasterCharacter>(OtherActor);if (BlasterCharacter /* && PickWidget */ ){//PickWidget->SetVisibility(true);BlasterCharacter->SetOverlappingWeapon(this);}
}void AWeapon::OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{ABlasterCharacter* BlasterCharacter = Cast<ABlasterCharacter>(OtherActor);if (BlasterCharacter /* && PickWidget */){//PickWidget->SetVisibility(true);BlasterCharacter->SetOverlappingWeapon(nullptr);}
}void AWeapon::OnRep_WeaponState()
{switch (WeaponState){case EWeaponState::EWS_Equipped:ShowPickupWidget(false);//AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);break;}
}void AWeapon::SetWeaponState(EWeaponState state)
{WeaponState = state;switch (WeaponState){case EWeaponState::EWS_Equipped:ShowPickupWidget(false);AreaSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);break;}}// Called every frame
void AWeapon::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}

        六、当前的问题

        可能会有测试游戏时在服务器上人物与武器重叠时会有提示框不会在客户端显示,重新测试当客户端与武器重叠时当前客户端和服务器上都会有提示,这是因为在重叠时武器的状态会改变,之前在人物的C++类中定义的武器的变量存在服务器一份客户端一份,客户端的武器变量改变时服务器也会发生改变,可以在人物C++中加判断

        七、人物C++类代码

        1.说明

        在头文件中添加了武器类的指针和当状态改变时的回调函数同时重写GetLifetimeReplicatedProps函数指定复制变量的类和复制的变量,同时设置了指定的条件

        2.ReplicatedUsing = OnReq_XX:作用是绑定了OnReq_XX回调函数,在当前变量改变时调用,也说明当前变量是一个可复制的变量

        3.DOREPLIFETIME_CONDITION的作用是:/** 指定了具有复制变量的类 和 复制的变量是哪个 , 复制的条件是什么  */DOREPLIFETIME_CONDITION(ABlasterCharacter, OverLappingWeapon, COND_OwnerOnly);若是DOREPLIFETIME宏则只有(ABlasterCharacter, OverLappingWeapon)两个参数可能会在客户端与武器重叠时,服务器上也会有相同的显示

/** 要标记要复制的内容,我们使用 UPROPERTY 中的 Replicated 说明符。 
在将某个内容标记为 Replicated 之后,我们必须定义一个名为 GetLifetimeReplicatedProps 的新函数 */
/** 返回用于网络复制的属性,这需要被所有具有本机复制属性的 actor 类覆盖 */
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;/** 属性设置为变量可重复 */
//UPROPERTY(Replicated)
/** 使用复制指定复制函数,通知OnRep_OverLappingWeapon调用 */
UPROPERTY(ReplicatedUsing = OnRep_OverLappingWeapon)
class AWeapon* OverLappingWeapon;UFUNCTION()
void OnRep_OverLappingWeapon(AWeapon* LastWeapon);
void ABlasterCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{Super::GetLifetimeReplicatedProps(OutLifetimeProps);/** 指定了具有复制变量的类 和 复制的变量是哪个  */DOREPLIFETIME_CONDITION(ABlasterCharacter, OverLappingWeapon, COND_OwnerOnly);
}void ABlasterCharacter::OnRep_OverLappingWeapon(AWeapon* LastWeapon)
{if (OverLappingWeapon){OverLappingWeapon->ShowPickupWidget(true);}if (LastWeapon){LastWeapon->ShowPickupWidget(false);}
}

 

        xxx.h 

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "BlasterCharacter.generated.h"UCLASS()
class BLASTER_API ABlasterCharacter : public ACharacter
{GENERATED_BODY()public:// Sets default values for this character's propertiesABlasterCharacter();	// Called every framevirtual void Tick(float DeltaTime) override;// Called to bind functionality to inputvirtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;/** 要标记要复制的内容,我们使用 UPROPERTY 中的 Replicated 说明符。 在将某个内容标记为 Replicated 之后,我们必须定义一个名为 GetLifetimeReplicatedProps 的新函数 *//** 返回用于网络复制的属性,这需要被所有具有本机复制属性的 actor 类覆盖 */virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;/* 人物移动函数 */void MoveForward(float Value);void MoveRight(float Value);void Turn(float Value);void LookUp(float Value);private:/** 弹簧臂组件类声明 属性设置为在任何地方可视 类别是摄像机 */UPROPERTY(VisibleAnywhere, Category = Camera)class USpringArmComponent* CameraBoom;/** 摄像机类声明 属性设置为在任何地方可视 类别是摄像机 */UPROPERTY(VisibleAnywhere, Category = Camera)class UCameraComponent* FollowCamera;UPROPERTY(EditAnywhere,BlueprintReadOnly,meta = (AllowPrivateAccess = "true"))class UWidgetComponent* OverheadWidget;/** 属性设置为变量可重复 *///UPROPERTY(Replicated)/** 使用复制指定复制函数,通知OnRep_OverLappingWeapon调用 */UPROPERTY(ReplicatedUsing = OnRep_OverLappingWeapon)class AWeapon* OverLappingWeapon;UFUNCTION()void OnRep_OverLappingWeapon(AWeapon* LastWeapon);public:	//FORCEINLINE void SetOverlappingWeapon(AWeapon* Weapon) { OverLappingWeapon = Weapon; };void SetOverlappingWeapon(AWeapon* Weapon);
};

        xxx.cpp

// Fill out your copyright notice in the Description page of Project Settings.#include "BlasterCharacter.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "Components/WidgetComponent.h"
#include "Net/UnrealNetwork.h"
#include "Blaster/Weapon/Weapon.h"
#include "Blaster/BlasterComponents/CombatComponent.h"// Sets default values
ABlasterCharacter::ABlasterCharacter()
{// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.PrimaryActorTick.bCanEverTick = true;CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));/** 创建类 */CameraBoom->SetupAttachment(GetMesh());/** SetupAttachment()将弹簧臂固定在网格上 GetMesh()获得角色的网格(胶囊体) */CameraBoom->TargetArmLength = 600.f;/** 设置臂长 */CameraBoom->bUsePawnControlRotation = true;/** 是否控制旋转 */FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));/** 设置附件 将摄像机连接到弹簧臂上,通过USpringArmComponent的指针和USpringArmComponent的名字USpringArmComponent::SocketName*/FollowCamera->SetupAttachment(CameraBoom,USpringArmComponent::SocketName);/** 跟随摄像头无需使用旋转 旋转在CameraBoom  CameraBoom是FollowCamera的组件 */FollowCamera->bUsePawnControlRotation = false;bUseControllerRotationYaw = false; /** 不希望角色和控制器一起旋转 */GetCharacterMovement()->bOrientRotationToMovement = true; /** 使角色按照原有的方向运动 */OverheadWidget = CreateDefaultSubobject<UWidgetComponent>(TEXT("OverheadWidget"));OverheadWidget->SetupAttachment(RootComponent);
}// Called every frame
void ABlasterCharacter::Tick(float DeltaTime)
{Super::Tick(DeltaTime);//if (OverLappingWeapon)//{//	OverLappingWeapon->ShowPickupWidget(true);//}
}// Called to bind functionality to input
void ABlasterCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);/* 绑定动作映射 */PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);/* 具有一个输入的事件IE_Pressed *//* 绑定轴映射 */PlayerInputComponent->BindAxis("MoveForward",this,&ABlasterCharacter::MoveForward);PlayerInputComponent->BindAxis("MoveRight", this, &ABlasterCharacter::MoveRight);PlayerInputComponent->BindAxis("Turn", this, &ABlasterCharacter::Turn);PlayerInputComponent->BindAxis("LookUp", this, &ABlasterCharacter::LookUp);
}void ABlasterCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{Super::GetLifetimeReplicatedProps(OutLifetimeProps);/** 指定了具有复制变量的类 和 复制的变量是哪个  */DOREPLIFETIME_CONDITION(ABlasterCharacter, OverLappingWeapon, COND_OwnerOnly);
}// Called when the game starts or when spawned
void ABlasterCharacter::BeginPlay()
{Super::BeginPlay();}void ABlasterCharacter::MoveForward(float Value)
{/* Controller理解成一个人物的控制器 */if (Controller != nullptr && Value != 0.f){/* 获得旋转方向 */const FRotator YawRotation(0.f, Controller->GetControlRotation().Yaw, 0.f);/* 从旋转方向创建旋转矩阵FRotationMatrix(YawRotation) 称其为单位轴GetUnitAxis(EAxis::X),返回一个F向量 */const FVector Direction(FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X));/*沿给定世界方向向量(通常归一化)添加运动输入,按 'ScaleValue' 缩放。如果 ScaleValue < 0,则移动方向相反。Base Pawn 类不会自动应用移动,在 Tick 事件中,这取决于用户是否这样做。Character 和 DefaultPawn 等子类会自动处理此输入并移动*/AddMovementInput(Direction, Value);}
}void ABlasterCharacter::MoveRight(float Value)
{if (Controller != nullptr && Value != 0.f){const FRotator YawRotation(0.f, Controller->GetControlRotation().Yaw, 0.f);const FVector Direction(FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y));/*沿给定世界方向向量(通常归一化)添加运动输入,按 'ScaleValue' 缩放。如果 ScaleValue < 0,则移动方向相反。Base Pawn 类不会自动应用移动,在 Tick 事件中,这取决于用户是否这样做。Character 和 DefaultPawn 等子类会自动处理此输入并移动*/AddMovementInput(Direction, Value);}
}void ABlasterCharacter::Turn(float Value)
{/*如果是本地 PlayerController,则将输入(影响 Yaw)添加到控制器的 ControlRotation。此值乘以 PlayerController 的 InputYawScale 值。*/AddControllerYawInput(Value);
}void ABlasterCharacter::LookUp(float Value)
{/*如果它是本地 PlayerController,则将输入(影响 Pitch)添加到控制器的 ControlRotation。此值乘以 PlayerController 的 InputPitchScale 值*/AddControllerPitchInput(Value);
}void ABlasterCharacter::OnRep_OverLappingWeapon(AWeapon* LastWeapon)
{if (OverLappingWeapon){OverLappingWeapon->ShowPickupWidget(true);}if (LastWeapon){LastWeapon->ShowPickupWidget(false);}
}void ABlasterCharacter::SetOverlappingWeapon(AWeapon* Weapon)
{if (OverLappingWeapon){OverLappingWeapon->ShowPickupWidget(false);}OverLappingWeapon = Weapon;if (IsLocallyControlled()){if (OverLappingWeapon){OverLappingWeapon->ShowPickupWidget(true);}}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【人工智能】Transformers之Pipeline(十):视频分类(video-classification)
  • C语言常用的数据结构
  • Python | Leetcode Python题解之第331题验证二叉树的前序序列化
  • PPPoE基础笔记
  • String 事务
  • 大模型面试系列-大模型算法工程师的面试题目与解答技巧详细说明
  • 安美数字酒店宽带运营系统 weather.php 任意文件读取漏洞复现
  • redis面试(十五)公平锁队列重排
  • 封装clickHouse线程池与ibeetl解析SQL并对结果转进行转化
  • 监控电脑屏幕被拍照的原理是什么?如此有趣的电脑防偷窥知识,你一学就会!
  • MAC 终端上传文件到云服务器
  • 【银河麒麟高级服务器操作系统】libtirpc-devel 安装问题分析
  • 英国与日本经济数据影响市场走势
  • allegro PCB设计心得笔记(四) -- 显示坐标原点和更改默认产品选项
  • 计算机网络——运输层(进程之间的通信、运输层端口,UDP与TCP、TCP详解)
  • CSS3 变换
  • ES6语法详解(一)
  • HTTP中GET与POST的区别 99%的错误认识
  • Java,console输出实时的转向GUI textbox
  • JavaScript服务器推送技术之 WebSocket
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • TypeScript迭代器
  • 基于游标的分页接口实现
  • 简单数学运算程序(不定期更新)
  • 前端面试总结(at, md)
  • 什么是Javascript函数节流?
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 用简单代码看卷积组块发展
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 组复制官方翻译九、Group Replication Technical Details
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​如何使用QGIS制作三维建筑
  • # 利刃出鞘_Tomcat 核心原理解析(八)-- Tomcat 集群
  • #if等命令的学习
  • (0)Nginx 功能特性
  • (C语言)逆序输出字符串
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (备份) esp32 GPIO
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (一)appium-desktop定位元素原理
  • (转)Linq学习笔记
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • ./configure、make、make install 命令
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .gitignore文件—git忽略文件
  • .htaccess 强制https 单独排除某个目录
  • .NET 设计一套高性能的弱事件机制
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .Net多线程总结
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • @Bean, @Component, @Configuration简析