Ability System Component(ASC)

Ability System Component

AbilitySystemComponent(ASC)是GAS的核心,这个组件用于处理与GAS系统的交互,所有使用GameplayAbililty,包含Attribute,接收GameplayEffect的Actor都应该附加与ASC,由ASC来管理并同步这些对象。

ASC附加的Actor可以作为ASC的OwnerActor,ASC的物理代表Actor可以称为AvatarActor(我这里理解为这个Actor的包含具体的模型)。OwnerActor和AvatarActor可以是同一个Actor,比如MOBA中游戏的小兵,也可以是不同的Actor,比如MOBA中玩家控制的英雄(玩家可以选择不同的英雄,因此AvatarActor会不断变化)。在MOBA游戏中玩家的ASC,OwnerActor是PlayerState,AvatarActor则是英雄的Character类,如果Actor需要重生,并且重生需要持续Attribute的效果或者GamplayEffect的效果,那么OwnerActor的位置应该选取PlayerState。

**NOTE:**如果选取PlayerState作为OwnerActor,我们需要注意提高PlayerState的NetUpdateFrequency,其默认值很低,因此客户端改变时会有延迟和卡顿,需要启用Adaptive Network Update Frequency。

OwnerActor需要继承并实现IAbilitySystemInterface,如果AvatarActor和OwnerActor不是相同的Actor,那么AvatarActor也应该继承实现IAbilitySystemInterface,这个接口有一个必须重写的函数UAbilitySystemComponent* GetAbilitySystemComponent() const,其返回一个指向ASC的指针,ASC通过该借口函数与GAS系统内部进行交互。

ASCFGameplayAbilitySpecContainer ActivatableAbility中保存GameplayAbility. 当你想遍历ActivatableAbility.Items时, 确保在循环体之上添加ABILITYLIST_SCOPE_LOCK();来锁定列表以防其改变(比如移除一个Ability). 每个域中的ABILITYLIST_SCOPE_LOCK();会增加AbilityScopeLockCount, 之后出域时会减量. 不要尝试在ABILITYLIST_SCOPE_LOCK();域中移除某个Ability(Ability删除函数会在内部检查AbilityScopeLockCount以防在列表锁定时移除Ability).

同步模式

ASC定义了三种不同的同步模式用于同步GameplayEffect, GameplayTagGameplayCue - Full, MixedMinimal. Attribute由其AttributeSet同步.

同步模式何时使用描述
Full单人所有GameplayEffect都同步到客户端.
Mixed多人, 玩家控制的ActorGameplayEffect只同步到其所属客户端, 只有GameplayTagGameplayCue同步到所有客户端.
Minimal多人, AI控制的ActorGameplayEffect从不同步到任何客户端, 只有GameplayTagGameplayCue同步到所有客户端.

设置和初始化

ASC一般在OwnerActor的构造函数中创建,并且声明为Replicated(多人游戏中),在代码中,玩家控制的角色的ASC我们存放于PlayerState中,因此代码如下:

AFusePlayerState::AFusePlayerState()
{
	//ASC初始化
	FuseAbilitySystemComponent = CreateDefaultSubobject<UFuseAbilitySystemComponent>(TEXT("FuseAbilitySystemComponent"));
	FuseAbilitySystemComponent->SetIsReplicated(true);
	
}

ASC不仅需要在OwnerActor进行初始化,还需要在AvatarActor中进行初始化,并且在多人游戏中,不仅在服务器上进行初始化,我们还需要在所有客户端同样进行初始化。

假如ASC的OwnerAcrtor与AvatarActor相同,都是 Pawn中,那么服务器的初始化应该放在PawnPossessBy()函数中,而客户端则是应该在PlayerControllerAcknowledgePossession()中初始化,代码如下:

//服务器更新
void AFuseCharacterBase::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);

	AFusePlayerState* PlayerState = GetPlayerState<AFusePlayerState>();
	if (FuseAbilitySystemComponent)
	{
		FuseAbilitySystemComponent->InitAbilityActorInfo(this, this);
	}
    SetOwner(NewController);
}

//客户端更新
void APAPlayerControllerBase::AcknowledgePossession(APawn* P)
{
	Super::AcknowledgePossession(P);

	APACharacterBase* CharacterBase = Cast<APACharacterBase>(P);
	if (CharacterBase)
	{
		CharacterBase->GetAbilitySystemComponent()->InitAbilityActorInfo(CharacterBase, CharacterBase);
	}
	//...
}

而如果OwnerActor是PlayerState,AvatarActor是Character,那么服务器初始化应该在Pawn的PossessdBy()函数,而客户端则是应该在Character的OnRep_PlayerState()函数中初始化。

//由于ASC是存在于PlayerState的,因此我们需要从PlayerState获取ASC,服务端执行
void AFuseCharacterBase::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);

	AFusePlayerState* PlayerState = GetPlayerState<AFusePlayerState>();
	if (PlayerState)
	{
		FuseAbilitySystemComponent = Cast<UFuseAbilitySystemComponent>(PlayerState->GetAbilitySystemComponent());
		PlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(PlayerState, this);
		UE_LOG(LogTemp, Log, TEXT("Server: ASC Init Compeleted!"));
	}
}
void AFuseCharacterBase::OnRep_PlayerState()
{
	Super::OnRep_PlayerState();
	
	AFusePlayerState* PlayerState = GetPlayerState<AFusePlayerState>();
	if (PlayerState)
	{
		FuseAbilitySystemComponent = Cast<UFuseAbilitySystemComponent>(PlayerState->GetAbilitySystemComponent());
		PlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(PlayerState, this);
		UE_LOG(LogTemp, Log, TEXT("Client: ASC Init Compeleted!"));
	}
}

在游戏界面中,我们需要使用蓝图重载GameMode和PlayerState,并在游戏地图中设置重载的GameMode,然后使用聆听服务器开启两个客户端。

结果如下:
在这里插入图片描述
可以看到初始化在服务器进行了一次,在客户端进行了两次,由于是聆听服务器,服务器上开始的客户端还会再初始化一次。因此ASC在多人游戏下能够正常初始化。
在这里插入图片描述
角色没有设置摄像机和弹簧臂,所以视角很奇怪= =。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值