Forum rules - please read before posting.

Adding a custom RememberHealth component to save/load Opsive/UCC health value

edited July 2024 in Technical Q&A

AC v 1.78.4
Opsive UCC v2

I'm trying to create a way for AC to remember the UCC character's health attribute and applying it automatically when loading/saving. Afaik there isn't a way to do this in the UCC/AC integration. I tried creating a script but I don't think it's headed in the right direction. When loading, it doesn't update the health to the saved value from that save. When saving, it does give the correct value in the debug log.
I'm sure the LoadData() part is completely wrong, I tried following the format from the tutorial but that gave more errors. Any ideas?

using UnityEngine;
using Opsive.UltimateCharacterController.Traits;

namespace AC
{ 

    public class AC_UCCPlayerHealth : Remember

    {
        private AttributeManager attributeManager;
        void Awake() 
        {
            attributeManager = GetComponent<AttributeManager>();
            if (attributeManager == null)
            {
                Debug.LogError("AC_UCCPlayerHealth: AttributeManager component not found!");
            }
        }




        public override string SaveData()
        {
            if (attributeManager != null)
            {
                Attribute healthAttribute = attributeManager.GetAttribute("Health");

                if (healthAttribute != null)
                {
                    PlayerPrefs.SetFloat("PlayerHealth", healthAttribute.Value);
                    PlayerPrefs.Save();
                    Debug.Log("Player health saved: " + healthAttribute.Value);
                    return healthAttribute.Value.ToString(); 
                }
            }
            return null;  
        }

        public void LoadData()
        {
            if (attributeManager != null)
            {
                Attribute healthAttribute = attributeManager.GetAttribute("Health");
                if (healthAttribute != null)
                {
                    float savedHealth = PlayerPrefs.GetFloat("PlayerHealth", healthAttribute.MaxValue);
                    healthAttribute.Value = savedHealth;
                    Debug.Log("Player health loaded: " + savedHealth);

                }
            }
        }
    }
    [System.Serializable]
    public class HealthData : RememberData
    {

        public HealthData() { } 
    }


}

Comments

  • Your script isn't relying on AC to store any data - it's just storing the health in PlayerPrefs separately.

    Your LoadData function is also not overriding anything, so it won't be called during the loading process.

    The intended way is to store within HealthData:

    using UnityEngine;
    using Opsive.UltimateCharacterController.Traits;
    
    namespace AC
    { 
    
        public class AC_UCCPlayerHealth : Remember
        {
    
            private AttributeManager attributeManager;
            void Awake() 
            {
                attributeManager = GetComponent<AttributeManager>();
                if (attributeManager == null)
                {
                    Debug.LogError("AC_UCCPlayerHealth: AttributeManager component not found!");
                }
            }
    
            public override string SaveData()
            {
                HealthData data = new HealthData();
                data.objectID = constantID;
                data.savePrevented = savePrevented;
    
                if (attributeManager != null)
                {
                    Attribute healthAttribute = attributeManager.GetAttribute("Health");
    
                    if (healthAttribute != null)
                    {
                        data.health = healthAttribute.Value;
                        Debug.Log("Player health saved: " + healthAttribute.Value);
                    }
                }
                return Serializer.SaveScriptData <HealthData> (data);
            }
    
            public override void LoadData(string stringData)
            {
                HealthData data = Serializer.LoadScriptData <HealthData> (stringData);
                if (data == null) return;
                SavePrevented = data.savePrevented; if (savePrevented) return;
    
                if (attributeManager != null)
                {
                    Attribute healthAttribute = attributeManager.GetAttribute("Health");
                    if (healthAttribute != null)
                    {
                        float savedHealth = data.health;
                        healthAttribute.Value = savedHealth;
                        Debug.Log("Player health loaded: " + savedHealth);
    
                    }
                }
            }
        }
        [System.Serializable]
        public class HealthData : RememberData
        {
    
            public float health;
    
            public HealthData() { } 
        }
    
    
    }
    
  • Hi Chris, thanks for the response. Unfortunately it gives me this error -

    FormatException: The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
    System.Convert.FromBase64CharPtr (System.Char* inputPtr, System.Int32 inputLength) (at <80e08c2cc04049bf931fc9038d04f397>:0)

  • No obvious cause springs to mind.

    • At which point - saving or loading?
    • Does this occur in builds or the Editor?
    • Is there a stacktrace to go with the error?
    • Do the "Player health saved / loaded" logs show?
  • Weird, that error disappeared on its own and everything's working perfectly! Thanks a lot as always!

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.