見出し画像

ダンスゲーを作りたい#44 【標準化】キャラクターアイコンのテンプレート

前回まででプレイが出来るようになりました。

設定画面の時とかにちらほら必要に迫られるも放置していたCharacterアイコンとか、Character一覧とか、その辺を標準化していきます。

キャラクターアイコンのテンプレート

機能としては、

・IDセットでアイコン画像自動取得、表示
・単押しで選択し、キャラIDをネクストアクションに渡す
・長押しで詳細表示
・Newとかみたいな要素はKey指定で追加可能

ができるようにします。

構成として、まずキャラアイコンのプレハブを作ります。

画像1

押せる部分を担当するボタンと、枠を担当するパネル、以下はNewとか表示するためのパネルで、追加したい場合下にパネルを増やしてそれぞれの親パネルにはcanvasgroupを追加してalphaを0にしておきます。

そして全体の親につけるスクリプトをを書きます。

public class Charactor_icon_script : MonoBehaviour {
   Manager Manager{
       get{return GameObject.Find("Manager").GetComponent<Manager>();}
   }
   string __id = "";
   public async void SetID(string ID , Sprite Image ,float size){
       __id=ID;
       if(size>0f){
           GetComponent<RectTransform>().sizeDelta   =   new Vector2(size,size);
       }
       if(Image==null){    
           this.transform.GetChild(0).transform.gameObject.GetComponent<Image>().sprite  = await getImage(ID);
       }else{
           this.transform.GetChild(0).transform.gameObject.GetComponent<Image>().sprite  =  Image;
       }
   }
   
   public void SetOption(int key,bool visivility){
       CanvasGroup Object = this.transform.GetChild(key).transform.gameObject.GetComponent<CanvasGroup>();
       if(visivility){
           Object.alpha = 1f;
       }else{
           Object.alpha = 0f;
       }
   }
   
   Action<string> __ontapaction;
   public void OnTap(Action<string> Action){
       __ontapaction=Action;               
   }
   
   bool isTaping = false;
   Stopwatch sw;
   public async void OnTap(){
       isTaping=true;
       await Task.Run(()=>{
           sw = new Stopwatch();
           sw.Start();
           while(true){
               if(!isTaping){
                   sw.Stop();
                   break;
               }
               if(sw.ElapsedMilliseconds>700){
                   sw.Stop();
                   break;
               }
           }
       });
       if(isTaping){
           isTaping=false; 
           OnLongTap();
       }
   }
   public void OnTapUP(){
       if(isTaping){
           if(__ontapaction!=null){
               __ontapaction(__id);
           }
       }
       isTaping=false;
   }
   
   void OnLongTap(){
       GameObject area = GameObject.Find("詳細画面表示用のcanvas");
       foreach (Transform c in area.transform) {
           Destroy (c.gameObject,0);
       }
       GameObject __prefab = (GameObject)Resources.Load("詳細画面のプレハブ");
       GameObject obj = Instantiate(__prefab) as GameObject;
       obj.transform.SetParent(area.transform, false);
   }
   
   public async Task<Sprite> getImage(string ID){
       /*
       IDからサーバとかに問い合わせるなりローカルから引っ張るなりして
       イメージを取得し、Spriteにして返す処理
       これはローカルから引っ張る場合
       */
       retrun Resources.Load<Sprite>("パス/"+ID); 
   }

}

外からのアクセスについては、表示するキャラとサイズを指定するSetIDとNewとか表示するかしないかを個別に設定できるSetOption、シングルタップされた際に呼ばれるアクションを設定するOnTapが存在します。

特にポイントはロングタップを見分ける方法でしょうか。

まずボタンにイベントトリガを追加して、タップダウンとタップアップを判定できるようにします。

画像2

タップダウンされたら別スレッドで時間を計測します。計測は以前使ったストップウォッチでやります。

一定時間(ここでは700ms)経過するかタップアップされた時、Bool値を判定してロングタップとシングルタップを振り分けます。

一定時間経過した場合はロングタップ扱いで詳細画面を表示、タップアップが先の場合はシングルタップ扱いであらかじめ指定したアクションが呼ばれます。

選択した段階でデータマネージャにID経由で一時データを保存するのが道理ですが、あくまでキャラアイコンのためキャラIDとビルドIDのすり合わせが面倒なので、それぞれネクストアクションでIDをもとにデータの処理をする形式にします。

そして、

public class TmpObject : MonoBehaviour{
   public GameObject CharacterIcon(string ID,float size=100f,Sprite Image=null){
       GameObject __prefab = (GameObject)Resources.Load("キャラアイコンのプレハブのパス");
       GameObject obj = Instantiate(__prefab) as GameObject;
       obj.GetComponent<Charactor_icon_script>().SetID(ID,Image,size);
       return obj;
   }
}

こんな感じでオブジェクト作成用のスクリプトを作り、独自実装のマネージャに登録して呼び出せるようにしたら、

