1.上一节,武器加载后,发现只能在单机游戏里生效,显然不是我想要的.
准备在网络游戏里也生效:
创建角色基类的子类:敌人类:WarriorEnemyCharacter
2.将GAS和属性集在英雄角色/敌人角色创建:
Source/Warrior/Private/Characters/WarriorHeroCharacter.cpp:
/*构造函数,初始化属性*/
AWarriorHeroCharacter::AWarriorHeroCharacter()
{
/*胶囊体组件*/
GetCapsuleComponent()->InitCapsuleSize(42.f, 92.f); //初始化胶囊体半径、半高
bUseControllerRotationPitch = false; //是否使用控制器的旋转俯仰
bUseControllerRotationYaw = false; //是否使用控制器的旋转偏移
bUseControllerRotationRoll = false; //是否使用控制器的旋转翻滚
/*弹簧臂组件*/
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(GetRootComponent()); //设置父级(根组件)
CameraBoom->TargetArmLength = 200.f; //设置臂长
CameraBoom->SocketOffset = FVector(0.f, 55.f, 65.f); //插槽偏移
CameraBoom->bUsePawnControlRotation = true; //使用棋子控制旋转
/*相机组件*/
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); //设置父级(弹簧臂插槽名称)
FollowCamera->bUsePawnControlRotation = false;
/*角色移动组件*/
GetCharacterMovement()->bOrientRotationToMovement = true; //保持旋转到位移方向
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f); //旋转速度(转身速度)
GetCharacterMovement()->MaxWalkSpeed = 400.f; //最大位移速度
GetCharacterMovement()->BrakingDecelerationWalking = 200.f; //行走加速度
//将能力系统组件添加到角色
WarriorAbilitySystemComponent = CreateDefaultSubobject<UWarriorAbilitySystemComponent>(TEXT("WarriorAbilitySystemComponent"));
//将属性集添加到角色
WarriorAttributeSet = CreateDefaultSubobject<UWarriorAttributeSet>(TEXT("WarriorAttributeSet"));
}
Source/Warrior/Private/Characters/WarriorEnemyCharacter.cpp:
AWarriorEnemyCharacter::AWarriorEnemyCharacter()
{
//将能力系统组件添加到角色
WarriorAbilitySystemComponent = CreateDefaultSubobject<UWarriorAbilitySystemComponent>(TEXT("WarriorAbilitySystemComponent"));
//将属性集添加到角色
WarriorAttributeSet = CreateDefaultSubobject<UWarriorAttributeSet>(TEXT("WarriorAttributeSet"));
}
3.GAS的复制模式
(1)英雄类采用混合模式:
WarriorAbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed); //复制模式
Source/Warrior/Private/Characters/WarriorHeroCharacter.cpp:
// Copyright @ ChenChao
#include "Characters/WarriorHeroCharacter.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "EnhancedInputSubsystems.h"
#include "DataAssets/Input/WarriorDataAssetInputConfig.h"
#include "Components/Input/WarriorInputComponent.h"
#include "WarriorDebugHelper.h"
#include "WarriorGameplayTags.h"
#include "AbilitySystem/WarriorAbilitySystemComponent.h"
#include "AbilitySystem/WarriorAttributeSet.h"
#include "DataAssets/StartUp/DataAsset_StartUpDataBase.h"
/*构造函数,初始化属性*/
AWarriorHeroCharacter::AWarriorHeroCharacter()
{
/*胶囊体组件*/
GetCapsuleComponent()->InitCapsuleSize(42.f, 92.f); //初始化胶囊体半径、半高
bUseControllerRotationPitch = false; //是否使用控制器的旋转俯仰
bUseControllerRotationYaw = false; //是否使用控制器的旋转偏移
bUseControllerRotationRoll = false; //是否使用控制器的旋转翻滚
/*弹簧臂组件*/
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(GetRootComponent()); //设置父级(根组件)
CameraBoom->TargetArmLength = 200.f; //设置臂长
CameraBoom->SocketOffset = FVector(0.f, 55.f, 65.f); //插槽偏移
CameraBoom->bUsePawnControlRotation = true; //使用棋子控制旋转
/*相机组件*/
FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); //设置父级(弹簧臂插槽名称)
FollowCamera->bUsePawnControlRotation = false;
/*角色移动组件*/
GetCharacterMovement()->bOrientRotationToMovement = true; //保持旋转到位移方向
GetCharacterMovement()->RotationRate = FRotator(0.f, 500.f, 0.f); //旋转速度(转身速度)
GetCharacterMovement()->MaxWalkSpeed = 400.f; //最大位移速度
GetCharacterMovement()->BrakingDecelerationWalking = 200.f; //行走加速度
//将能力系统组件添加到角色
WarriorAbilitySystemComponent = CreateDefaultSubobject<UWarriorAbilitySystemComponent>(TEXT("WarriorAbilitySystemComponent"));
WarriorAbilitySystemComponent->SetIsReplicated(true);
WarriorAbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Mixed); //复制模式
//将属性集添加到角色
WarriorAttributeSet = CreateDefaultSubobject<UWarriorAttributeSet>(TEXT("WarriorAttributeSet"));
}
//当Controller(玩家或AI)获得该Pawn控制权时触发
void AWarriorHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (CharacterStartUpData.IsNull()) return;
UDataAsset_StartUpDataBase* LoadedData = CharacterStartUpData.LoadSynchronous();
if (LoadedData == nullptr) return;
LoadedData->GiveToAbilitySystemComponent(WarriorAbilitySystemComponent);
}
//设置玩家输入组件
void AWarriorHeroCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
checkf(DataAssetInputConfig,TEXT("DataAssetInputConfig 指针为空!"));
// 获取本地玩家
class ULocalPlayer* LocalPlayer = GetController<APlayerController>()->GetLocalPlayer();
check(LocalPlayer);
// 获取增强输入本地玩家子系统
UEnhancedInputLocalPlayerSubsystem* Subsystem = ULocalPlayer::GetSubsystem<UEnhancedInputLocalPlayerSubsystem>(LocalPlayer);
check(Subsystem);
//添加映射上下文
Subsystem->AddMappingContext(DataAssetInputConfig->DefaultMappingContext, 0);
//获取战士输入组件
UWarriorInputComponent* WarriorInputComponent = CastChecked<UWarriorInputComponent>(PlayerInputComponent);
// 绑定回调函数
WarriorInputComponent->BindNativeInputAction(DataAssetInputConfig, WarriorGameplayTags::InputTag_Move, ETriggerEvent::Triggered, this, &AWarriorHeroCharacter::Input_Move);
WarriorInputComponent->BindNativeInputAction(DataAssetInputConfig, WarriorGameplayTags::InputTag_Look, ETriggerEvent::Triggered, this, &AWarriorHeroCharacter::Input_Look);
}
void AWarriorHeroCharacter::BeginPlay()
{
Super::BeginPlay();
}
//回调函数: 移动输入
void AWarriorHeroCharacter::Input_Move(const FInputActionValue& InputActionValue)
{
//获取移动二维向量
const FVector2D MovementVector = InputActionValue.Get<FVector2D>();
// 获取移动旋转
const FRotator MovementRotator(0.f, GetControlRotation().Yaw, 0.0f);
//设置前进
if (MovementVector.Y != 0.f)
{
//前进方向
const FVector ForwardDirection = MovementRotator.RotateVector(FVector::ForwardVector);
//添加移动输入
AddMovementInput(ForwardDirection, MovementVector.Y);
}
//设置向右
if (MovementVector.X != 0.f)
{
//向右方向
const FVector RightDirection = MovementRotator.RotateVector(FVector::RightVector);
AddMovementInput(RightDirection, MovementVector.X);
}
}
//回调函数: 视角输入
void AWarriorHeroCharacter::Input_Look(const FInputActionValue& InputActionValue)
{
//获取鼠标轴二维向量
const FVector2D LookAxisVector = InputActionValue.Get<FVector2D>();
//左右看
if (LookAxisVector.X != 0.f)
{
AddControllerYawInput(LookAxisVector.X);
}
// 上下看
if (LookAxisVector.Y != 0.f)
{
AddControllerPitchInput(LookAxisVector.Y);
}
}
(2) 敌人类采用最小模式:
WarriorAbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal); //复制模式
Source/Warrior/Private/Characters/WarriorEnemyCharacter.cpp:
// Copyright @ ChenChao
#include "Characters/WarriorEnemyCharacter.h"
#include "AbilitySystem/WarriorAbilitySystemComponent.h"
#include "AbilitySystem/WarriorAttributeSet.h"
AWarriorEnemyCharacter::AWarriorEnemyCharacter()
{
//将能力系统组件添加到角色
WarriorAbilitySystemComponent = CreateDefaultSubobject<UWarriorAbilitySystemComponent>(TEXT("WarriorAbilitySystemComponent"));
WarriorAbilitySystemComponent->SetIsReplicated(true);
WarriorAbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal); //复制模式
//将属性集添加到角色
WarriorAttributeSet = CreateDefaultSubobject<UWarriorAttributeSet>(TEXT("WarriorAttributeSet"));
}
4.初始化GAS的能力演员信息
我们什么时候初始化呢?
玩家角色:
- ASC在角色上,在PossessedBy()和AcknowledgePossession()调用;
- ASC在状态类上构造时,在PossessedBy()和OnRep_PlayerState()上调用.
敌人角色:
- 在BeginPlay()调用
(1)为敌人类初始化演员能力信息:
void AWarriorEnemyCharacter::BeginPlay()
{
Super::BeginPlay();
WarriorAbilitySystemComponent->InitAbilityActorInfo(this,this);
}
(2)为玩家类初始化演员能力信息:
Source/Warrior/Public/Characters/WarriorHeroCharacter.h:
//~Begin Apawn Interface.
virtual void PossessedBy(AController* NewController) override; //当Controller(玩家或AI)获得该Pawn控制权时触发
//~ End APawn Interface
Source/Warrior/Private/Characters/WarriorHeroCharacter.cpp:
//当Controller(玩家或AI)获得该Pawn控制权时触发
void AWarriorHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
if (WarriorAbilitySystemComponent == nullptr) return;
WarriorAbilitySystemComponent->InitAbilityActorInfo(this, this);
if (CharacterStartUpData.IsNull()) return;
UDataAsset_StartUpDataBase* LoadedData = CharacterStartUpData.LoadSynchronous();
if (LoadedData == nullptr) return;
LoadedData->GiveToAbilitySystemComponent(WarriorAbilitySystemComponent);
}
Source/Warrior/Public/Controllers/WarriorHeroController.h:
public:
//~Begin PlayerController Interface.
virtual void AcknowledgePossession(class APawn* P) override;
//~ End PlayerController Interface
Source/Warrior/Private/Controllers/WarriorHeroController.cpp:
void AWarriorHeroController::AcknowledgePossession(class APawn* P)
{
Super::AcknowledgePossession(P);
AWarriorHeroCharacter* WarriorHeroCharacter = Cast<AWarriorHeroCharacter>(P);
if (WarriorHeroCharacter) return;
UWarriorAbilitySystemComponent* WarriorAbilitySystemComponent = WarriorHeroCharacter->GetWarriorAbilitySystemComponent();
if (WarriorAbilitySystemComponent == nullptr) return;
WarriorAbilitySystemComponent->InitAbilityActorInfo(this, this);
}
AcknowledgePossession
是Unreal Engine中用于处理角色控制权确认的重要函数,通常在网络游戏开发中与GameplayAbilitySystem(GAS)配合使用。该函数的主要功能是:
- 服务器-客户端同步:当服务器将Pawn的控制权授予客户端时,客户端通过此函数确认接收
- GAS初始化关键点:必须在函数内调用
InitAbilityActorInfo
来初始化GAS相关的Actor信息,否则会导致能力系统无法正常工作 - 调用位置:通常在
PossessedBy
(服务器端)和AcknowledgePossession
(客户端)两个地方成对实现
在专用服务器架构中,该函数对确保客户端和服务器端的GAS组件同步至关重要。若未正确实现,可能导致网络游戏中能力激活失败或属性同步异常等问题。
后续不会了,再学习一下