何故か.cのワイルドカードが使えなかった。
git add *.c
.txt .logはインデックスに追加できた。
シングルコーテーションで囲えばインデックスに追加されました。
git add ‘*.c’
参考
http://stackoverflow.com/questions/12066184/git-add-using-wildcard-is-not-functioning-as-i-hoped-must-i-cd-into-specific
何故か.cのワイルドカードが使えなかった。
git add *.c
.txt .logはインデックスに追加できた。
シングルコーテーションで囲えばインデックスに追加されました。
git add ‘*.c’
参考
http://stackoverflow.com/questions/12066184/git-add-using-wildcard-is-not-functioning-as-i-hoped-must-i-cd-into-specific
今日、入社日でした。
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に追加すればよい、その時他のサブクラスには影響は無いですね。
今日は久しぶりにiPhoneアプリの勉強。
コードでviewの拘束をどのように書くか復習してました。
この例が分かりやすかった。
centerViewの右から20pxのところに位置する縦横44pxのrightButton
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 |
self.rightButton.setTranslatesAutoresizingMaskIntoConstraints(false) self.navigationView.addConstraints([ // centerViewの右から20pxのところに配置 NSLayoutConstraint( item: self.rightButton, attribute: .Left, relatedBy: .Equal, toItem: self.centerView, attribute: .Right, multiplier: 1.0, constant: 20 ), // center.yはcenterViewと同じ NSLayoutConstraint( item: self.rightButton, attribute: .CenterY, relatedBy: .Equal, toItem: self.centerView, attribute: .CenterY, multiplier: 1.0, constant: 0 ), // 横(固定) NSLayoutConstraint( item: self.rightButton, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1.0, constant: 44 ), // 縦(固定) NSLayoutConstraint( item: self.rightButton, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1.0, constant: 44 )] ) |
コメント書いて思い出しやすいようにした
1 2 3 4 5 6 7 8 9 |
NSLayoutConstraint( item: self.rightButton,//対象とするbutton or view attribute: .Left,//self.rightButtonの左側を拘束する relatedBy: .Equal,//よくわからない toItem: self.centerView,//基準となるview attribute: .Right,//基準となるviewの右側に対しself.rightButtonは拘束される multiplier: 1.0, constant: 20//20pixel移動させる ), |
なかなか進みませんがViewのあとイベント駆動を勉強します。
この本で勉強してます。
iOSが裏で何をしているか書いているので基礎ができて良いです。
前回作ったひよこ情報保存ですが仕組みが悪いので作り直しました。
各ひよこにある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クラスは単純な命令にして各オブジェクトで個性を判断させればいい感じになりそうだな。
iPhone/iPadアプリケーション開発の教科書 は120ページまで読んだ。
UIに関しても勉強です。
動画を画面に載せれるようにするまでは頑張らなくては。
つまずいた箇所メモ
1 2 3 4 5 6 |
let button = UIButton.buttonWithType(UIButtonType.System) as UIButton button.frame = CGRect(x: 0, y: 0, width: 50, height: 44) button.setTitle("開く", forState: UIControlState.Normal) button.addTarget(self, action: "respondToButtonClick:", forControlEvents:UIControlEvents.TouchUpInside) |
button.addTargetのaction引数は下だとエラーになるのね、
:が欲しいみたい
よくわからないけど..
1 2 3 |
button.addTarget(self, action: "respondToButtonClick", forControlEvents:UIControlEvents.TouchUpInside) |
今日はひよこゲームの続きを作っていた。
プログラムはコレクション実装、初めてゲット、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(); } |