//マネージャ経由でアイコンオブジェクトを生成
GameObject ICO = Manager.TmpObject.CharacterIcon("C01902901",500f);
//例えばNew(=2 staticクラスにでもまとめたらいい)を表示させる
ICO.GetComponent<Charactor_icon_script>().SetOption(2,true);
//タップ時の処理を追加(引き数でIDを渡してくれるAction)
ICO.GetComponent<Charactor_icon_script>().OnTap((id)=>{
   Debug.Log("シングルタップで処理が動きます: ID: "+id);
});
//親要素の中に入れる
ICO.transform.SetParent(GameObject.Find("Layer1").transform, false);

こんな感じでキャラアイコンが呼び出せて、

画像3

画像4

シングルタップでは登録した通りログが出て、ロングタップで中身は作ってないので白いですが詳細画面が表示されます。

キャラリスト

キャラアイコンが単体で欲しいこともありますが、どちらかというとキャラ一覧の方が使います。なのでさっき作ったアイコンを一覧表示するリストも同じように標準化します。

オブジェクト構成は、キャラリストであることを示すタイトルパネルとキャラリストそのもの、戻るボタンを設定します。

画像6

スクリプトはこんな感じ

public class Character_List_script : MonoBehaviour{
   Manager Manager{
       get{return GameObject.Find("Manager").GetComponent<Manager>();}
   }
   public async void Set(){
       float w = Screen.width/10f;
       float h = Screen.height/10f;
       
       //サイズ感を設定
       this.transform.GetChild(0).gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(w*9f,h*7f);
       RectTransform title = this.transform.GetChild(0).GetChild(0).transform.gameObject.GetComponent<RectTransform>();
       title.sizeDelta = new Vector2(w*9f,w*1.5f);
       title.localPosition = new Vector2(0f,h*3.5f - w*0.75f);
       RectTransform BTarea = this.transform.GetChild(0).GetChild(2).transform.gameObject.GetComponent<RectTransform>();
       BTarea.sizeDelta = new Vector2(w*9f,w*1.5f);
       BTarea.localPosition = new Vector2(0f,-h*3.5f + w*0.75f);
       RectTransform list = this.transform.GetChild(0).GetChild(1).transform.gameObject.GetComponent<RectTransform>();
       list.sizeDelta = new Vector2(w*8f,h*7f - w*3f);
       list.localPosition = new Vector2(0f,0f);
       RectTransform BT = this.transform.GetChild(0).GetChild(2).GetChild(0).gameObject.GetComponent<RectTransform>();
       BT.sizeDelta = new Vector2(w*5f,w*1.5f);
       BT.localPosition = new Vector2(0f,0f);        
       float size = w*7.5f/4f;
       float mrgine = w*0.5f/3f;
       GameObject CA = GameObject.Find("CLPU_Contentarea");
       CA.GetComponent<GridLayoutGroup>().spacing = new Vector2(mrgine,mrgine*2f);
       CA.GetComponent<GridLayoutGroup>().cellSize = new Vector2(size,size);
       
       //持ってるキャラ情報を取得
       BuildDataList Data = await Manager.GameDataManager.GetData<BuildDataList>(new BuildDataList());
       //持ってるキャラ一覧アイコンを作成
       foreach(BuildData data in Data.List){
           GameObject ICO = Manager.TmpObject.CharacterIcon(data.CharaID,size);
           ICO.GetComponent<Charactor_icon_script>().OnTap((id)=>{
               OnIconTap(id);
           });
           ICO.transform.SetParent(CA.transform, false);
       }
   }
   
   //タップ時のアクションを実行
   Action<string> __action;
   public void OnTap(Action<string> action){
       __action = action;
   }
   void OnIconTap(string id){
       if(__action!=null){
           __action(id);
       }
   }
   
   public void OnBackBT(){
       GetComponent<CanvasGroup>().DOFade(0f,0.5f).OnComplete(()=>{
           Destroy (this.gameObject,0);
       });
   }
   
}

さっきと同様マネージャ経由で呼び出しますが、このリストは表示用のcanvasを別途用意し、呼び出し時にそこにハメて、オブジェクトも返してくれるようにします。

    public GameObject PrintCharacterList(){
       GameObject __prefab = (GameObject)Resources.Load(ConfigDatas.prefabTempPath+"Template/CharacterList/CharactorList");
       GameObject obj = Instantiate(__prefab) as GameObject;
       obj.GetComponent<Character_List_script>().Set();
       obj.transform.SetParent(GameObject.Find("ListPopup").transform, false);
       return obj;
   }

なので、呼び出し方的には

//こうすると表示してくれる
Manager.TmpObject.PrintCharacterList();


//表示&オブジェクト取得はこう ただし表示済みでバッティングした場合はnullが来る
GameObject ICO = Manager.TmpObject.PrintCharacterList();
ICO.GetComponent<Character_List_script>().OnTap((id)=>{
   Debug.Log(id);
});

こんな感じです。

リスト表示したらこんな感じ

画像6

画像7

各アイコンは自分のIDを持つので、シングルタップではそれぞれ別のIDが表示されてます。アイコンは素材を共通にしてるので一緒ですが、個別に取得処理が走るはずです。

別段載せませんが技アイコンもキャラと全く同じ仕様で作る予定です。

これでビルド画面とかキャラ選択画面とかが非常に楽に作れるようになる見込みです。

今回は以上。そろそろガチャ作んないとね。

この記事が気に入ったらサポートをしてみませんか?