1
+ using System ;
2
+ using System . Collections . Generic ;
3
+ using System . IO ;
4
+ using System . Threading . Tasks ;
5
+ using UnityEditor ;
6
+ using UnityEngine ;
7
+ using VirtueSky . Inspector ;
8
+
9
+
10
+ #if VIRTUESKY_FIREBASE
11
+ using Firebase ;
12
+ using Firebase . Extensions ;
13
+ #endif
14
+
15
+ #if VIRTUESKY_FIREBASE_REMOTECONFIG
16
+ using Firebase . RemoteConfig ;
17
+ #endif
18
+
19
+ namespace VirtueSky . RemoteConfigs
20
+ {
21
+ public class FirebaseRemoteConfigManager : MonoBehaviour
22
+ {
23
+ [ SerializeField ] private bool dontDestroyOnLoad ;
24
+ #if VIRTUESKY_FIREBASE
25
+ [ Space , ReadOnly , SerializeField ] private DependencyStatus dependencyStatus = DependencyStatus . UnavailableOther ;
26
+ #endif
27
+ [ SerializeField ] private bool isSetupDefaultData = true ;
28
+ [ Space ( 10 ) , SerializeField ] private List < FirebaseRemoteConfigData > listRemoteConfigData ;
29
+
30
+ private bool _isFetchRemoteConfigCompleted = false ;
31
+ private static FirebaseRemoteConfigManager _instance ;
32
+
33
+ private void Awake ( )
34
+ {
35
+ if ( dontDestroyOnLoad )
36
+ {
37
+ DontDestroyOnLoad ( this . gameObject ) ;
38
+ }
39
+
40
+ if ( _instance == null )
41
+ {
42
+ _instance = this ;
43
+ }
44
+ else
45
+ {
46
+ Destroy ( gameObject ) ;
47
+ }
48
+ }
49
+
50
+ #region API
51
+
52
+ public static bool IsFetchRemoteConfigCompleted => _instance . _isFetchRemoteConfigCompleted ;
53
+ public static List < FirebaseRemoteConfigData > ListRemoteConfigData => _instance . listRemoteConfigData ;
54
+
55
+ #endregion
56
+
57
+ #if VIRTUESKY_FIREBASE
58
+ private void Start ( )
59
+ {
60
+ _isFetchRemoteConfigCompleted = false ;
61
+ if ( isSetupDefaultData )
62
+ {
63
+ foreach ( var remoteConfigData in listRemoteConfigData )
64
+ {
65
+ remoteConfigData . SetupDataDefault ( ) ;
66
+ }
67
+ }
68
+
69
+ FirebaseApp . CheckAndFixDependenciesAsync ( ) . ContinueWithOnMainThread ( task =>
70
+ {
71
+ dependencyStatus = task . Result ;
72
+ if ( dependencyStatus == DependencyStatus . Available )
73
+ {
74
+ #if VIRTUESKY_FIREBASE_REMOTECONFIG
75
+ FetchDataAsync ( ) ;
76
+ #endif
77
+ }
78
+ else
79
+ {
80
+ Debug . LogError ( "Could not resolve all Firebase dependencies: " +
81
+ dependencyStatus ) ;
82
+ }
83
+ } ) ;
84
+ }
85
+ #endif
86
+
87
+ #if VIRTUESKY_FIREBASE_REMOTECONFIG && VIRTUESKY_FIREBASE
88
+ private Task FetchDataAsync ( )
89
+ {
90
+ Debug . Log ( "Fetching data..." ) ;
91
+ Task fetchTask = FirebaseRemoteConfig . DefaultInstance
92
+ . FetchAsync ( TimeSpan . Zero ) ;
93
+ if ( fetchTask . IsCanceled )
94
+ {
95
+ Debug . Log ( "Fetch canceled." ) ;
96
+ }
97
+ else if ( fetchTask . IsFaulted )
98
+ {
99
+ Debug . Log ( "Fetch encountered an error." ) ;
100
+ }
101
+ else if ( fetchTask . IsCompleted )
102
+ {
103
+ Debug . Log ( "Fetch completed successfully!" ) ;
104
+ }
105
+
106
+ return fetchTask . ContinueWithOnMainThread ( tast =>
107
+ {
108
+ var info = FirebaseRemoteConfig . DefaultInstance . Info ;
109
+ if ( info . LastFetchStatus == LastFetchStatus . Success )
110
+ {
111
+ FirebaseRemoteConfig . DefaultInstance . ActivateAsync ( ) . ContinueWithOnMainThread (
112
+ task =>
113
+ {
114
+ Debug . Log ( String . Format (
115
+ "Remote data loaded and ready (last fetch time {0})." ,
116
+ info . FetchTime ) ) ;
117
+ foreach ( var remoteConfigData in listRemoteConfigData )
118
+ {
119
+ if ( string . IsNullOrEmpty ( remoteConfigData . key ) ) continue ;
120
+ remoteConfigData . SetupData ( FirebaseRemoteConfig . DefaultInstance
121
+ . GetValue ( remoteConfigData . key . ToString ( ) ) ) ;
122
+ }
123
+
124
+ _isFetchRemoteConfigCompleted = true ;
125
+ } ) ;
126
+
127
+ Debug . Log ( "<color=Green>Firebase Remote Config Fetching completed!</color>" ) ;
128
+ }
129
+ else
130
+ {
131
+ Debug . Log ( "Fetching data did not completed!" ) ;
132
+ }
133
+ } ) ;
134
+ }
135
+ #endif
136
+
137
+ #if UNITY_EDITOR
138
+ private const string pathDefaultScript = "Assets/_Root/Scripts" ;
139
+ [ Button ]
140
+ private void GenerateRemoteData ( )
141
+ {
142
+ if ( ! Directory . Exists ( pathDefaultScript ) )
143
+ {
144
+ Directory . CreateDirectory ( pathDefaultScript ) ;
145
+ }
146
+
147
+ var productImplPath = $ "{ pathDefaultScript } /RemoteData.cs";
148
+ var str = "namespace VirtueSky.RemoteConfigs\n {" ;
149
+ str += "\n \t public struct RemoteData\n \t {" ;
150
+
151
+ var listRmcData = listRemoteConfigData ;
152
+ for ( int i = 0 ; i < listRmcData . Count ; i ++ )
153
+ {
154
+ var rmcKey = listRmcData [ i ] . key ;
155
+
156
+ str += $ "\n \t \t public const string KEY_{ rmcKey . ToUpper ( ) } = \" { rmcKey } \" ;";
157
+
158
+ switch ( listRmcData [ i ] . typeRemoteConfigData )
159
+ {
160
+ case TypeRemoteConfigData . StringData :
161
+ str +=
162
+ $ "\n \t \t public const string DEFAULT_{ rmcKey . ToUpper ( ) } = \" { listRmcData [ i ] . defaultValueString } \" ;";
163
+ str += "\n \t \t #if VIRTUESKY_DATA" ;
164
+ str +=
165
+ $ "\n \t \t public static string { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
166
+ str += "\n \t \t #else" ;
167
+ str +=
168
+ $ "\n \t \t public static string { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetString(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
169
+ str += "\n \t \t #endif" ;
170
+ break ;
171
+ case TypeRemoteConfigData . BooleanData :
172
+ str +=
173
+ $ "\n \t \t public const bool DEFAULT_{ rmcKey . ToUpper ( ) } = { GetBool ( listRmcData [ i ] . defaultValueBool ) } ;";
174
+ str += "\n \t \t #if VIRTUESKY_DATA" ;
175
+ str +=
176
+ $ "\n \t \t public static bool { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
177
+ str += "\n \t \t #else" ;
178
+ str +=
179
+ $ "\n \t \t public static bool { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetInt(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } ? 1 : 0) > 0;";
180
+ str += "\n \t \t #endif" ;
181
+ break ;
182
+ case TypeRemoteConfigData . IntData :
183
+ str +=
184
+ $ "\n \t \t public const int DEFAULT_{ rmcKey . ToUpper ( ) } = { listRmcData [ i ] . defaultValueInt } ;";
185
+ str += "\n \t \t #if VIRTUESKY_DATA" ;
186
+ str +=
187
+ $ "\n \t \t public static int { rmcKey . ToUpper ( ) } => VirtueSky.DataStorage.GameData.Get(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
188
+ str += "\n \t \t #else" ;
189
+ str +=
190
+ $ "\n \t \t public static int { rmcKey . ToUpper ( ) } => UnityEngine.PlayerPrefs.GetInt(KEY_{ rmcKey . ToUpper ( ) } , DEFAULT_{ rmcKey . ToUpper ( ) } );";
191
+ str += "\n \t \t #endif" ;
192
+ break ;
193
+ }
194
+ }
195
+
196
+ str += "\n \t }" ;
197
+ str += "\n }" ;
198
+
199
+ var writer = new StreamWriter ( productImplPath , false ) ;
200
+ writer . Write ( str ) ;
201
+ writer . Close ( ) ;
202
+ AssetDatabase . ImportAsset ( productImplPath ) ;
203
+
204
+ string GetBool ( bool condition )
205
+ {
206
+ return condition ? "true" : "false" ;
207
+ }
208
+ }
209
+ #endif
210
+ }
211
+ }
0 commit comments