NT-2.2|网络权威
大约 7 分钟
书接上文
问题
void AExorcistHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
InitAbilityActorInfo();
InitAbilities();
}
void AExorcistHeroCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
InitAbilityActorInfo();
}
void AExorcistHeroCharacter::InitAbilityActorInfo()
{
AExorcistPlayerState* ExorcistPlayerState =GetPlayerState<AExorcistPlayerState>();
if(!ExorcistPlayerState)
{
return;
}
//利用PlayerState初始化组件
ExorcistPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(ExorcistPlayerState, this);
//赋值指针
AbilitySystemComponent = ExorcistPlayerState->GetAbilitySystemComponent();
AttributeSet = ExorcistPlayerState->GetAttributeSet();
UUIManagerSubsystem * UIManagerSubsystem = UGameplayStatics::GetGameInstance(this)->GetSubsystem<UUIManagerSubsystem>();
if(UIManagerSubsystem)
{
UIManagerSubsystem->ExecuteBindAttributeInfo(AbilitySystemComponent);
}
}
预热
Lyra的UI框架
PossessedBy
一切从PlayerJoin后的PossessedBy开始说起
/**
* Called when this Pawn is possessed. Only called on the server (or in standalone).
* @param NewController The controller possessing this pawn
*/
virtual void PossessedBy(AController* NewController);
AIController
推荐用IDE直接打断点,不过这种方法也不是不可取。
void AExorcistHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
UE_LOG(LogTemp, Warning, TEXT("PossessedBy %d"), count);
InitAbilityActorInfo();
}
InitAbilityActorInfo()中写了计数函数主要负责++处理,以及获取玩家PlayerState
PlayerState
OnRep_PlayerState
void AExorcistHeroCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
UE_LOG(LogTemp, Warning, TEXT("OnRep_PlayerState %d"), count);
InitAbilityActorInfo();
}
UPROPERTY(EditAnywhere,BlueprintReadWrite)
int32 count = 0
强化认知
RunOnServer
- 先去掉OnRep_PlayerState回调函数,并在子系统中加入一个测试函数。
void AExorcistHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
InitAbilityActorInfo();
}
void AExorcistHeroCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
//InitAbilityActorInfo();
}
void AExorcistHeroCharacter::InitAbilityActorInfo()
{
AExorcistPlayerState* ExorcistPlayerState =GetPlayerState<AExorcistPlayerState>();
if(!ExorcistPlayerState)
{
return;
}
//利用PlayerState初始化组件
ExorcistPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(ExorcistPlayerState, this);
//赋值指针
AbilitySystemComponent = ExorcistPlayerState->GetAbilitySystemComponent();
AttributeSet = ExorcistPlayerState->GetAttributeSet();
UUIManagerSubsystem * UIManagerSubsystem = UGameplayStatics::GetGameInstance(this)->GetSubsystem<UUIManagerSubsystem>();
if(UIManagerSubsystem)
{
UIManagerSubsystem->SetTest();
}
}
//子系统
public:
UPROPERTY(VisibleAnywhere,BlueprintReadWrite)
int32 count = 0;
UFUNCTION(BlueprintCallable, Category = "UIManagerSubsystem")
void SetTest();
- 打开UE,监听服务器模式,玩家设置为2.
UFUNCTION(BlueprintCallable, Category = "UIManagerSubsystem")
void SetTest(APlayerController * LocalPlayerController);
UPROPERTY(VisibleAnywhere,BlueprintReadWrite)
TArray<APlayerController*> PlayerControllers;
void UUIManagerSubsystem::Kill()
{
PlayerControllers[1]->UnPossess();
}
OnRep_PlayerState
void AExorcistHeroCharacter::PossessedBy(AController* NewController)
{
Super::PossessedBy(NewController);
InitAbilityActorInfo();
}
void AExorcistHeroCharacter::OnRep_PlayerState()
{
Super::OnRep_PlayerState();
InitAbilityActorInfo();
}
void AExorcistHeroCharacter::InitAbilityActorInfo()
{
AExorcistPlayerState* ExorcistPlayerState =GetPlayerState<AExorcistPlayerState>();
if(!ExorcistPlayerState)
{
return;
}
//利用PlayerState初始化组件
ExorcistPlayerState->GetAbilitySystemComponent()->InitAbilityActorInfo(ExorcistPlayerState, this);
//赋值指针
AbilitySystemComponent = ExorcistPlayerState->GetAbilitySystemComponent();
AttributeSet = ExorcistPlayerState->GetAttributeSet();
if(IsLocallyControlled())
{
UUIManagerSubsystem * UIManagerSubsystem = UGameplayStatics::GetGameInstance(this)->GetSubsystem<UUIManagerSubsystem>();
if(UIManagerSubsystem)
{
//UI绑定函数
}
}
}
- 服务器上PossessedByA
- 服务器上执行InitAbilityActorInfo初始化A的ASC组件
- 看到IsLocallyControlled =true ,所以调用子系统UIManagerSubsystem绑定对应的AS委托
- 接着join New Player B
- 服务器上PossessedByB
- 服务器上执行InitAbilityActorInfo初始化B的ASC组件
- 服务器上B看到IsLocallyControlled为False,所以没有执行子系统绑定
- PossessedByB导致PlayerState变量更新,通过OnRep_PlayerState告诉对应的客户端。
- 对于客户端B来说OnRep_PlayerState的通知函数告诉他执行InitAbilityActorInfo, 此时他看到IsLocallyControlled = true, 所以成功调用了子系统将ASC的数据委托绑定到了本地的UI上。
UUIManagerSubsystem * UIManagerSubsystem = UGameplayStatics::GetGameInstance(this)->GetSubsystem<UUIManagerSubsystem>();
if(UIManagerSubsystem && IsLocallyControlled())
{
UIManagerSubsystem->InitAsc(AbilitySystemComponent);
UIManagerSubsystem->BindAttributeInfo();
UIManagerSubsystem->NotifyUIShowAttributeInfo();
}
void UUIManagerSubsystem::InitAsc(
UAbilitySystemComponent* TargetASC)
{
if (!TargetASC) return;
AbilitySystemComponent = TargetASC;
}
void UUIManagerSubsystem::BindAttributeInfo()
{
if (!AbilitySystemComponent) return;
AbilitySystemComponent->GetAllAttributes(OutAttributes);
if (OutAttributes.Num() > 0)
{
for (auto const Attribute : OutAttributes)
{
GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Red, Attribute.GetName());
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(Attribute).AddLambda(
[this](const FOnAttributeChangeData& OnAttributeChangeData)
{
OnAttributeChanged.Broadcast(OnAttributeChangeData.Attribute, OnAttributeChangeData.NewValue);
}
);
}
}
}
void UUIManagerSubsystem::NotifyUIShowAttributeInfo()
{
if (OutAttributes.Num() > 0 && AbilitySystemComponent)
{
for (auto Attribute : OutAttributes)
{
OnAttributeChanged.Broadcast(Attribute, AbilitySystemComponent->GetNumericAttributeBase(Attribute));
}
}
}