今日、入社日でした。
Android,iOSの広告を引き継ぎます。
復習メモ
terminalでAndroid端末確認 adb devices
apkを端末インストール adb install -r ~/Desktop/Q_android.apk
AndroidJavaClass リフレクションを使いUnityでJavaクラスを使えるようにしている
AndroidJavaObject クラスの中のメンバ変数を参照させる、インスタンス
今日、入社日でした。
Android,iOSの広告を引き継ぎます。
復習メモ
terminalでAndroid端末確認 adb devices
apkを端末インストール adb install -r ~/Desktop/Q_android.apk
AndroidJavaClass リフレクションを使いUnityでJavaクラスを使えるようにしている
AndroidJavaObject クラスの中のメンバ変数を参照させる、インスタンス
HeadFirstの本を読んでStrategy Patternを覚えました。
色んなひよこを作るとき副作用無しで動きを柔軟に変更できるのが良いです。
メモ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
using UnityEngine; using System.Collections.Generic; using System.Collections; public class CharacterManager : MonoBehaviour { public IFlyBehavior flyBehavior; public void SetPerformFly(IFlyBehavior iFlyBehavior) { flyBehavior = iFlyBehavior; } public void PeformFly() { flyBehavior.Fly(); } } |
下は動かなかった
1 2 3 4 5 |
public IFlyBehavior flyBehavior { set{ flyBehavior = value;} get{ return flyBehavior;} } |
interfaceとinterfaceを継承したクラスを作成
.csは三つ作成
IFlyBehavior.cs
1 2 3 4 5 6 |
using UnityEngine; using System.Collections; public interface IFlyBehavior { void Fly(); } |
FlyNoWay.cs
1 2 3 4 5 6 7 8 9 10 11 12 |
using UnityEngine; using System.Collections; using UnityEngine; using System.Collections; public class FlyNoWay : IFlyBehavior { public void Fly() { Debug.Log("FlyNoWay"); } } |
FlyWithWings.cs
1 2 3 4 5 6 7 8 9 10 11 12 |
using UnityEngine; using System.Collections; using UnityEngine; using System.Collections; public class FlyWithWings : IFlyBehavior { public void Fly() { Debug.Log("FlyWithWings"); } } |
実装に対するプログラミング
とりあえず爆弾ひよこを作ってみる
3Dモデルと飛ぶ振る舞いの細かい中身は後にしてログだけ出す。
動的に飛ぶ振る舞いを変えれるようにAwake,Startで変更
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
using UnityEngine; using System.Collections; public class BombChick : ChickManager { void Awake () { SetPerformFly(new FlyWithWings()); base.PeformFly(); } void Start() { SetPerformFly(new FlyNoWay()); base.PeformFly(); } void Update () { } } |
UnityEditorで確認
FlyWithWings,FlyNoWayが呼ばれました^^
もし爆発振る舞いが欲しければChickManagerに追加すればよい、その時他のサブクラスには影響は無いですね。
前回作ったひよこ情報保存ですが仕組みが悪いので作り直しました。
各ひよこにある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; } |
BitMapNumを表示させるのに整理した。
1が含まれると右にずらさないといけないので面倒ですね。
各数字の親にはBitMapNumberManagerクラスを貼り付け
その下階層にはNumSettingsクラスを貼る
カゴに入った時のスコアは背景に卵があるのでEgg1も表示、非表示に対応できるようにNumSettingsクラスを新たに作りました。
BitMapNumberManagerの命令で『もし各UISpriteが子供を持っていたら表示、非表示」をすると分かりにくいと思って。
UpdateNumberメソッドに好きな数字を渡せば数字を表示する
each.Show(true)だけで下の階層が有る無し関わらず実行できる
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 |
using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; public class BitmapNumberManager : MonoBehaviour { private List<NumSettings> numSprites = new List<NumSettings>(); private float firstNumPosX; private const float initializeOffsetX = 38f; void Awake () { //Debug.Log("transform.childCount: " + transform.childCount); for (int i = 0; i < transform.childCount; i++) { //Debug.Log("transform.GetChild(i).name: " + transform.GetChild(i).name); numSprites.Add(transform.GetChild(i).GetComponent<NumSettings>()); } firstNumPosX = numSprites[0].transform.localPosition.x; } public void UpdateNumber(int refernce){ float posX = firstNumPosX; //initialize position X foreach(var each in numSprites){ each.gameObject.transform.setLocalPositionX(posX); posX -= initializeOffsetX; each.Show(false); //Debug.Log("each.name: " + each.name); } float offsetX = 20f; int offsetCount = 0; foreach(var each in numSprites) { //Debug.Log("refernce: " + refernce); if(refernce < 1) {return;} //Debug.Log("point: " + point); if(!each.activeSelf) {each.Show(true);} int currNum = refernce % 10; each.gameObject.transform.addLocalPositionX(offsetX * offsetCount); //Debug.Log("offsetCount: " + offsetCount ); each.SetSpriteName(currNum.ToString()); if(currNum == 1){ offsetCount +=1;} refernce /= 10; } } } |
各数字に貼るスクリプト
下の階層が有る無しを判断させてから処理
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 |
using UnityEngine; using System.Collections; public class NumSettings : MonoBehaviour { private UISprite sprite; private UISprite childSprite; private bool hasChild = false; public bool activeSelf{private set; get;} void Awake(){ sprite = GetComponent<UISprite>(); if(transform.childCount != 0){ hasChild = true; childSprite = transform.GetChild(0).GetComponent<UISprite>(); } activeSelf = sprite.enabled; } void Start () { } public void Show(bool onOff) { if(hasChild){ sprite.enabled = onOff; childSprite.enabled = onOff; } else{ sprite.enabled = onOff; } activeSelf = onOff; } public void SetSpriteName(string path){ sprite.spriteName = path; } void Update () { } } |
これ見てから機能の細分化せないかんなと思ったのでNumSettingsクラスを作った。
Managerクラスは単純な命令にして各オブジェクトで個性を判断させればいい感じになりそうだな。
MayaLTとUnityでゲームを作るムービー。
Mayaで作っているところを見ていると久しぶりに作りたくなりましたね。
Jointのtransform rotation 初期化は勉強になった。
UnityのMechanimが出来るとかっこいいな、今まで触ってなかったけど雰囲気は掴めた。
他メモ。
今日は今まで悩んでいたMacOSX YosemiteでのWifi不接続問題を下の記事で直して見た。
今のところ急に切れることがなく快適!
Facebookのウェブリンク貼ると自動で画像と見出し取ってくるの便利だなーと思っていてWordPressでないか調べたらありました!
今日からこれ使うぞ〜
今日はひよこゲームの続きを作っていた。
プログラムはコレクション実装、初めてゲット、2回目以降ゲットを分ける。
ひよこprefab作り直し
Mayaでひよこを奥に倒して顔がよく見えるように改善。
UnityではCapsuleCollider,BoxColliderを配置
AssetStoreの TexturePackerProでUV空間を編集します。
これがないとMayaでAtlasTexture用にUV編集するので膨大な作業になります(@_@)
Mayaでは下のようにUV空間0~1のままでFBX Export
TexturePackerでの編集画面
バラの画像を2048pxの画像にまとめる
テキストデータに_dataを加えるとTexturePackerProが認識してくれる。
これでアトラステクスチャーの各ヒヨコ絵にUVを合わせてくれる
文だとわかりにくいのでGIFにしてみた。
今日気づきました。
UnityEventはpublicじゃないとnull referenceになってしまいますね。
なんでだろ、publicにして[System.NonSerialized]も使えない。
Inspectorからの操作を誤操作を無くしたくprivateにしたいのですが…
[HideInspector]でいけました!
スコアに応じてパーセント表示を更新するコードを書きました。
ちょっと読みにくくなっているので綺麗に整形できればいいのですが..
UnityEventに慣れる為labelクラスのメソッドはUnityEventに登録させて呼びました。
今回はシーンに一つだけのクラスなので直にメソッドを読んでもよかったかもしれません。
UpdateLevelPercentageメソッドのUpdatePercentage.Invoke();でLabelManagerクラスのメソッドを呼びNGUI UISpriteの表示を変えています。
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 |
GameControllerクラス public UnityEvent UpdatePercentage; public static int NextLevelPercentage{private set; get;} void Start() { score.AddListener(AddScore); UpdateScoreAndLevel.AddListener(labelManager.updateLabelAction); UpdatePercentage.AddListener(labelManager.updatePercentageAction); } void AddScore(int chickScore) { Score += chickScore; Point += chickScore * 10; Debug.Log("Score: " + Score); UpdateLevelPercentage(); UpdateLevel(); //After update score and level you can call label action UpdateScoreAndLevel.Invoke(); } void UpdateLevelPercentage() { int nextLevel = Level + 1; float nextLevelScore = (float)(DATA.NextLevelScore[nextLevel]); float score = (float)Score; float untilNextScorePercentage = score / nextLevelScore; //Debug.Log("untilNextScorePercentage: " + untilNextScorePercentage); int storeNextLevelPercentage = NextLevelPercentage; //整数一桁を返す if(untilNextScorePercentage > 0.9 && untilNextScorePercentage < 1.0) NextLevelPercentage = 8; else NextLevelPercentage = Mathf.RoundToInt((untilNextScorePercentage) * 10); //整数を返す 0,2,4,6,8,10 if(NextLevelPercentage % 2 != 0) NextLevelPercentage -= 1; //割り切れた時を考慮 , It"s level up timing if(NextLevelPercentage >= 10) { NextLevelPercentage = 10; } Debug.Log("NextLevelPercentage: " + NextLevelPercentage); //更新した時だけラベル更新 またはレベルアップした次にかごに入る時 if(storeNextLevelPercentage < NextLevelPercentage || NextLevelPercentage == 10 || storeNextLevelPercentage == 10) UpdatePercentage.Invoke(); } void OnDestroy() { Debug.Log("GameController OnDestroy"); score.Dispose(); createCharNum.Dispose(); touchPos.Dispose(); UpdateScoreAndLevel.RemoveAllListeners(); UpdatePercentage.RemoveAllListeners(); } |
UnityEditorですと再生ボタンを押す時OnApplicationPauseが呼ばれるんですね。
これが原因でAwakeとOnApplicationPauseでLoadElapseDataが2回呼ばれてしまい、変数が初期化されてしまいました。
1日ハマった…
なので#if UNITY_EDITORではLoadElapseData()を呼ばないように使い分けしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void OnApplicationPause(bool pauseStatus) { //離れる時 if(pauseStatus) SaveToDisc(); //戻る時 else{ #if UNITY_EDITOR //ゲームシーンから再生時OnApplicationPauseが呼ばれてしまうのでLoadElapseData();を呼ばない Debug.Log("OnApplicationPause in UnityEditor"); #else Debug.Log("OnApplicationPause in except UnityEditor"); LoadElapseData(); #endif } } |
原因がわからない場合はとりあえずメソッドの中にログを書いとくと解決の糸口になりますね、勉強になりました。
全体
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 |
private const string SCOREKEY = "Score"; private const string LEVELKEY = "Level"; private const string POINTKEY = "Point"; private const string SAVEDFIRSTRUNKEY = "savedFirstRun"; private int checkFirstRun; public static int Score{private set; get;} private static int _point = 2000; public static int Point{ get{ return _point;} private set{ _point = value;} } private static int _level = 1; public static int Level{ get{ return _level;} private set{ _level = value;} } private bool isLoadedGame = false; void Awake() { LoadElapseData(); if(checkFirstRun == 0) { Point = 2000; Debug.Log("FirstLaunch: Point: " + Point); checkFirstRun = 1; } else{ } } void OnApplicationPause(bool pauseStatus) { //離れる時 if(pauseStatus) SaveToDisc(); //戻る時 else{ #if UNITY_EDITOR //ゲームシーンから再生時OnApplicationPauseが呼ばれてしまうのでLoadElapseData();を呼ばない Debug.Log("OnApplicationPause in UnityEditor"); #else Debug.Log("OnApplicationPause in except UnityEditor"); LoadElapseData(); #endif } } void OnApplicationQuit() { //gamesceneで止めるとなぜかtitleで読み込まれていることになる為、boolを作る if(isLoadedGame) SaveToDisc(); } void SaveToDisc() { Debug.Log("SaveToDisc"); createCharManager.SaveCharDataToDisc(); PlayerPrefs.SetInt( SCOREKEY, Score); PlayerPrefs.SetInt( LEVELKEY,Level); PlayerPrefs.SetInt( POINTKEY, Point); Debug.Log("Point: " + Point + " SaveToDisc"); PlayerPrefs.SetInt( SAVEDFIRSTRUNKEY, checkFirstRun); PlayerPrefs.Save(); } void LoadElapseData() { Debug.Log("LoadElapseData"); Score = PlayerPrefs.GetInt(SCOREKEY); Level = PlayerPrefs.GetInt(LEVELKEY); Point = PlayerPrefs.GetInt(POINTKEY); Debug.Log("Point: " + Point); checkFirstRun = PlayerPrefs.GetInt(SAVEDFIRSTRUNKEY); } |
uGUIのイベントコールバック登録をコードから行う方法とUnityActionデリゲート群
今までUnityActionの使い方がわかりませんでしたがいい記事を見つけたのである程度わかるようになりました。
今まではdelegateとeventで命令していましたがゲームを終えた時、ひよこより先にCharCreateManagerが消えるのでメソッドの解除時nullになっていました。
UnityEngine.Events.UnityEventはRemoveAllListenersで安全にメソッドの解除ができたのでよかったです。
リストを作ってシーンの全てのひよこ情報を追加する
discに保存するコードは省いてます。
シーンの全てのひよこに命令
CreateCharManagerはゲームシーンに一つ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class CreateCharManager : MonoBehaviour{ [System.NonSerialized] public List <Vector3> charPosList = new List<Vector3>(); [System.NonSerialized] public List <Vector3> charRotList = new List<Vector3>(); [System.NonSerialized] public List <int> charKindList = new List<int>(); [System.NonSerialized] public List <bool> isActiveBottomColliderOfCharList = new List<bool>(); public UnityEngine.Events.UnityEvent saveCharacterData; public void SaveCharDataToDisc(){ saveCharacterData.Invoke(); //delegate to all chicks in scene. } void OnDestroy () { saveCharacterData.RemoveAllListeners(); } } |
各ひよこは位置、回転、種類、コライダーのOnOFFをcreateCharManagerのリストに追加
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 |
public class ChickManager : CharacterManager{ void saveData() { createCharManager.charPosList.Add(thisTransform.localPosition); createCharManager.charRotList.Add(thisTransform.localRotation.eulerAngles); createCharManager.charKindList.Add(thisCharScore); if(boxCollider.enabled) createCharManager.isActiveBottomColliderOfCharList.Add (true); else createCharManager.isActiveBottomColliderOfCharList.Add (false); } void OnEnable(){ createCharManager.saveCharacterData.AddListener(saveData); } void OnDisable(){ UnSubscribeEvent(); } void OnDestroy(){ UnSubscribeEvent(); } void UnSubscribeEvent(){ createCharManager.saveCharacterData.RemoveListener(saveData); } } |
projectはここにあります。
GitHub project