前回作ったひよこ情報保存ですが仕組みが悪いので作り直しました。
UnityActionについて | ゲームでヒットさせてハワイに住むまでhttp://rainbow23.jp/?p=25今までUnityActionの使い方がわかりませんでしたがいい記事を見つけたのである程度わかるようになりました。
各ひよこにあるChickManagerオブジェクトがCreateCharManagerクラスにあるリストに自分の情報を追加としてましたがリストがpublicなので情報が他のオブジェクトに漏れて危なかったです。
今回はDataEventクラスを作り保存、復元を全て任せました。
命令はGameControllerクラスから受けてます。
GameControllerクラス 関係ない箇所は削除して記載
簡素にSave,Loadメソッド名にしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.Events; using System.Linq; /// <summary> /// ゲームのステータスや状況を管理 /// </summary> public class GameController : MonoBehaviour//SingletonMonoBehaviour<GameController> { public int[] obtainedCharArray; private enum State{ firstGet, got}; private bool isLoadedGame = false; DataEvent dataEvent; CreateCharManager createCharManager; AudioManager audioManager; LabelManager labelManager; FunctionManager functionManager; [HideInInspector] public UnityEvent UpdatePercentage; [HideInInspector] public UnityEvent UpdateScoreAndLevel; //private NotificationObject<int> _score = new NotificationObject<int>(0); //public NotificationObject<int> score { get{ return _score; }} public ScoreObject<int, Vector3> scoreObject = new ScoreObject<int, Vector3>(); private NotificationObject<Vector3> _touchPos = new NotificationObject<Vector3>(); public NotificationObject<Vector3> touchPos{ get{ return _touchPos; }} private NotificationObject<int> _createCharNum = new NotificationObject<int>(0); public NotificationObject<int> createCharNum{ get{ return _createCharNum; }} void Awake() { dataEvent = GameObject.Find("DataEvent").GetComponent<DataEvent>(); Load(); if(DATA.CheckFirstRun == false) { Debug.Log("FirstLaunch"); obtainedCharArray = new int[DATA.ResourcesChickNum]; DATA.Point = 2000; DATA.Level = 1; DATA.Score = 0; DATA.CheckFirstRun = true; } else{ } Application.targetFrameRate = 60; isLoadedGame = true; audioManager = GameObject.Find("AudioManager").GetComponent<AudioManager>(); createCharManager = GameObject.Find("CreateCharManager").GetComponent<CreateCharManager>(); labelManager = GameObject.Find("LabelManager").GetComponent<LabelManager>(); functionManager = GameObject.Find("Background").GetComponent<FunctionManager>(); } void Start() { scoreObject.AddListener(AddScore); createCharNum.AddListener(audioManager.PlayTouchSE); UpdateScoreAndLevel.AddListener(labelManager.updateLabelAction); UpdatePercentage.AddListener(labelManager.updatePercentageAction); touchPos.AddListener(createCharManager.Create); //Destroyで保存すると他のオブジェクトが削除されていてうまく保存できないので //ボタンを押した時に保存する functionManager.sceneTransitionEvent.AddListener(Save); } void OnApplicationPause(bool pauseStatus) { //離れる時 if(pauseStatus){ #if UNITY_EDITOR //ゲームシーンから再生時OnApplicationPauseが呼ばれてしまう Debug.Log("OnApplicationPause go away in UnityEditor"); #endif Save(); } //戻る時 else{ #if UNITY_EDITOR //ゲームシーンから再生時OnApplicationPauseが呼ばれてしまうのでLoad();を呼ばない Debug.Log("OnApplicationPause come back in UnityEditor"); #else Debug.Log("OnApplicationPause in except UnityEditor"); Load(); #endif } } void OnApplicationQuit() { Debug.Log("OnApplicationQuit"); //gamesceneで止めるとなぜかtitleで読み込まれていることになる為、boolを作る if(isLoadedGame) { Save(); } } void Save() { Debug.Log("Save"); PlayerPrefsX.SetIntArray(DATA.OBTAINEDCHARKEY, obtainedCharArray); PlayerPrefs.Save(); dataEvent.SaveGameData(); } //経過時間を保存する void Load() { Debug.Log("Load"); obtainedCharArray = PlayerPrefsX.GetIntArray(DATA.OBTAINEDCHARKEY); for(int i =0; i < obtainedCharArray.Length; i++) { //Debug.Log("Load obtainedCharArray[" + i + "]: " + obtainedCharArray[i]); } dataEvent.LoadGameData(); } } |
DataEventクラス
1 |
Transform poolPlace = createCharManager.poolCharPlace.transform; |
の階層下にひよこを全部作っている。
復元するときも同じ場所にしないといけない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; public class DataEvent :MonoBehaviour { private const string CharPosKey = "CharPosKey"; private const string CharRotKey = "CharRotKey"; private const string CharKindKey = "CharKindKey"; private const string CharBottomColliderKey = "CharBottomColliderKey"; private CreateCharManager createCharManager; void Awake() { createCharManager = GameObject.Find("CreateCharManager").GetComponent<CreateCharManager>(); } private void SaveChar() { Transform poolPlace = createCharManager.poolCharPlace.transform; List<GameObject> objList = new List<GameObject>(); for (int i = 0; i < poolPlace.childCount; i++) { objList.Add(poolPlace.GetChild(i).gameObject); } var activeObj = from item in objList where item.activeSelf == true select item; CharInfo(activeObj.ToArray()); } private void CharInfo(GameObject[] objList) { List<Vector3> posList = new List<Vector3>(); List<Vector3> rotList = new List<Vector3>(); List<int> charKindList = new List<int>(); List<bool> charBottomColliderList = new List<bool>(); foreach (var obj in objList ) { ChickManager chickManager = obj.GetComponent<ChickManager>(); posList.Add (obj.transform.position); rotList.Add(obj.transform.rotation.eulerAngles); charKindList.Add(chickManager.thisCharNum); charBottomColliderList.Add(chickManager.boxCollider.enabled); } //position PlayerPrefsX.SetVector3Array(CharPosKey, posList.ToArray()); //rotation PlayerPrefsX.SetVector3Array(CharRotKey, rotList.ToArray()); //kind PlayerPrefsX.SetIntArray(CharKindKey, charKindList.ToArray()); //bottomCollider PlayerPrefsX.SetBoolArray (CharBottomColliderKey, charBottomColliderList.ToArray()); PlayerPrefs.Save(); } public void SaveGameData() { //Debug.Log("SaveGameData"); PlayerPrefs.SetInt( DATA.SCOREKEY, DATA.Score); PlayerPrefs.SetInt( DATA.LEVELKEY,DATA.Level); PlayerPrefs.SetInt( DATA.POINTKEY, DATA.Point); PlayerPrefs.SetInt( DATA.SAVEDFIRSTRUNKEY, System.Convert.ToInt32(DATA.CheckFirstRun)); PlayerPrefs.SetInt( DATA.NEXTLEVELPERCENTAGEKEY, DATA.NextLevelPercentage); SaveChar(); PlayerPrefs.Save(); //Debug.Log("Level: " + Level ); //Debug.Log("DATA.CheckFirstRun: " + DATA.CheckFirstRun ); //Debug.Log("Point: " + Point); } private void LoadChar() { Vector3[] charPos = PlayerPrefsX.GetVector3Array(CharPosKey); Vector3[] charRot = PlayerPrefsX.GetVector3Array(CharRotKey); int[] charKind = PlayerPrefsX.GetIntArray(CharKindKey); bool[] charBottomCollider = PlayerPrefsX.GetBoolArray(CharBottomColliderKey); //restore chick for(int i =0; i < charPos.Length; i++) { RestoreChar(charPos[i], charRot[i], charKind[i], charBottomCollider[i]); } Debug.Log("LoadChar"); } private void RestoreChar(Vector3 pos, Vector3 rot, int kind, bool bottomCollider) { GameObject referenceChar = createCharManager.resourcesLoadChickDic[kind]; if(createCharManager.resourcesLoadChickDic.ContainsKey(kind)) { GameObject obj = Instantiate(referenceChar, pos, Quaternion.Euler(rot)) as GameObject; obj.name = referenceChar.name; obj.transform.parent = createCharManager.poolCharPlace; if(!bottomCollider) obj.GetComponentInChildren<BoxCollider>().enabled = false; } else{ Debug.Log(kind + " key isn't exist");} } public void LoadGameData() { //Debug.Log("LoadGameData"); DATA.Score = PlayerPrefs.GetInt(DATA.SCOREKEY); DATA.Level = PlayerPrefs.GetInt(DATA.LEVELKEY); DATA.Point = PlayerPrefs.GetInt(DATA.POINTKEY); DATA.CheckFirstRun = System.Convert.ToBoolean(PlayerPrefs.GetInt(DATA.SAVEDFIRSTRUNKEY)); DATA.NextLevelPercentage = PlayerPrefs.GetInt(DATA.NEXTLEVELPERCENTAGEKEY); LoadChar(); //Debug.Log("DATA.Level: " + DATA.Level ); //Debug.Log("DATA.CheckFirstRun: " + DATA.CheckFirstRun ); //Debug.Log("DATA.Point: " + DATA.Point); } } |
ひよこを作る仕組みはPoolに変更しました。
新しいひよこが作られるたびPoolコンポーネントが増えます。
掃除実行は初期設定のままで問題無いですね。
GetInstanceメソッドで元の記述がreturn nullでエラーが出ていたので修正しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public GameObject GetInstance (Transform parentInfo) { pooledObjectList.RemoveAll( (obj) => obj == null); foreach (GameObject obj in pooledObjectList) { if (obj.activeSelf == false) { obj.SetActive (true); return obj; } } //if (pooledObjectList.Count < maxCount) { GameObject obj2 = (GameObject)GameObject.Instantiate (prefab); obj2.SetActive (true); obj2.transform.parent = parentInfo; pooledObjectList.Add (obj2); return obj2; //} //return null; } |
新・オブジェクトプール – テラシュールブログhttp://tsubakit1.hateblo.jp/entry/20140309/1394296581オブジェクトプールを新しく自作した。前に作ったオブジェクトプール [Unity3D]オブジェクトプール作ってみたオブジェクトプールとはオブジェクトの生成・破棄を回避するギミック。基本的にオブジェクトやインスタンスの生成・破棄はパフォーマンスに影響を与える候補の中で上位にあり、特にマネージドコード上で動作するUnityはこの影響が顕著に出る。 使わなくなったら破棄するのではなく、キャッシュしておき使用するタイミングで初期化・再配置するオブジェクトプールがパフォーマンスの改善に役立つことがある。 使い方 Pool.csをプロジェクトの適当なフォルダに配置後、下のコードのようなコードを記述。// p…