TeamSystem框架
基本架构
支持基本的加入、退出 队伍,以及维护队伍的基本数据(TeamID
、 MemberUIDs
)
提供继承扩展,维护自定义业务逻辑与队伍数据;
对于挂载组件:由 Manager
级别的 TeamManager
,与 Player
身上的 TeamComponent
组成;
以及队伍数据同步,自定义不同方式的数据同步;
classDiagram
UTeamManager..>UTeamBase
UTeamManager..>UTeamSyncDataBase
class UTeamManager {
SubSystemCollections : FGameSubSystemCollection~UTeamCommonSubSystemBase~
Teams : TMap~uint64|UTeamBase*~
TeamSyncDatas : TArray~UTeamSyncDataBase*~
CreateTeam(TeamID)
DestoryTeam(TeamID)
GetTeam(TeamID)
JoinTeam(TeamID, PlayerUID)
LeaveTeam(PlayerUID)
}
UTeamComponent..>UTeamSyncDataBase
class UTeamComponent {
TeamID : uint64
SubSystemCollection : FGameSubSystemCollection~UTeamPlayerSubSystemBase~
UpdateTeamID()
CreateSyncData()
DestroySyncData()
}
class UTeamBase {
TeamID : uint64
MemberUIDs : TArray~uint64~
OnDataDirty
Init(TeamID)
Uninit()
AddMember(PlayerUID)
RemoveMember(PlayerUID)
MarkDirty()
}
class UTeamSyncDataBase {
BoundTeam : TWeakObjectPtr~UTeamBase~
TeamID : uint64
MemberUIDs : TArray~uint64~
BindTeam(InTeam)
Unbind()
OnDataDirty()
CollectSyncData(InTeam)
}
TeamManager
持有 Teams
保存队伍的原始指针,提供 CreateTeam
、DestroyTeam
方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 #pragma region Team UTeamBase* UTeamManager::GetTeam (uint64 TeamID) { return Teams.FindRef (TeamID); } const TMap<uint64, UTeamBase*>& UTeamManager::GetTeams () const { return Teams; } uint64 UTeamManager::GetHashValue (uint64 Value) { uint64 HashValue = HashCombine ( GetHashCode (), GetTypeHash (Value))); LogD (TEXT ("UTeamManager::GetHashValue, HashValue=%llu, [Value=%llu | HashCode=%llu]" ), HashValue, Value, GetHashCode ()); return HashValue; } UTeamBase* UTeamManager::GetOrCreateTeam (uint64 TeamID) { if (auto Team = GetTeam (TeamID); !IsValid (Team)) { CreateTeam (TeamID); } return GetTeam (TeamID); } UTeamBase* UTeamManager::CreateTeam (uint64 TeamID) { if (GetTeam (TeamID) != nullptr ) { LogW (TEXT ("UTeamManager::CreateTeam, Team is existed! TeamID=%llu" ), TeamID); return nullptr ; } LogD (TEXT ("UTeamManager::CreateTeam, Begin, TeamID=%llu" ), TeamID); auto TeamClass = GetTeamClass (); if (!IsValid (TeamClass) || !TeamClass->IsChildOf (UTeamBase::StaticClass ())) { LogE (TEXT ("UTeamManager::CreateTeam, TeamClass is invalid! TeamID=%llu" ), TeamID); return nullptr ; } UTeamBase* NewTeam = NewObject<UTeamBase>(this , GetTeamClass ()); if (!IsValid (NewTeam)) { LogE (TEXT ("UTeamManager::CreateTeam, NewTeam is invalid! TeamID=%llu" ), TeamID); return nullptr ; } LogD (TEXT ("UTeamManager::CreateTeam, CreateTeam, TeamID=%llu" ), TeamID); NewTeam->Init (TeamID); Teams.Add ( TeamID, NewTeam ); { auto NewTeamSyncData = UTeamUtils::CreateTeamSyncData ( this , NewTeam, GetTeamSyncDataClass () ); if (IsValid (NewTeamSyncData)) { LogD (TEXT ("UTeamManager::CreateTeam, CreateTeamSyncData, TeamID=%llu" ), TeamID); TeamSyncDatas.Add ( NewTeamSyncData ); MARK_PROPERTY_DIRTY_FROM_NAME (UTeamManager, TeamSyncDatas, this ); } } return NewTeam; } void UTeamManager::DestoryTeam (uint64 TeamID) { auto Team = GetTeam (TeamID); if (!IsValid (Team)) return ; LogD (TEXT ("UTeamManager::DestoryTeam, TeamID=%llu" ), TeamID); for (auto Iter = TeamSyncDatas.CreateIterator (); Iter; ++Iter) { auto SyncData = *Iter; if (!IsValid (SyncData) || SyncData->GetTeamID () == TeamID) { UTeamUtils::DestoryTeamSyncData (SyncData); Iter.RemoveCurrent (); } } MARK_PROPERTY_DIRTY_FROM_NAME (UTeamManager, TeamSyncDatas, this ); Team->Uninit (); Teams.Remove (TeamID); } #pragma endregion Team
提供 Player
的 JoinTeam
、LeaveTeam
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #pragma region Join/Leave void UTeamManager::JoinTeam (uint64 TeamID, uint64 PlayerUID, bool bNeedHash) { if (!IsStandaloneOrDS (this )) return ; if (TeamID == 0 ) { LogD (TEXT ("UTeamManager::JoinTeam, TeamID is 0! PlayerUID=%llu, TeamID=%llu, bNeedHash=%d" ), PlayerUID, TeamID, bNeedHash); return ; } auto TeamComponent = UTeamUtils::GetComponentByUID (GetWorld (), PlayerUID); if (!IsValid (TeamComponent)) return ; LogD (TEXT ("UTeamManager::JoinTeam, PlayerUID=%llu, TeamID=%llu, bNeedHash=%d" ), PlayerUID, TeamID, bNeedHash); if (bNeedHash) { TeamID = GetHashValue (TeamID); LogD (TEXT ("UTeamManager::JoinTeam, ProcessID, PlayerUID=%llu, HashTeamID=%llu" ), PlayerUID, TeamID); } if (auto ExistTeam = GetTeam (TeamComponent->GetTeamID ()); IsValid (ExistTeam)) { LogE (TEXT ("UTeamManager::JoinTeam, Player already exist Team! PlayerUID=%llu, ExistTeamID=%llu" ), PlayerUID, ExistTeam->GetTeamID ()); return ; } auto Team = GetOrCreateTeam (TeamID); if (!IsValid (Team)) { LogE (TEXT ("UTeamManager::JoinTeam, Team is invalid! PlayerUID=%llu, TeamID=%llu" ), PlayerUID, TeamID); return ; } LogD (TEXT ("UTeamManager::JoinTeam, Begin, PlayerUID=%llu, TeamID=%llu" ), PlayerUID, TeamID); TeamComponent->UpdateTeamID (Team->GetTeamID ()); TeamComponent->CreateSyncData (Team); Team->AddMember (PlayerUID); } void UTeamManager::LeaveTeam (uint64 PlayerUID) { if (!IsStandaloneOrDS (this )) return ; auto TeamComponent = UTeamUtils::GetComponentByUID (GetWorld (), PlayerUID); if (!IsValid (TeamComponent)) return ; auto Team = GetTeam (TeamComponent->GetTeamID ()); if (!IsValid (Team)) { LogE (TEXT ("UTeamManager::LeaveTeam, Player isn't in any team! PlayerUID=%llu" ), PlayerUID); return ; } uint64 TeamID = Team->GetTeamID (); LogD (TEXT ("UTeamManager::LeaveTeam, Begin, PlayerUID=%llu, TeamID=%llu" ), PlayerUID, TeamID); Team->RemoveMember (PlayerUID); TeamComponent->UpdateTeamID (0 ); TeamComponent->DestroySyncData (); if (Team->GetMemberUIDs ().Num () == 0 ) { DestoryTeam ( TeamID ); } } #pragma endregion Join/Leave
持有 TeamCommonSubSystem
,支持业务扩展拆分为若干个子系统,参考:[UE]GameSubSystem 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void UTeamManager::RegisterSubSystems () { if (!IsStandaloneOrDS (this )) return ; LogD (TEXT ("UTeamManager::RegisterSubSystems" )); SubSystemCollection.Init ( this , GetSubSystemClasses () ); } void UTeamManager::UnregisterSubSystems () { if (!IsStandaloneOrDS (this )) return ; LogD (TEXT ("UTeamManager::UnregisterSubSystems" )); SubSystemCollection.Uninit (); }
同步 TeamSyncDatas
,其中类型为 TeamSyncData_Common
,记录所有人都需要关心的队伍同步数据;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #pragma region Replicate void UTeamManager::OnRep_TeamSyncDatas (const TArray<UTeamSyncDataBase*>& LastTeamSyncDatas) { LogD (TEXT ("UTeamManager::OnRep_TeamSyncDatas, TeamSyncDatas=%s, LastTeamSyncDatas=%s" ), *UStringUtils::ToString (TeamSyncDatas), *UStringUtils::ToString (LastTeamSyncDatas)); } bool UTeamManager::ReplicateSubobjects (UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags) { bool WroteSomething = Super::ReplicateSubobjects (Channel, Bunch, RepFlags); if (IsValid (Channel) && RepFlags->bNetInitial == false ) { for (const auto & SyncData : TeamSyncDatas) { WroteSomething |= Channel->ReplicateSubobject ( SyncData, *Bunch, *RepFlags); } } return WroteSomething; } #pragma endregion Replicate
TeamComponent
维护 TeamID
;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #pragma region TeamID void UTeamComponent::UpdateTeamID (uint64 InTeamID) { if (InTeamID == TeamID) return ; LogD (TEXT ("UTeamComponent::UpdateTeamID, UID=%llu, TeamID=%llu" ), GetUID (), InTeamID); SetTeamID (InTeamID); OnRep_TeamID (); if (IsDS (this )) { S2C_NotifyTeamIDChanged (InTeamID); } } void UTeamComponent::S2C_NotifyTeamIDChanged_Implementation (uint64 InTeamID) { if (!IsClient (this )) return ; if (InTeamID == TeamID) return ; LogD (TEXT ("UTeamComponent::S2C_NotifyTeamIDChanged_Implementation, UID=%llu, TeamID=%llu" ), GetUID (), TeamID); SetTeamID (InTeamID); OnRep_TeamID (); } void UTeamComponent::OnRep_TeamID () { LogD (TEXT ("UTeamComponent::OnRep_TeamID, UID=%llu, TeamID=%llu" ), GetUID (), TeamID); OnPlayerTeamIDChanged.Broadcast (TeamID); UTeamDelegate::GetDelegate ()->OnPlayerTeamIDChanged.Broadcast (GetUID (), TeamID); } #pragma endregion TeamID
持有 TeamPlayerSubSystem
,支持业务扩展拆分为若干个子系统;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #pragma region SubSystem void UTeamComponent::RegisterSubSystems () { if (!IsStandaloneOrDS (this )) return ; LogD (TEXT ("UTeamComponent::RegisterSubSystems, UID=%llu" ), GetUID ()); SubSystemCollection.Init ( this , GetSubSystemClasses () ); } void UTeamComponent::UnregisterSubSystems () { if (!IsStandaloneOrDS (this )) return ; LogD (TEXT ("UTeamComponent::UnregisterSubSystems, UID=%llu" ), GetUID ()); SubSystemCollection.Uninit (); } UTeamPlayerSubSystemBase* UTeamComponent::GetSubSystem (UClass* InClass) const { if (!IsValid (InClass)) return nullptr ; return SubSystemCollection.GetSubSystem (InClass); } #pragma endregion SubSystem
同步 TeamSyncData
,其中类型为 TeamSyncData_OwnerOnly
,记录仅自己队伍成员关心的队伍同步数据;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 bool UComponentBase::ReplicateSubobjects (UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags) { bool WroteSomething = Super::ReplicateSubobjects (Channel, Bunch, RepFlags); if (IsValid (Channel) && IsValid (Channel->Connection)) { if (Channel->Connection->PlayerController == GetPlayerController ()) { WroteSomething |= ReplicateSubobjects_OwnerOnly (Channel, Bunch, RepFlags); } } return WroteSomething; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #pragma region SyncData bool UTeamComponent::ReplicateSubobjects_OwnerOnly (UActorChannel* Channel, FOutBunch* Bunch, FReplicationFlags* RepFlags) { bool WroteSomething = Super::ReplicateSubobjects_OwnerOnly (Channel, Bunch, RepFlags); WroteSomething |= SubSystemCollection.ReplicateSubSystems (Channel, Bunch, RepFlags); if (IsValid (Channel) && RepFlags->bNetInitial == false ) { WroteSomething |= Channel->ReplicateSubobject ( SyncData, *Bunch, *RepFlags); } return WroteSomething; } void UTeamComponent::CreateSyncData (UTeamBase* InTeam) { if (!IsValid (InTeam)) return ; LogD (TEXT ("UTeamComponent::CreateSyncData, UID=%llu, InTeamID=%llu, TeamID=%llu" ), GetUID (), InTeam->GetTeamID (), TeamID); auto NewSyncData = UTeamUtils::CreateTeamSyncData ( this , InTeam, GetSyncDataClass () ); if (IsValid (NewSyncData)) { SetSyncData (NewSyncData); LogD (TEXT ("UTeamComponent::CreateSyncData, UID=%llu, SyncData=%s" ), GetUID (), *SyncData->ToString ()); OnRep_SyncData (); } } void UTeamComponent::DestroySyncData () { LogD (TEXT ("UTeamComponent::DestroySyncData, UID=%llu, TeamID=%llu" ), GetUID (), TeamID); UTeamUtils::DestoryTeamSyncData (SyncData); SetSyncData ( nullptr ); } void UTeamComponent::OnRep_SyncData () { LogD (TEXT ("UTeamComponent::OnRep_SyncData, UID=%llu, SyncData=%s" ), GetUID (), *UStringUtils::ToString (SyncData)); }
Team
维护队伍信息: TeamID
、MemberUIDs
,以及可能继承的属性;
当属性变化时,进行 MarkDirty
通知 OnDataDirty
;
完整实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 #pragma region Property #define TEAM_GENERATE_PROPERTY(Visibility, Type, Name) \ Visibility: Type Name{}; \ TEAM_GENERATE_PROPERTY_FUNCTIONS_INTERNAL(Name) #define TEAM_GENERATE_PROPERTY_MARKDIRTY(Visibility, Type, Name) \ Visibility: Type Name{}; \ TEAM_GENERATE_PROPERTY_MARKDIRTY_FUNCTIONS(Name) #pragma endregion Property #pragma region Function #define TEAM_GENERATE_PROPERTY_FUNCTIONS(Name) \ TEAM_EXPAND(TEAM_GENERATE_PROPERTY_FUNCTIONS_INTERNAL(decltype(Name), Name)) #define TEAM_GENERATE_PROPERTY_FUNCTIONS_INTERNAL(Type, Name) \ public: const Type& Get##Name() const { return Name; } \ public: void Set##Name(const Type& Value) { \ Name = Value; \ } #define TEAM_GENERATE_PROPERTY_MARKDIRTY_FUNCTIONS(Name) \ TEAM_EXPAND(TEAM_GENERATE_PROPERTY_MARKDIRTY_FUNCTIONS_INTERNAL(decltype(Name), Name)) #define TEAM_GENERATE_PROPERTY_MARKDIRTY_FUNCTIONS_INTERNAL(Type, Name) \ public: const Type& Get##Name() const { return Name; } \ public: void Set##Name(const Type& Value) { \ if (Name == Value) return; \ Name = Value; \ this->MarkDirty(); \ } #pragma endregion Function
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 UCLASS (Blueprintable, BlueprintType)class UTeamBase : public UObject{ GENERATED_BODY () public : void Init (uint64 InTeamID) ; void Uninit () ; public : virtual FString ToString () const ; #pragma region Dirty public : DECLARE_MULTICAST_DELEGATE (FDataDirty) FDataDirty OnDataDirty; protected : virtual void MarkDirty () ; #pragma endregion Dirty #pragma region Member public : void AddMember (uint64 MemberUID) ; void RemoveMember (uint64 MemberUID) ; #pragma endregion Member private : TEAM_GENERATE_PROPERTY_MARKDIRTY (protected , uint64, TeamID); TEAM_GENERATE_PROPERTY_MARKDIRTY (protected , TArray<uint64>, MemberUIDs); };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 void UTeamBase::Init (uint64 InTeamID) { TeamID = InTeamID; LogD (TEXT ("UTeamBase::Init, TeamID=%llu" ), TeamID); MemberUIDs.Empty (); } void UTeamBase::Uninit () { LogD (TEXT ("UTeamBase::Uninit, TeamID=%llu" ), TeamID); } #pragma region Dirty void UTeamBase::MarkDirty () { OnDataDirty.Broadcast (); } #pragma endregion Dirty #pragma region Member void UTeamBase::AddMember (uint64 MemberUID) { if (MemberUIDs.Contains ( MemberUID )) return ; MemberUIDs.Add ( MemberUID ); LogD (TEXT ("UTeamBase::AddMember, TeamID=%llu, MemberUID=%llu, MemberUIDs=%s" ), TeamID, MemberUID, *UStringUtils::ToString (MemberUIDs)); MarkDirty (); } void UTeamBase::RemoveMember (uint64 MemberUID) { if (!MemberUIDs.Contains ( MemberUID )) return ; MemberUIDs.Remove ( MemberUID ); LogD (TEXT ("UTeamBase::RemoveMember, TeamID=%llu, MemberUID=%llu, MemberUIDs=%s" ), TeamID, MemberUID, *UStringUtils::ToString (MemberUIDs)); MarkDirty (); } #pragma endregion Member
TeamSyncData
与对应的 Team
进行绑定;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #pragma region Bind void UTeamSyncDataBase::BindTeam (UTeamBase* InTeam) { if (!IsValid (InTeam)) return ; BoundTeam = InTeam; InTeam->OnDataDirty.AddUObject (this , &ThisClass::OnDataDirty); CollectSyncData (InTeam); LogD (TEXT ("UTeamSyncDataBase::BindTeam, %s" ), *ToString ()); } void UTeamSyncDataBase::Unbind () { if (!BoundTeam.IsValid ()) return ; BoundTeam->OnDataDirty.RemoveAll (this ); LogD (TEXT ("UTeamSyncDataBase::Unbind, %s" ), *ToString ()); } #pragma endregion Bind
当 Team
进行 OnDataDirty
时,重新对 Team
进行 CollectSyncData
收集并设置同步数据;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #pragma region CollectData void UTeamSyncDataBase::OnDataDirty () { if (BoundTeam.IsValid ()) { CollectSyncData ( BoundTeam.Get () ); } } void UTeamSyncDataBase::CollectSyncData (UTeamBase* InTeam) { if (!IsValid (InTeam)) return ; SetTeamID ( InTeam->GetTeamID () ); SetMemberUIDs ( InTeam->GetMemberUIDs () ); LogD (TEXT ("UTeamSyncDataBase::CollectSyncData, %s" ), *ToString ()); } #pragma endregion CollectData
提供 Create
/ Destroy
TeamSyncData
的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 UTeamSyncDataBase* UTeamUtils::CreateTeamSyncData (UObject* Outer, UTeamBase* InTeam, UClass* InClass) { if (!IsValid (Outer)) return nullptr ; if (!IsValid (InClass) || !InClass->IsChildOf (UTeamSyncDataBase::StaticClass ())) return nullptr ; UTeamSyncDataBase* NewSyncData = NewObject<UTeamSyncDataBase>(Outer, InClass); if (!IsValid (NewSyncData)) return nullptr ; NewSyncData->BindTeam ( InTeam ); return NewSyncData; } void UTeamUtils::DestoryTeamSyncData (UTeamSyncDataBase* SyncData) { if (!IsValid (SyncData)) return ; SyncData->Unbind (); SyncData = nullptr ; }
完整实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 UCLASS ()class UTeamSyncDataBase : public UObject{ GENERATED_BODY () #pragma region Base protected : virtual bool IsSupportedForNetworking () const override { return true ; } protected : virtual void GetLifetimeReplicatedProps (TArray<FLifetimeProperty>& OutLifetimeProps) const override ; #pragma endregion Base #pragma region Bind public : void BindTeam (UTeamBase* InTeam) ; void Unbind () ; private : TWeakObjectPtr <UTeamBase> BoundTeam; #pragma endregion Bind #pragma region CollectData private : void OnDataDirty () ; protected : virtual void CollectSyncData (UTeamBase* InTeam) ; #pragma endregion CollectData #pragma region Data public : virtual FString ToString () const ; protected : UFUNCTION () virtual void OnRep_TeamID () ; UFUNCTION () virtual void OnRep_MemberUIDs (const TArray<uint64>& LastMemberUIDs) ; private : UPROPERTY (PushModelProperty, ReplicatedUsing=OnRep_TeamID) uint64 TeamID; UPROPERTY (PushModelProperty, ReplicatedUsing=OnRep_MemberUIDs) TArray <uint64> MemberUIDs; #pragma endregion Data };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 #pragma region Base void UTeamSyncDataBase::GetLifetimeReplicatedProps (TArray<FLifetimeProperty>& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps (OutLifetimeProps); FDoRepLifetimeParams SharedParams; SharedParams.bIsPushBased = true ; DOREPLIFETIME_WITH_PARAMS_FAST (UTeamSyncDataBase, TeamID, SharedParams); DOREPLIFETIME_WITH_PARAMS_FAST (UTeamSyncDataBase, MemberUIDs, SharedParams); } #pragma endregion Base #pragma region Bind void UTeamSyncDataBase::BindTeam (UTeamBase* InTeam) { if (!IsValid (InTeam)) return ; BoundTeam = InTeam; InTeam->OnDataDirty.AddUObject (this , &ThisClass::OnDataDirty); CollectSyncData (InTeam); LogD (TEXT ("UTeamSyncDataBase::BindTeam, %s" ), *ToString ()); } void UTeamSyncDataBase::Unbind () { if (!BoundTeam.IsValid ()) return ; BoundTeam->OnDataDirty.RemoveAll (this ); LogD (TEXT ("UTeamSyncDataBase::Unbind, %s" ), *ToString ()); } #pragma endregion Bind #pragma region CollectData void UTeamSyncDataBase::OnDataDirty () { if (BoundTeam.IsValid ()) { CollectSyncData ( BoundTeam.Get () ); } } void UTeamSyncDataBase::CollectSyncData (UTeamBase* InTeam) { if (!IsValid (InTeam)) return ; SetTeamID ( InTeam->GetTeamID () ); SetMemberUIDs ( InTeam->GetMemberUIDs () ); LogD (TEXT ("UTeamSyncDataBase::CollectSyncData, %s" ), *ToString ()); } #pragma endregion CollectData #pragma region Data FString UTeamSyncDataBase::ToString () const { return FString::Printf (TEXT ("UID=%llu, TeamID=%llu, Members=%s" ), GetUID (), TeamID, *UStringUtils::ToString (MemberUIDs)); } void UTeamSyncDataBase::OnRep_TeamID () { LogD (TEXT ("UTeamSyncDataBase::OnRep_TeamID, %s" ), *ToString ()); } void UTeamSyncDataBase::OnRep_MemberUIDs (const TArray<uint64>& LastMemberUIDs) { LogD (TEXT ("UTeamSyncDataBase::OnRep_MemberUIDs, LastMemberUIDs=%s, %s" ), *UStringUtils::ToString (LastMemberUIDs), *ToString ()); } #pragma endregion Data