From a339149a71ac2190ff5f1d0f473057b03718d736 Mon Sep 17 00:00:00 2001 From: Shaun M Reed Date: Sun, 3 Sep 2017 18:56:05 -0400 Subject: [PATCH] Added saving and loading Added PlayerData class to GamerManager.cs - Stored in Application.PersistantDataPath + "/playerInfo.dat" - Safer way to store / transfer data? - Add saving of local time when calling Save() or Load() - Compare save time to load time and give afk rewards earned based on rotation speed --- Assets/Scenes/Main.unity | Bin 113368 -> 114152 bytes Assets/Scripts/ExperienceBar.cs | 59 +++++++++------- Assets/Scripts/GameManager.cs | 95 ++++++++++++++++++++++++++ Assets/Scripts/GameManager.cs.meta | 12 ++++ Assets/Scripts/SpinningCube.cs | 25 +++---- ProjectSettings/QualitySettings.asset | Bin 4736 -> 4784 bytes 6 files changed, 154 insertions(+), 37 deletions(-) create mode 100644 Assets/Scripts/GameManager.cs create mode 100644 Assets/Scripts/GameManager.cs.meta diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index 534f596ecd0b458409903ccf500d3aa6e3d8ef3a..87f67444f2081ed9418315424a783f90f47aa36a 100644 GIT binary patch delta 6725 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 delta 6576 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.text != currentLevel.ToString()){ + currentLevelText.GetComponent().text = currentLevel.ToString(); + } if (fillAmount != expBarSprite.fillAmount) { @@ -47,7 +52,7 @@ public class ExperienceBar : MonoBehaviour { if (expBarSprite.fillAmount >= 1.0f) { LevelUp(); - clicksNeeded = (expRequired - expObtained) / Increment; + clicksNeeded = (currentRequirement - currentExp) / Increment; fillAmount = 0; } } @@ -55,28 +60,28 @@ public class ExperienceBar : MonoBehaviour { public void ExpMore() { ++clicks; - expObtained = expObtained + Increment; - fillAmount = (expObtained / expRequired); + currentExp = currentExp + Increment; + fillAmount = currentExp / currentRequirement; Debug.Log("fillAmount = " + fillAmount); } public void LevelUp() { - ++level; - levelText.GetComponent().text = level.ToString(); - previousExpRequired = expRequired; - expObtained = 0; - expRequired = Mathf.Pow(expRequired, 1.05f); + ++currentLevel; + currentLevelText.GetComponent().text = currentLevel.ToString(); + previousExpRequired = currentRequirement; + currentExp = 0; + currentRequirement = Mathf.Pow(currentRequirement, 1.05f); GameObject.FindGameObjectWithTag("Player").GetComponent().RaiseRotationSpeed(); } public void ResetExp() { - level = 1; - levelText.GetComponent().text = level.ToString(); + currentLevel = 1; + currentLevelText.GetComponent().text = currentLevel.ToString(); fillAmount = 0; - expObtained = 0; - expRequired = 100; + currentExp = 0; + currentRequirement = 100; clicksNeeded = 10; clicks = 0; } @@ -84,9 +89,17 @@ public class ExperienceBar : MonoBehaviour { public void ExpLess() { --clicks; - expObtained = expObtained - Increment; - fillAmount = (expObtained / expRequired); + currentExp = currentExp - Increment; + fillAmount = (currentExp / currentRequirement); Debug.Log("fillAmount = " + fillAmount); } + public float GetExperience() + { + float currentExp; + currentExp = this.currentExp; + return currentExp; + } + + } diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs new file mode 100644 index 0000000..7209a28 --- /dev/null +++ b/Assets/Scripts/GameManager.cs @@ -0,0 +1,95 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + + +public class GameManager : MonoBehaviour { + + //Used to save playerdata + //Serializable tells unity it can save to a file + [Serializable] + private class PlayerData + { + public int level; + public float experience; + public float requirement; + public float speed; + public float increment; + } + + + // Use this for initialization + void Start () { + Load(); + } + + // Update is called once per frame + void Update () { + + } + + void OnEnable() + { + Load(); + } + + void OnApplicationPause() + { + Save(); + } + + void OnApplicationQuit() + { + Save(); + } + + public void Save() + { + BinaryFormatter bf = new BinaryFormatter(); + FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat"); + + int currentLevel = GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentLevel; + float currentExp = GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentExp; + float currentRequirement = GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentRequirement; + float currentSpeed = GameObject.FindGameObjectWithTag("Player").GetComponent().currentSpeed; + float currentIncrement = GameObject.FindGameObjectWithTag("Player").GetComponent().currentIncrement; + + PlayerData data = new PlayerData(); + data.level = currentLevel; + data.experience = currentExp; + data.requirement = currentRequirement; + data.speed = currentSpeed; + data.increment = currentIncrement; + + bf.Serialize(file, data); + file.Close(); + Debug.Log("Saved"); + + } + + public void Load() + { + if (File.Exists(Application.persistentDataPath + "/playerInfo.dat")) + { + BinaryFormatter bf = new BinaryFormatter(); + FileStream file = File.Open(Application.persistentDataPath + "/playerInfo.dat", FileMode.Open); + PlayerData data = (PlayerData)bf.Deserialize(file); + file.Close(); + + GameObject.FindGameObjectWithTag("Player").GetComponent().currentSpeed = data.speed; + GameObject.FindGameObjectWithTag("Player").GetComponent().currentIncrement = data.increment; + GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentLevel = data.level; + GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentExp = data.experience; + GameObject.FindGameObjectWithTag("ExpGained").GetComponent().currentRequirement = data.requirement; + Debug.Log("Loaded"); + + + + } + + } + +} diff --git a/Assets/Scripts/GameManager.cs.meta b/Assets/Scripts/GameManager.cs.meta new file mode 100644 index 0000000..697d467 --- /dev/null +++ b/Assets/Scripts/GameManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2da23f5b35feb9749839423cfa5b61b2 +timeCreated: 1503806997 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/SpinningCube.cs b/Assets/Scripts/SpinningCube.cs index ce4f7be..9c7c0d6 100644 --- a/Assets/Scripts/SpinningCube.cs +++ b/Assets/Scripts/SpinningCube.cs @@ -3,8 +3,10 @@ using System.Collections; public class SpinningCube : MonoBehaviour { - public float m_Speed = 20f; - public float increments = 10f; + + //Playerdata -- Needs saved + public float currentSpeed = 20f; + public float currentIncrement = 10f; private string RotationDirection = "Up"; @@ -52,21 +54,21 @@ public class SpinningCube : MonoBehaviour public void RaiseRotationSpeed() { - m_Speed = m_Speed + increments; + currentSpeed = currentSpeed + currentIncrement; - Debug.Log("Rotation Speed: " + m_Speed); + Debug.Log("Rotation Speed: " + currentSpeed); } public void LowerRotationSpeed() { - m_Speed = m_Speed - increments; + currentSpeed = currentSpeed - currentIncrement; - Debug.Log("Rotation Speed: " + m_Speed); + Debug.Log("Rotation Speed: " + currentSpeed); } public void ResetRotationSpeed() { - m_Speed = 20.0f; + currentSpeed = 20.0f; Debug.Log("Rotation Speed Reset"); } @@ -111,16 +113,11 @@ public class SpinningCube : MonoBehaviour gameObject.GetComponent().material.color = Color.cyan; } - public void Start() - { - Vector3 rotationOrigin = GameObject.FindGameObjectWithTag("Player").transform.rotation.eulerAngles; - } - void FixedUpdate() { //Set angle1 = eulerAngle of axis being rotated prior to applying rotation angle1 = this.gameObject.transform.rotation.eulerAngles.y; - transform.Rotate(m_RotationDirection * Time.deltaTime * m_Speed); + transform.Rotate(m_RotationDirection * Time.deltaTime * currentSpeed); //angle2 = eulerAngle of axis after rotation applied angle2 = this.gameObject.transform.rotation.eulerAngles.y; //Difference between angle2 and angle1, how much the object rotated between frames @@ -132,7 +129,7 @@ public class SpinningCube : MonoBehaviour //If object has rotated 20 degrees (m_speed = 20), when angle1 = 350, && angle2 = 10 //angle2(10)-angle1(350) = -340 //Object has rotated past 360 - if ((m_Speed > 0) && (angledif < 0)) + if ((currentSpeed > 0) && (angledif < 0)) { ++rotations; GameObject.FindGameObjectWithTag("ExpGained").GetComponent().ExpMore(); diff --git a/ProjectSettings/QualitySettings.asset b/ProjectSettings/QualitySettings.asset index 7f8b68311cec3c3cd1b37c11d91db142fb1f5593..29bd02d940dec7132fc96088ff8a8ed2db007a45 100644 GIT binary patch literal 4784 zcmeI0&u<$=6vv z#ugd|ETwguB z_njl4FAazcvl#-tg)VKQv_x|F`*KiPU+1JX1V~qL$;r>KWk7PcFhcvEV1ED_{S1<} z*k>R&gBlAt`^Xmgpz*T@eaMn=41mu;KWptrP>=l#$qCpNpwiE1hYzRxkAdg%^gojF ze+RiKBXSBJ>7V+J4j(f1$DwmPccM^o&^X^!)XDE6ge3el>g0D5LK5CUoqU`SlJIv? zC%=afLVj7K^%3gi@r&&8&n?G0Hj>zXWBJY={yXyX19Xn@e#0l=f7tlH4xRoV$nak* ze=x&;wR~5H$9ee8@`nuX&g*Z>cV{>k6yrXe;p0d?`6C&A(DFS!yeQI|0>{7X&G4g^ zKMKxv=7;u0%lBpMwdMQC^WE{k2hQO;`-fCey>Gl6K`4)M4{Xau4G3P!?_SdrplaHqM z(R1LrJo#8^A3aZQ{EVgc(F+}(lfMvXpB?99$A9`9Fvn7h{?q5cH0_Q5LD@gh9VgBY zJKy*m_zW7)f!PjE=YeNPJpObZ4v`!G>2u)44v*LQ4&-PE>@W()bE>I4H`*-gD01uT zq0~+Pk0 z)s-Hwpu&oBbkbqb4I@>rXlwquRzb;Ab$zm04Rzw(_L(g=Fav98*`b(i$flgPEj1Os z^_uT!S@U$=S=AhCD3RWXnt@IxtLkp(M}gmPD=TqJD5@U0$2?bs$d816H7cnfaw{GO z3++w4t|Mip5@_W`ZcQ)isu#}=^IU`7n(KLMz6zXhNmcX$5*DbEAG)U3x$MZfX03Q~v8c~!PZ~Djvf8YuFe)@1#1s{x;~NdnSI!EemOU2<>w$%4wW@=% zdtOV>c>(1L-gkX{3Gd5UEWLv9M1CN8qvACk?X0K(o{{RP>IXHhhLUFHjk>6-s_AtW z1~xLqK1}^8Hb-Cj8R%!ApMib``WfhFpr3*NlL3Bd<`-ms8D7GLM~6|$4euQBy`ymq z)%;giuFSuG;lj~t+r{}mZ`_!tao2`gS3bRX(X{gt%NkPSZ^mDZF^;IZqCdj515U|xgGa?hnyve!@9^s0U!U# zBW>dLB;Noz2p&n!=!iDGdE}201+8%7uQol@`J)MKSh_wxC_uew%-B~?pH9pzGd~8q iSG-6=wS~E6(k3}y6xhsg`Nuq=T_0(dQeAO(PZ z06u*H7UKE1cC!Zm27`eRBvk3?ZmpN>_hU~Nqu$jw^_ssx+V1YfM9A*5FzNsZu*4id z$`2U_HU&VZ`yq@ZfCUAp)B3iCu7ba{(=nVB4wOxJG4jMRZX+qOWZK&J52-S-D6Q#W!kL+?A_3GzoJVf{h{fE zqIa0`q*TwFnocVE!V23XbeuNJJDSRXoX`T^2~&cpFbTA#_qx3qqc z^+e@w^C<5T;KHR5Lyz>wS}%|29REb?hjRLJtsl5oe1rwu%j0rSGR=6YU_zM$p6uL7ZJ!fd6E|wPgSR