2016-12-27 97 views
1

我正在使用XMGUnityLib插件。該程序運行在沒有任何錯誤的編輯正常,但當我嘗試構建它(安卓),然後同時按下APK步驟中給出了這樣的錯誤:Unity:Singleton DontDestroyOnLoad生成錯誤

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 
} 

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 retireve 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 
} 

這個單例類是否正確編碼?如果是,那可能是什麼問題? 任何幫助將不勝感激。 謝謝:)

+0

它說的錯誤是在'XMGInAppManage'但你貼代碼'XMGSingleton' ... – Programmer

+0

更新了問題... – Khubaib

+0

對不起,我沒有XMGUnityLib插件。聯繫作者並報告問題。 XMGSingleton類沒有錯。 – Programmer

回答

0

你有一個「編輯器腳本」,從這個類繼承嗎?如果是這樣,那麼很可能這是導致錯誤的原因。如果您不確定這意味着什麼,請嘗試在名爲Editor的項目中查找文件夾並查看其腳本。或者嘗試搜索using UnityEditor;以及從Editor繼承的任何腳本,如下所示:public class Name : Editor並使它們不能從此類繼承。

另一種解決方法是嘗試評論DontDestroyOnLoad行(XMGSingleton.cs中的第26行)並將其放在需要它的位置。

轉到您使用這個腳本,做這樣的事情的對象:

void Awake() 
{ 
    if (instance == null) 
    { 
     DontDestroyOnLoad(gameObject); 
     instance = this; 
    } 
    else 
     if (instance != this) 
      Destroy(gameObject); 
}