Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/207.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity:Singleton DontDestroyOnLoad生成错误_C#_Android_Unity3d_Singleton - Fatal编程技术网

C# Unity:Singleton DontDestroyOnLoad生成错误

C# Unity:Singleton DontDestroyOnLoad生成错误,c#,android,unity3d,singleton,C#,Android,Unity3d,Singleton,我正在使用XMGUnityLib插件。该程序在编辑器中运行良好,没有任何错误,但当我尝试构建它(Android)时,在按下apk步骤时,会出现以下错误: InvalidOperationException: The following game object is invoking the DontDestroyOnLoad method: AnalyticsManager. Notice that DontDestroyOnLoad can only be used in play mode

我正在使用XMGUnityLib插件。该程序在编辑器中运行良好,没有任何错误,但当我尝试构建它(Android)时,在按下apk步骤时,会出现以下错误:

InvalidOperationException: The following game object is invoking the DontDestroyOnLoad method: AnalyticsManager. Notice that DontDestroyOnLoad can only be used in play mode and, as such, cannot be part of an editor script.
XMGSingleton`1[XMGAnalyticsManager].get_Instance () (at Assets/XMG/UnityLib/Util/XMGSingleton.cs:28)
AndroidStorePostProcess.OnPostprocessScene () (at Assets/Editor/AndroidStorePostProcess.cs:32)
UnityEditor.HostView:OnGUI()
XMGSingleton.cs:

using UnityEngine;
using System.Collections;
using System;

/// <summary>
/// XMG singleton base Class.
/// Inherit your Manager Monobehavior classes that you want to be Singletons
/// </summary>
public abstract class XMGSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance;
    /// <summary>
    /// Returns the instance of this singleton
    /// Make sure we don't get destroyed on Scene Load
    /// </summary>
    public static T Instance {
        get {
            
            if(instance == null) {
                instance = (T) FindObjectOfType(typeof(T));
            
                if (instance == null) {
                   Debug.LogError("An instance of " + typeof(T) + 
                      " is needed in the scene, but there is none.");
                    return null;
                }

                DontDestroyOnLoad(instance.gameObject);
            }
            return instance;
        }
    }

    #region Public Methods

    public static bool HasInstance {
        get {
            if( (T) FindObjectOfType(typeof(T)) != null ) {
                return true;
            } else {
                return false;
            }
        }
    }
    
    /// <summary>
    /// Helper to cast the Instance to the Type provided
    /// </summary>
    public static Type MyInstance<Type> () {
        return (Type)(object)Instance;
    }
    
    #endregion
}
使用UnityEngine;
使用系统集合;
使用制度;
/// 
///XMG单例基类。
///继承要成为单例的Manager单行为类
/// 
公共抽象类XMGSingleton:monoBehavior,其中T:monoBehavior
{
保护静态T实例;
/// 
///返回此单例的实例
///确保我们不会在现场装载时被毁
/// 
公共静态T实例{
得到{
if(实例==null){
实例=(T)FindObjectOfType(typeof(T));
if(实例==null){
Debug.LogError(“一个“+typeof(T)+
“场景中需要,但没有。”);
返回null;
}
DontDestroyOnLoad(instance.gameObject);
}
返回实例;
}
}
#区域公共方法
公共静态bool实例{
得到{
如果((T)FindObjectOfType(typeof(T))!=null){
返回true;
}否则{
返回false;
}
}
}
/// 
///帮助器将实例强制转换为提供的类型
/// 
公共静态类型MyInstance(){
返回(类型)(对象)实例;
}
#端区
}
XMGAnalyticsManager.cs:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using Com.XMG.UnityLib.Community.OnlineGame;
using Com.XMG.UnityLib.Tracking;
    
#if UNITY_IPHONE
    using FlurryAccess = FlurryBinding;
#elif UNITY_ANDROID
    using FlurryAccess = FlurryAndroid;
#endif

public abstract partial class XMGAnalyticsManager : XMGSingleton<XMGAnalyticsManager> {
    
    #region Private Fields
    
    /// <summary>
    /// The type of the current build.
    /// For Analytics QA testing point to Analytics
    /// For QA Testing point to SandBox
    /// For Production/Release build point to Production
    /// </summary>
    [SerializeField]
    private BuildTypeEnum buildType = BuildTypeEnum.SandBox;
    
    /// <summary>
    /// The type of the android store type
    /// </summary>
    [SerializeField]
    private AndroidStoreTypeEnum androidStoreType = AndroidStoreTypeEnum.Google;
    
    /// <summary>
    /// The swrve authentication Info
    /// </summary>
    [SerializeField]
    private SwrveAuthentication swrveAuth;
    
    /// <summary>
    /// The flurry auth.
    /// </summary>
    [SerializeField]
    private FlurryAuthentication flurryAuth;
    
    /// <summary>
    ///  Sends events every X seconds.
    /// </summary>
    [SerializeField]
    private float sendEventsEverySeconds = 30;
    
    /// <summary>
    /// The parent screen.
    /// </summary>
    [SerializeField]
    private string parentScreen = "SplashPage";
    
    /// <summary>
    /// The grand parent screen.
    /// </summary>
    string grandParentScreen = "null";
    
    /// <summary>
    /// My external IP.
    /// </summary>
    string myExtIP = "";
    
    /// <summary>
    /// The swrve component.
    /// </summary>
    private SwrveComponent swrveComponent;
    
    private Dictionary<string, JSONObject> swrveResources = new Dictionary<string, JSONObject>();
    /// <summary>
    /// Resource hashmap ----> (key: resource name, value: json object)
    /// </summary>
    public Dictionary<string, JSONObject> Resources {
        get {
            return this.swrveResources;
        }
    }
    
    /// <summary>
    /// This event is triggered when swrve data is updated.
    /// </summary>
    public static event Action ItemsConfigurationUpdatedEvent = delegate {};
    
    /// <summary>
    /// True if we are in the fetching of AB Test Data State
    /// </summary>
    private bool isFetchingABParams = false;
    
    /// <summary>
    /// The current swrve identifier.
    /// </summary>
    private string currentSwrveId = null;
    
    /// <summary>
    /// The android bundle version.
    /// </summary>
    [SerializeField]
    protected string androidBundleVersion = "1.0";
    
    #endregion
    
    #region Public Properties
    
    /// <summary>
    /// True if it's a production build
    /// </summary>
    public bool IsProductionBuild {
        get { return buildType == BuildTypeEnum.Production; }
    }
    
    /// <summary>
    /// Gets the type of the android store.
    /// </summary>
    public AndroidStoreTypeEnum AndroidStoreType {
        get { return androidStoreType; }
        set { androidStoreType = value; }
    }
    
    /// <summary>
    /// True if its a google play store build
    /// </summary>
    public bool IsGoogleStoreType {
        get { return androidStoreType == AndroidStoreTypeEnum.Google; }
    }
    
    /// <summary>
    /// True if its an Amazon store build
    /// </summary>
    public bool IsAmazonStoreType {
        get { return androidStoreType == AndroidStoreTypeEnum.Amazon; }
    }
    
    #endregion
    
    #region Monobehaviors & Init
    
    /// <summary>
    /// Add event Listeners
    /// </summary>
    void Awake() {
        XMGOnlineProfileManager.OnProfileLoadedEvent += ProfileHasLoadedCallback;
        XMGCommunityManager.OnCreateRealProfileOnServerEvent += ProfileCreatedOnServerCallback;
        XMGCommunityManager.OnNewFriendsAddedEvent += NewFriendsAddedCallback;
        
        RegisterGameListeners();
        // TODO: Listen for Profile Change events
        swrveAuth.Init();
        flurryAuth.Init();
    }
    
    /// <summary>
    /// Starts the SWRVE Event timer
    /// </summary>
    void Start() {
        StartSwrveTimer();
        StartCoroutine( CheckIP() );
    }
    
    /// <summary>
    /// Checks for the IP
    /// </summary>
    /// <returns>
    /// The IP
    /// </returns>
    IEnumerator CheckIP(){

        WWW myExtIPWWW = new WWW("http://checkip.dyndns.org");
    
        if( myExtIPWWW != null ) {
            yield return myExtIPWWW;
            
            if( myExtIPWWW.error == null ) {
        
                myExtIP=myExtIPWWW.text;
            
                myExtIP=myExtIP.Substring(myExtIP.IndexOf(":")+1);
            
                myExtIP=myExtIP.Substring(0,myExtIP.IndexOf("<"));
            }
        }
    }
    
    
    /// <summary>
    /// Detach event Listeners
    /// </summary>
    void OnDestroy() {
        XMGOnlineProfileManager.OnProfileLoadedEvent -= ProfileHasLoadedCallback;
        XMGCommunityManager.OnCreateRealProfileOnServerEvent -= ProfileCreatedOnServerCallback;
        XMGCommunityManager.OnNewFriendsAddedEvent -= NewFriendsAddedCallback;
        UnRegisterGameListeners();
    }
    
    /// <summary>
    /// If Pause end session
    /// If Resume Start session and Re-Login.
    /// At any case post events
    /// </summary>
    /// <param name='pause'>
    /// Pause.
    /// </param>
    void OnApplicationPause(bool pause) {
        if (currentSwrveId != null) {
            
            if(pause) {
                swrveComponent.Swrve_AddSessionEnd();
            } else {
                swrveComponent.Swrve_AddSessionStart();
                SessionStart();
                AnalyticsLogout();
                AnalyticsLogin();
            }
            
            LogUserProperties();
            swrveComponent.Swrve_PostEvents(currentSwrveId, SWRVE_APP_VERSION);
        }
    }
    
    /// <summary>
    /// Init plugins.The Profile Has loaded
    /// </summary>
    void ProfileHasLoadedCallback() {
        // Get Swrve component
        swrveComponent = gameObject.GetComponentInChildren<SwrveComponent>();
        AnalyticsLogin();
        
        // Check if we've set the random user property, if not then set it
        if (!PlayerPrefs.HasKey(RANDOM_TEST_PROPERTY_KEY)) {
            PlayerPrefs.SetString(RANDOM_TEST_PROPERTY_KEY, "true");

            JSONObject userProperty = new JSONObject(JSONObject.Type.OBJECT);
            int random = NGUITools.RandomRange(1, 100);
            userProperty.AddField("RandNum", random.ToString());
            
            swrveComponent.Swrve_AddUserUpdateEvent(userProperty.ToString());
        }
        
    }
    
    /// <summary>
    /// A new Online Profile created callback.
    /// </summary>
    void ProfileCreatedOnServerCallback() {
        AddNamedEvent( "Community.FacebookUserCreated" );
    }
    
    /// <summary>
    /// New friends were added callback.
    /// </summary>
    /// <param name='newFriendsAdded'>
    /// The New friends added
    /// </param>
    void NewFriendsAddedCallback( int newFriendsAdded ) {
        JSONObject jTournamentFriends = new JSONObject(JSONObject.Type.OBJECT);
        jTournamentFriends.AddField( "NewFriendsAdded", BucketGeneral( newFriendsAdded ) );
        AddNamedEvent ( "Community.TournamentAddedFriend", jTournamentFriends );
    }
    
    #endregion
    
    #region Abstract & Virtual Methods
    
    /// <summary>
    /// Gets the tracking Object
    /// </summary>
    protected abstract XMGTracking GetTracking();
    
    /// <summary>
    /// Registers the game listeners.
    /// </summary>
    protected abstract void RegisterGameListeners();
    
    /// <summary>
    /// Unregister the game listeners.
    /// </summary>
    protected abstract void UnRegisterGameListeners();
    
    /// <summary>
    /// Logs the game user properties.
    /// </summary>
    /// <param name='jUserProperties'>
    /// The JSON Object with the user properties.
    /// </param>
    protected abstract void LogGameUserProperties(JSONObject jUserProperties);
    
    /// <summary>
    /// A session Is Started
    /// </summary>
    protected abstract void SessionStart();
    
    /// <summary>
    /// The session has ended
    /// </summary>
    protected abstract void SessionEnd();
    
    /// <summary>
    /// Gets the user start time.
    /// Default to Now
    /// Override to provide the user's start time
    /// </summary>
    /// <returns>
    /// The user start time.
    /// </returns>
    protected virtual long GetUserStartTime() {
        return (long)XMGUnityUtil.ToUnixTimeFromUniversal( DateTime.UtcNow );
    }
    
    #endregion
    
    #region Private Methods
    
    /// <summary>
    /// Starts the swrve timer.
    /// </summary>
    private void StartSwrveTimer() {
        StartCoroutine( StartEventsTimer());
    }
    
    /// <summary>
    /// Logs the user properties.
    /// And Calls abstract LogGameUserProperties
    /// </summary>
    private  void LogUserProperties() {
        JSONObject jUserProperties = new JSONObject(JSONObject.Type.OBJECT);
        // Add here Common User Properties
        XMGTracking tracking = GetTracking();
        
        jUserProperties.AddField( UP_FIRST_LAUNCH_DAY, tracking.FirstLaunch.Day );
        jUserProperties.AddField( UP_FIRST_LAUNCH_MONTH, tracking.FirstLaunch.Month );
        jUserProperties.AddField( UP_FIRST_LAUNCH_YEAR, tracking.FirstLaunch.Year );
        jUserProperties.AddField( UP_FIRST_LAUNCH_EPOCH, XMGUnityUtil.ToUnixTimeFromUniversal( tracking.FirstLaunch ).ToString() );
        jUserProperties.AddField( UP_TOTAL_TAPJOY_REWARDS, tracking.TotalTapJoyPointsEarned );
        jUserProperties.AddField( UP_TOTAL_SPONSORPAY_REWARDS, tracking.TotalSponsorPayPointsEarned );
        jUserProperties.AddField( UP_TOTAL_CHARTBOOST_ADS_CLICKED, tracking.TotalChartBoostAdsClicked );
        jUserProperties.AddField( UP_TOTAL_CHARTBOOST_ADS_CLOSED, tracking.TotalChartBoostAdsClosed );
        
        jUserProperties.AddField( UP_TOTAL_SOFT_CURRENCY_EARNED, tracking.SoftCurrencyEarned );
        jUserProperties.AddField( UP_TOTAL_HARD_CURRENCY_EARNED, tracking.HardCurrencyEarned );
        jUserProperties.AddField( UP_TOTAL_SOFT_CURRENCY_SPENT, tracking.SoftCurrencySpent );
        jUserProperties.AddField( UP_TOTAL_HARD_CURRENCY_SPENT, tracking.HardCurrencySpent );
#if UNITY_IPHONE
        jUserProperties.AddField( UP_VERION, EtceteraTwoBinding.getInfoPlistValue("CFBundleVersion") );
#elif UNITY_ANDROID
        jUserProperties.AddField( UP_VERION, androidBundleVersion );
#endif
        jUserProperties.AddField( UP_TOTAL_FRIENDS, tracking.TotalFriends );
        jUserProperties.AddField( UP_TOTAL_UNIQUE_DAYS_PLAYED, tracking.TotalUniqueDaysPlayed );
        if( string.IsNullOrEmpty( myExtIP ) ) {
            jUserProperties.AddField( UP_IP, myExtIP );
        }
        LogGameUserProperties(jUserProperties);
        swrveComponent.Swrve_AddUserUpdateEvent(jUserProperties.ToString());
    }
    
    #endregion
    
    #region Authentication
    
    /// <summary>
    /// Logs in to Flurry and SWRVE
    /// </summary>
    void AnalyticsLogin() {

        FlurryLogin();
        
        if( currentSwrveId != null ) {
            if( !currentSwrveId.Equals( XMGOnlineProfileManager.Instance.ActiveOnlineProfile.GameStats.SwrveId ) ) {
                Debug.Log("There is already a swrve account signed in!!! You must close the session first!");
                AnalyticsLogout();
            } else {
                // This swrve user is already logged in, bail out of this function
                Debug.Log("Attempt to log into swrve twice with the same id... Ignoring.");
                return;
            }
        }
        
        SwrveLogin(XMGOnlineProfileManager.Instance.ActiveOnlineProfile.GameStats.SwrveId);
    }
    
    /// <summary>
    /// Logout from Flurry and SWRVE
    /// </summary>
    private void AnalyticsLogout() {
        
        FlurryLogout();
        
        if(currentSwrveId == null) {
            Debug.LogError("There is no active swrve user!!! Cannot close session.");
            return;
        }
        
        SwrveLogout();
    }
    
    
    /// <summary>
    /// Starts Flurry Session
    /// </summary>
    private void FlurryLogin() {
#if UNITY_IPHONE
        FlurryAccess.startSession(flurryAuth.FlurryKey);
#elif UNITY_ANDROID
        FlurryAccess.onStartSession(flurryAuth.FlurryKey, true, true );
#endif
    }
    
    /// <summary>
    /// Logouts from Flurry
    /// </summary>
    private void FlurryLogout() {
#if UNITY_ANDROID
        FlurryAccess.onEndSession();
#endif
    }
    
    /// <summary>
    /// Login to Swrve
    /// </summary>
    /// <param name='swrveId'>
    /// The Swrve identifier.
    /// </param>
    private void SwrveLogin(string swrveId) {
        
        currentSwrveId = swrveId;
        
        int gameId = 0;
        string apiKey = "";
        
        if (buildType == BuildTypeEnum.Analytics) {
            gameId = swrveAuth.AnalyticsGameID;
            apiKey = swrveAuth.AnalyticsAPIKey;
        } else if (buildType == BuildTypeEnum.SandBox) {
            gameId = swrveAuth.SandboxGameID;
            apiKey = swrveAuth.SandboxAPIKey;
        } else if( buildType == BuildTypeEnum.Production ) {
            gameId = swrveAuth.ProductionGameID;
            apiKey = swrveAuth.ProductionAPIKey;
        }
        
        
        InitializeSWRVEComponent(gameId,
                    apiKey,
                    swrveAuth.PersonalKey,
                    swrveAuth.URLABTest
                    );
    }
    
    /// <summary>
    /// Logout from Swrve
    /// </summary>
    private void SwrveLogout() {
        // Make sure to close the Swrve session
        SessionEnd();
        swrveComponent.Swrve_AddSessionEnd();
        swrveComponent.Swrve_PostEvents(currentSwrveId, SWRVE_APP_VERSION);
        currentSwrveId = null;
    }
    
    /// <summary>
    /// Initializes the SWRVE component.
    /// </summary>
    /// <param name='gameId'>
    /// The Game identifier.
    /// </param>
    /// <param name='apiKey'>
    /// The API key.
    /// </param>
    /// <param name='personalKey'>
    /// Personal key.
    /// </param>
    /// <param name='abURL'>
    /// The Ab Test server URL.
    /// </param>
    private void InitializeSWRVEComponent(int gameId, string apiKey, string personalKey, string abURL) {
        swrveComponent.gameId = gameId;
        swrveComponent.apiKey = apiKey;
        swrveComponent.abTestServer = abURL;
        
        // Setup swrve for new user
        swrveComponent.Swrve_AddSessionStart();
        SessionStart();
        if(isFetchingABParams == false) {
            isFetchingABParams = true;
            StartCoroutine(GetAllResourcesWithABTests());
        }
    }
    
    #endregion
    
    #region A/B Helpers
    
    /// <summary>
    /// Returns the most recent JSON configuration for a resource from swrve or NULL if there is none.
    /// This means it could return cached data that is old. If you want to retrieve the latest from swrve.
    /// </summary>
    /// <param name="itemId">
    /// A <see cref="System.String"/>
    /// </param>
    /// <returns>
    /// A <see cref="JSONObject"/>
    /// </returns>
    public JSONObject GetItemParams(string itemId) {
        JSONObject item = null;
        swrveResources.TryGetValue(itemId, out item);
        return item;
    }
    
    /// <summary>
    /// Gets all resources with AB tests.
    /// </summary>
    /// <returns>
    /// The all resources with AB tests.
    /// </returns>
    private IEnumerator GetAllResourcesWithABTests() {
        
        string swrveURLRequest = string.Format(swrveAuth.URLABTestResources + "?api_key={0}&user={1}&joined={2}", swrveComponent.apiKey, currentSwrveId, GetUserStartTime() );
        WWW itemRequest = new WWW(swrveURLRequest);
        yield return itemRequest; // Yield until a result is returned.
        
        if(itemRequest.error != null) {
            Debug.LogWarning("Error attempting to fetch Swrve A/B Resource data: " + itemRequest.error);
            LoadCachedConfig();
            // Bail!
            yield break;
        }
        
        // Process all the resources into a hashmap ( key: resource name,  value: json object )
        JSONObject jResources = new JSONObject(itemRequest.text);
        if(jResources == null || jResources.type == JSONObject.Type.NULL) {
            // Bad data from swrve, abort!
            Debug.LogError("Bad A/B resource data from swrve!");
            LoadCachedConfig();
            yield break;
        } else {
            //Debug.LogWarning( "Data from SWRVE: " + jResources );
        }
        
        XMGSaveLoadUtils.Instance.SaveEncryptedField(CACHED_CONFIG_KEY, itemRequest.text); // Replace the old cached config.
        ParseResources(jResources);
        if( swrveResources.Count > 0 ) {
            ItemsConfigurationUpdatedEvent();
        }
        
        isFetchingABParams = false;
    }
    
    /// <summary>
    /// Loads the cached swrve config file
    /// </summary>
    private void LoadCachedConfig() {
        string cached = XMGSaveLoadUtils.Instance.LoadEncryptedField(CACHED_CONFIG_KEY);
        
        if(string.IsNullOrEmpty(cached)) {
            // There was no cached data
            return;
        }
        
        // Apply the cached resources so it doesn't block updates.
        JSONObject jResources = new JSONObject(cached);
        ParseResources(jResources);
        if( swrveResources.Count > 0 ) {
            ItemsConfigurationUpdatedEvent();
        }
    }
    
    /// <summary>
    ///  Expects a JSON array of resources.
    /// </summary>
    /// <param name="resources">
    /// A <see cref="JSONObject"/>
    /// </param>
    private void ParseResources(JSONObject jResources) {
        swrveResources.Clear();
        //Debug.Log( "Parsing SWRVE Resources: " + jResources );
        
        if(jResources == null || jResources.type != JSONObject.Type.ARRAY) {
            // Bad data from swrve, abort!
            Debug.LogError("Could not parse resource data, unexpected format!");
            return;
        }
        
        foreach(JSONObject data in jResources.list) {
            JSONObject key = data.GetField("uid");
            if(key == null || key.type != JSONObject.Type.STRING || string.IsNullOrEmpty( JSONObject.GetString(key) ) ) {
                // Bad item, on to the next
                Debug.LogWarning("Bad item, no property 'uid' in " + data.print());
                continue;
            }
            // Add the resource over top of any precached configuration
            swrveResources[JSONObject.GetString(key)] = data;
        }
    }
    
    #endregion
    
    #region Event Handling
    
    /// <summary>
    /// Adds the named event.
    /// </summary>
    /// <param name='name'>
    /// The EventName.
    /// </param>
    public void AddNamedEvent(string name) {
        swrveComponent.Swrve_AddNamedEvent(name, "{}");
#if UNITY_IPHONE
        FlurryAccess.logEvent(name, false);
#elif UNITY_ANDROID
        FlurryAccess.logEvent(name);
#endif
    }
    
    /// <summary>
    /// Adds a named event with Payload
    /// </summary>
    /// <param name='name'>
    /// The EventName.
    /// </param>
    /// <param name='payload'>
    /// Payload.
    /// </param>
    public void AddNamedEvent(string name, JSONObject payload) {
        string data = payload.ToString();
        
        if(!string.IsNullOrEmpty(data)) {
            swrveComponent.Swrve_AddNamedEvent(name, data);
        } else {
            swrveComponent.Swrve_AddNamedEvent(name, "{}");
        }
        
#if UNITY_IPHONE
        FlurryAccess.logEventWithParameters(name, payload.ToDictionary(), false);
#elif UNITY_ANDROID
        FlurryAccess.logEvent(name, payload.ToDictionary());
#endif
    }
    
    /// <summary>
    /// Infinite Loop to send events in the queue
    /// </summary>
    private IEnumerator StartEventsTimer() {
        float timeInterval = Time.realtimeSinceStartup;
        while (true) {
            if(Time.realtimeSinceStartup - timeInterval >= sendEventsEverySeconds) {
                SendEvents();
                timeInterval = Time.realtimeSinceStartup;
            }
            yield return new WaitForSeconds( 1 );
        }
    }
    
    /// <summary>
    /// Sends the events to SWRVE
    /// </summary>
    private void SendEvents() {
        if(currentSwrveId != null) {
            swrveComponent.Swrve_PostEvents(currentSwrveId, SWRVE_APP_VERSION);
        }
    }
    
    #endregion
    
    #region UI Events
    
    /// <summary>
    /// Logs a UI screen visit event.
    /// Records the current screen, the parent screen, and the grandparent screen.
    /// </summary>
    /// <param name='screenName'>
    /// Screen name.
    /// </param>
    public void ScreenVisitEvent(string screenName) {
        
        JSONObject eventParams = new JSONObject(JSONObject.Type.OBJECT);
        
        if(parentScreen != null) {
            eventParams.AddField("parent", parentScreen);
        }
        if(grandParentScreen != null) {
            eventParams.AddField("grandParent", grandParentScreen);
        }
        
        AddNamedEvent("UI.Flow." + screenName, eventParams);
        
        eventParams.AddField("screen", screenName);
        AddNamedEvent("UI.Flow.Screens", eventParams);
        
        grandParentScreen = parentScreen;
        parentScreen = screenName;
    }
    
    /// <summary>
    /// Logs a UI button pressed event
    /// </summary>
    /// <param name='buttonName'>
    /// The Button name.
    /// </param>
    public void ButtonPressedEvent( string buttonName ) {
        AddNamedEvent("UI.ButtonPressed." + buttonName );
    }
    
    #endregion
    
    #region Purchase Events
    
    /// <summary>
    /// Sends an analytics buy in event for purchasing inapps.
    /// </summary>
    /// <param name='rewardCurrency'>
    /// Reward currency
    /// </param>
    /// <param name='rewardAmount'>
    ///  Amount of rewardCurrency
    /// </param>
    /// <param name='localCost'>
    /// The real money price in local currency ( e.g 0.99 )
    /// </param>
    /// <param name='localCurrency'>
    /// CAD, USD, etc...
    /// </param>
    public void AddBuyInEvent(string rewardCurrency, int rewardAmount, float localCost, string localCurrency, string itemID ) {
        swrveComponent.Swrve_AddBuyInEvent( "", rewardCurrency, rewardAmount, Mathf.Round(localCost* 100)/100, localCurrency );
        AddNamedEvent( "Purhases.IAP" );
        AddNamedEvent( "Purhases.IAP.HardCurrency" + itemID );
    }
    
    /// <summary>
    /// Analytics event when a user purchases an item in-game.
    /// </summary>
    /// <param name='itemID'>
    /// The UID for the Item
    /// </param>
    /// <param name='currency'>
    /// The currency
    /// </param>
    /// <param name='itemCost'>
    /// Item cost.
    /// </param>
    /// <param name='itemQuantity'>
    /// Item quantity.
    /// </param>
    public void AddPurchaseEvent( string itemID, string currency, int itemCost, int itemQuantity ) {
        swrveComponent.Swrve_AddPurchaseItemEvent( itemID, currency, itemCost, itemQuantity );
    }
    
    /// <summary>
    /// Adds a purchase conversion event.
    /// </summary>
    /// <param name='itemID'>
    ///The unique Item ID
    /// </param>
    public void AddPurchaseConversionPackEvent( string itemID ) {
        AddNamedEvent( "Purchases.HardCurrency.SoftCurrency" );
        AddNamedEvent( "Purhases.HardCurrency.SoftCurrency." + itemID );
    }
    
    #endregion
}
使用UnityEngine;
使用制度;
使用系统集合;
使用System.Collections.Generic;
使用Com.XMG.UnityLib.Community.OnlineGame;
使用Com.XMG.UnityLib.Tracking;
#如果你是IPHONE的话
使用FlurryAccess=FlurryBinding;
#艾利夫·尤尼安卓
使用FlurryAccess=FlurryAndroid;
#恩迪夫
公共抽象部分类XMGAnalyticsManager:XMGSingleton{
#区域专用字段
/// 
///当前生成的类型。
///对于Analytics QA测试,请指向Analytics
///对于QA测试,请指向沙箱
///用于生产/发布构建点到生产
/// 
[序列化字段]
私有BuildTypeEnum buildType=BuildTypeEnum.SandBox;
/// 
///android商店类型的类型
/// 
[序列化字段]
私有AndroidStoreTypeEnum androidStoreType=AndroidStoreTypeEnum.Google;
/// 
///swrve身份验证信息
/// 
[序列化字段]
私有swrveAuth;
/// 
///慌乱的作者。
/// 
[序列化字段]
私人FlurryAuthentication flurryAuth;
/// 
///每X秒发送一次事件。
/// 
[序列化字段]
私有浮点sendEventsEverySeconds=30;
/// 
///父屏幕。
/// 
[序列化字段]
私有字符串parentScreen=“SplashPage”;
/// 
///父母大屏幕。
/// 
字符串grandrentscreen=“null”;
/// 
///我的外部IP。
/// 
字符串myExtIP=“”;
/// 
///swrve组件。
/// 
私有SwrveComponent SwrveComponent;
专用词典SWServerSources=新词典();
/// 
///资源hashmap-->(键:资源名称,值:json对象)
/// 
公共词典资源{
得到{
返回此.swrversources;
}
}
/// 
///更新swrve数据时触发此事件。
/// 
公共静态事件操作项配置UpdateEvent=委托{};
/// 
///如果我们处于提取AB测试数据状态,则为True
/// 
private bool isFetchingABParams=false;
/// 
///当前swrve标识符。
/// 
私有字符串currentSwrveId=null;
/// 
///android捆绑版本。
/// 
[序列化字段]
受保护的字符串AndroidBundLeverVersion=“1.0”;
#端区
#区域公共财产
/// 
///如果是生产构建,则为True
/// 
公共bool IsProductionBuild{
获取{return buildType==BuildTypeEnum.Production;}
}
/// 
///获取android应用商店的类型。
/// 
公共AndroidStoreType枚举AndroidStoreType{
获取{return androidStoreType;}
设置{androidStoreType=value;}
}
/// 
///如果是google play商店构建,则为True
/// 
公共bool是googlestoretype{
get{return androidStoreType==AndroidStoreTypeEnum.Google;}
}
/// 
///如果它是亚马逊商店构建,则为True
/// 
公共图书馆IsAmazonStoreType{
获取{return androidStoreType==AndroidStoreTypeEnum.Amazon;}
}
#端区
#区域单粒子行为&Init
/// 
///添加事件侦听器
/// 
无效唤醒(){
XMGOnlineProfileManager.OnProfileLoadedEvent+=ProfileHasLoadedCallback;
XMGCommunityManager.OnCreateRealProfileOnServerEvent+=ProfileCreatedOnServerCallback;
XMGCommunityManager.OnNewFriendsAddedEvent+=NewFriendsAddedCallback;
RegisterGameListeners();
//TODO:侦听配置文件更改事件
swrveAuth.Init();
flurryAuth.Init();
}
/// 
///启动SWRVE事件计时器
/// 
void Start(){
StartSwrveTimer();
start例程(CheckIP());
}
/// 
///检查IP地址
/// 
/// 
///知识产权
/// 
IEnumerator CheckIP(){
WWW myExtIPWWW=新建WWW(“http://checkip.dyndns.org");
如果(myExtIPWWW!=null){
收益率收益率;
if(myExtIPWWW.error==null){
myExtIP=myExtIPWWW.text;
myExtIP=myExtIP.Substring(myExtIP.IndexOf(“:”)+1);
myExtIP=myExtIP。
void Awake()
{
    if (instance == null)
    {
        DontDestroyOnLoad(gameObject);
        instance = this;
    }
    else
        if (instance != this)
            Destroy(gameObject);
}