はこねのはこ

はこねさんの備忘録

Unity Invokeの使い方メモ

はじめに

普段Unity開発してた時に、なんとなく使ってたInvoke
現在セットされているかや、キャンセルの仕方等がわかっていなかったので、 やり方を確認しました。
その時のメモです。

Invoke使い方

セットする

Invoke("CallFunction",5)

Invoke(関数名,時間)で実行します。
時間の単位は秒です。
5とすると5秒になります。
0.5fとすると0.5秒になります。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }

f:id:hakonebox:20181013210918p:plain
5秒後に実行されました。

セットされているか確認する

IsInvoking("CallFunction")

isInvoking(関数名)を使用します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",10);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log(IsInvoking("CallFunction"));
        }

    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }

f:id:hakonebox:20181013210546p:plain
セットされている場合には戻り値はTrueになります。
CallFunction関数が実行後は戻り値はFalseになります。

キャンセルする

特定の関数のみキャンセルする

CancelInvoke("CallFunction")

cancelInvoke(関数名)を使用します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
            Invoke("CallFunctionCheck",5);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log("キャンセルしました。");
            CancelInvoke("CallFunction");
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }
    void CallFunctionCheck()
    {
        Debug.Log("(確認用)時間が経過しました。");
    }

f:id:hakonebox:20181013211554p:plain
キャンセルしたCallFunction関数は実行されず、 CallFunctionCheck関数のみが実行されました。

全てキャンセルする

CancelInvoke()

cancelInvoke()引数なしで実行します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
            Invoke("CallFunctionCheck",5);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log("キャンセルしました。");
            CancelInvoke();
        }
        if (Input.GetKeyDown(KeyCode.T))
        {
            Debug.Log("経過時間確認用");
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }
    void CallFunctionCheck()
    {
        Debug.Log("(確認用)時間が経過しました。");
    }

f:id:hakonebox:20181013212226p:plain

CallFunction関数もCallFunctionCheck関数も実行されませんでした。

おわりに

Invokeは使いやすくて私は好きです。

はてなブログにGoogleアナリティクスを導入する

はじめに

アクセス解析をみていて、どんな検索ワードで、どんなルートでこのページに辿り着いているのかを知りたいと思いました。

どうやらGoogleアナリティクスが良いらしいので導入してみようと思います。

導入したその時のメモです。

f:id:hakonebox:20181012192029j:plain

導入してみる

アナリティクスの申し込み

marketingplatform.google.com

公式のページからGoogle アナリティクスの使用を開始の申し込みをします。

ラッキングIDの取得

必要事項を記入するだけでした。 登録が終わるとトラッキングIDが表示されました。 f:id:hakonebox:20181012190532p:plain

はてなブログに登録する

設定→詳細設定を開き、 f:id:hakonebox:20181012193033p:plain

解析ツール→Google Analytics 埋め込みに 先ほど取得したIDを貼り付け f:id:hakonebox:20181012191142p:plain

ページ最後の"変更する"を押して設定完了です。

おわりに

思ったよりも簡単に導入できました。
本当に導入できたか不安になるくらいです。
しばらく使ってみようと思います。

HTML,Javascriptでブラウザで動く4択問題集アプリを作ってみた。(CSV読み込み)

はじめに

今日、仕事中に5時間弱ぽっかりと時間ができました。
Javascriptは以前にねこアプリを作って以来1年ほど全く触っていなかったのですが、またなにかしら遊んでみようと思い、 5時間である程度動くところまで開発するチャレンジをしてみました。

JSはしっかりと勉強したことはなく、ググりながらゴリ押しで作っているので、そのへんご了承ください。
また、このスクリプトに関しての解説は全くありません。
また、検査等もほぼほぼ行っていません。

なぜ4択問題集アプリ?

タイトルにもあるように、4択問題集アプリを作りました。
社内でちょっとした年2回試験があるのですが、それの対策のために問題集アプリをちょうど欲しいと思っていました。

できました。

GitHub

github.com

こんな感じで動きます

JS Question 4

index.html

<!DOCTYPE HTML>
<html>
<head>
   <meta charset="utf-8">
   <title>JS Question 4</title>
   <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<script type="text/javascript">
   // 読み込んだデータを1行ずつ格納する配列
   var allData = [];
   var sW,sH,s;
   var now_question = 0;
   if (window.File && window.FileReader && window.FileList && window.Blob) {
   //alert('JS対応');
   } else {
   alert('JS未対応のブラウザです。たぶん動作しません');
   }

   loadCSV("./data.csv");
   setTimeout("setQuestion(now_question)", 10);//ms //一瞬間隔がないとダメみたい

   //ウィンドウサイズを取得する
   function getWindowSize() {
       sW = window.innerWidth;
       sH = window.innerHeight;
   }

   function setQuestion(number){
       document.getElementById("id_question").innerHTML=allData[number].question;
       document.getElementById("id_ChoiceA").innerHTML=allData[number].A;
       document.getElementById("id_ChoiceB").innerHTML=allData[number].B;
       document.getElementById("id_ChoiceC").innerHTML=allData[number].C;
       document.getElementById("id_ChoiceD").innerHTML=allData[number].D;
       if(allData[now_question].Q_gazo != 'none'){
           mondairesize();
           document.getElementById("id_mondaigazo").src='./gazo/'+allData[now_question].Q_gazo;
       }else{
           document.getElementById("id_mondaigazo").scr='';
           document.getElementById("id_mondaigazo").width=0;
       }
       document.getElementById("id_pf").innerHTML='';
       document.getElementById("id_kotae").innerHTML='';
       document.getElementById("id_mondaigazo").scr='';
       document.getElementById("id_kaitougazo").src='';
   }

   function next_question(){
       //現状ではループさせている
       if(allData.length-1 > now_question){
           now_question++;
       }else{
           now_question = 0;
       }
       setQuestion(now_question);
   }

   function kaitouresize(){
       getWindowSize();
       document.getElementById("id_kaitougazo").width=sW;
   }
   function mondairesize(){
       getWindowSize();
       document.getElementById("id_mondaigazo").width=sW;
   }

   function myCheck(){
       var seikai = allData[now_question].ANS;
       var kaitou = '';

       if(document.form1.elements[0].checked){
           kaitou = kaitou + 'A';
       }
       if(document.form1.elements[1].checked){
           kaitou = kaitou + 'B';
       }
       if(document.form1.elements[2].checked){
           kaitou = kaitou + 'C';
       }
       if(document.form1.elements[3].checked){
           kaitou = kaitou + 'D';
       }

       if(kaitou == seikai){
           document.getElementById("id_pf").innerHTML='正解です';
       }else{
           // 不正解の時は背景色を変えたい
           document.getElementById("id_pf").innerHTML='不正解です';
       }
       getWindowSize();
       document.getElementById("id_kotae").innerHTML=seikai;
       document.getElementById("id_kaitougazo").width=sW;
       if(allData[now_question].A_gazo != 'none'){
           document.getElementById("id_kaitougazo").src='./gazo/'+allData[now_question].A_gazo;
       }
   }

   function loadCSV(targetFile) {
       var request = new XMLHttpRequest();
       request.open("get", targetFile, false);
       request.send(null);
       var csvData = request.responseText;
       var lines = csvData.split("\n");
       for (var i = 0; i < lines.length; i++) {
           var wordSet = lines[i].split(",");
           var wordData = {
               question: wordSet[0],
               A: wordSet[1],
               B: wordSet[2],
               C: wordSet[3],
               D: wordSet[4],
               ANS: wordSet[5],
               Q_gazo: wordSet[6],
               A_gazo: wordSet[7],
           };
           allData.push(wordData);
       }
}

</script>
<body>
    <section>
        <hgroup>
            <h1>JS Question</h1>
        </hgroup>
        <section class="section-sub">
            <h4>問題</h4>
            <P id='id_question'>起動中</P>
            <img src="" alt="" id="id_mondaigazo" width="100" onclick="mondairesize();" />
            <form name="form1">
                <input type="checkbox" name="questions" value="A"><label id='id_ChoiceA'>A:選択肢A</label><br>
            <input type="checkbox" name="questions" value="B"><label id='id_ChoiceB'>B:選択肢B</label><br>
            <input type="checkbox" name="questions" value="C"><label id='id_ChoiceC'>C:選択肢C</label><br>
            <input type="checkbox" name="questions" value="D"><label id='id_ChoiceD'>D:選択肢D</label><br>
            <input type="button" value="解答" onclick="myCheck();">
            </form>
        </section>
        <section class="section-sub">
            <h4>解答</h4>
            <p id='id_pf'>-</p>
            <p id='id_kotae'>-</p>
            <img src="" alt="" id="id_kaitougazo" width="100" onclick="kaitouresize()" />
            <form name="form2">
            <input type="button" value="次の問題へ" onclick="next_question()" >
            </form>
        </section>
        <p>画像をクリックでサイズウィンドウ横幅に合わせます</p>
</body>

styles.css

.section-sub{
    background-color: #d8bfd8;
}

つかいかた

CSVに問題と選択肢、解答、参考画像の設定をします。
回答はA,B,AB,BCDなど、どれか一つ選ぶ問題でも複数選ぶ問題も対応しています。
問題の参考画像、解説の参考画像を載せたい場合は、 "gazo"というフォルダを作成し、そこに載せたい画像を保存します。 CSVに画像ファイル名を記載すれば表示できます。
記載しない場合はnoneと記載してください。

5時間チャレンジで達成できなかったこと

またぽっかり時間ができたら更新します。

おまけ宣伝ねこアプリ(クリーンキャット)

1年前に作成したアプリ。
それは癒しのwebアプリ。
たぶん仕事以外に初めて公開したアプリ。 github.com

https://yuikanoyu.github.io/cleanCat/

GitHubで有料プランに登録して毎日の進捗のチェックリストにしている話

はじめに

GitHubに課金して、およそ1.5ヵ月ほど経過しました。
草生やすの楽しいです。

※注意

この記事は、チームでGitHubを運用した話ではなく、個人でしかもプライベート運用の話です。 職場では使えないので...。

GitHub有料プラン

f:id:hakonebox:20181010233404p:plain 私は個人での運用なのでDeveloperプランです。 月額$7で無制限のプライベートリポジトリが使用できます。

なぜ有料プランにしようと思ったか

以前読んだ"独学プログラマー"という本にこのようなチャレンジがありました。

プログラミングの練習を毎日継続できるようにするためのチェックリストを作ろう。

これを実現するために、カレンダーにシールを張ったりとか、excelのような表計算ソフトも考えましたが、なるべく手間をかけずに実現したかったので、プッシュするだけで草が生えて記録となるGitHubを使おうと思いました。

しかし、無料プランではプライベートリポジトリが作成できません。
個人で開発中のものやテキストを使いながら作成したプロジェクトはプッシュしたくなかったので、試しに有料プランに登録してプライベートリポジトリ運用をしてみようと思いました。

プッシュ内容について

プログラミングの練習とありますが、何かしら自己開発で進捗があるものは全てリモートリポジトリを作成するようにして、パソコンに向かってコードを打ち込むほぼ全てを対象にしました。

意識していること

  • 改行やコメントなど、頭を使わない変更をだけでコミット&プッシュしない。

  • 明日の自分が進捗ありますか?と聞いて進捗ありますと答えられる程度の変更を目標にする。

  • 飲み会等でその日の夜に作業時間をとれなさそうなら、その日の朝早く起きて作業しておく。

  • 息を吐く様に意識せずに進捗を上げられるようになりたい。

ちょっと振り返り

よかったこと

毎日何かしら進捗を出すという習慣ができてきた気がします。 無制限にプライベートリポジトリが作成できるので、 ちょっとしたプロジェクトもガンガン履歴として残せます。

今日の夜の作業では〇〇を実装しよう。など、移動中にアイディアだしする習慣ができました。

開発&学習した跡が見えるのはやはりたのしいです。 今後も続けようという気になります。

今後への課題

更新することが目的とならないように気を付けたい。

おわりに

1.5ヶ月くらい毎日続けられてます。 f:id:hakonebox:20181010233157p:plain

おまけ

独学プログラマー

独学プログラマーこちらです。
最低限書いてあることはできるようにておいたほうがいいと思います(個人的感想)

独学プログラマー Python言語の基本から仕事のやり方まで

独学プログラマー Python言語の基本から仕事のやり方まで

プライベート草の見える化

デフォルトの設定だと、他のアカウントから、プライベートリポジトリで生えた草は見えないようです。

f:id:hakonebox:20181010233948p:plain

Contribution SettingsのPrivate contributionsを有効にしてください。 ここを設定すると他の人からも見えるようになります。

トドネロさんに教えていただきました。

Unity 1週間ゲームジャム[ぎりぎり] レースゲーム"NekoWay"公開しました。

はじめに

今回の開催期間は 2018-0-04 〜 2018-06-10でした。

遊んでいただいた方ありがとうございます。 コメント読みながら喜んでます!!

開催期間のツイートをまとめて、 振り返りをしておこうと思います。

完成したもの

公開先のリンクです。

NekoWay | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

7作目のゲームになりました。

一週間のふりかえり

1日目成果

レースゲームを作りたかったのでNekoWayつくりました。

2日目成果

3日目成果

4日目成果

5日目成果

進捗ありません。 お酒飲みたかったし。しかたないね。

6日目成果

7日目成果

アップデート

v1.1アプデしました。

ランキングの名前入力にRとTキーが使えない問題があったので修正しました。 コメントで教えていただき感謝です。

思ったことをつらつらと

反省点 面白さの肝となるコース作成に時間をかけることができなった。 Probuilderで作成する予定だったが、曲線を描くような使い方を理解できていなかった。

移動の制御は自動車のサンプルから使用。中身がわからないまま使ってしまっていた。

リプレイ機能が実装できなかった。 タイムアタック形式のゲームは リプレイがあったほうが他プレイヤーの動きを参考にできるので必要と感じたが、実装できていない。 できるかどうかの検証作業もできなかった。

WASDとJキーの入力をフレーム毎に保存しておいて、その入力を再現することでできそうだが、 壁にぶつかったときや加速床、ターボの動きが物理演算を使用しての動きとなっているため、 完全に同じような動きはできなさそう。壁にぶつかるし。

コントローラの対応が間に合わなかった。 ハンドルがキー入力だと、 どのくらい曲がるとかの制御がしにくい。

ランキング実装したかったね。

よかったこと 予想外の動きを減らすことで、ゴールまでのストレスを軽減できた。 何度もやってクリアは1面だけのコースで実装する気がしたのでぎりぎりで修正してよかった。

全体を通して、 最低目標までは期限内に実装できたが、満足できていない。 音楽とかエフェクトとか、もっとできることがあったと思うが、 もっと簡単な仕様でよかったと感じる

最後に

ハコネコー | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

PuddingJump α版 | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

シューティング、アクションに続いてレースができて、いろんなジャンルがそろい始めた。

Oculus GO向けアプリをUnityでビルドする際の環境メモ

はじめに

Oculus GO向けアプリをUnityでビルドできるようになりました。

その時の設定環境をメモしておこうと思います。

何か作ろうと思ったときに、振り返れるようになればいいなと。

環境

  • Windows10
  • Unity 2018.1.0f2

設定

Build Setting

f:id:hakonebox:20180527163504p:plain

PlayerSettings

Other Setting->Identification

f:id:hakonebox:20180527163650p:plain

XR Setting

f:id:hakonebox:20180527163800p:plain

おわりに

あとはAndroid SDKのパスくらいしか変更していません。

環境構築に苦労したのはAndroidSDKのダウンロードでした。

未来の私頑張ってください。

UnityでCVSファイルの読み出して2次元配列に格納しました。

はじめに

かくかくしかじかで、Unityでクイズゲーム作りたいと思いました。

しかし、問題を編集するのはUnityを使わない人なので、 スクリプトに埋め込むわけにはいきませんでした。

また、追加や編集が気軽にできるように、 外部ファイルに記載して、それを読み込む形をとります。

そんな感じでCSVファイルを読み込みます。

その時のメモです。

環境

  • Windows10
  • Unity 2018.1.0f2

やりたいこと

CSVファイルを作成し、それをUnityで読み込み、consoleに表示する。

結論

できました。 f:id:hakonebox:20180517005127p:plain

実際に使用したファイル

script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;

public class GameMaster : MonoBehaviour {

    public  string dataName;    // 問題テーマ
    private string title;       // タイトル
    private TextAsset csvFile;  // CSVファイル
    private List<string[]> csvDatas = new List<string[]>(); // CSVの中身を入れるリスト
    private int height = 0; // CSVの行数
    private int i,j=0;//debugループカウンタ
    const int size= 7;

    void Start()
    {
        title = "theme_"; // 頭文字
        csvFile = Resources.Load("CSV/" + title + dataName) as TextAsset; /* Resouces/CSV下のCSV読み込み */
        StringReader reader = new StringReader(csvFile.text);

        while (reader.Peek() > -1)
        {
            string line = reader.ReadLine();
            csvDatas.Add(line.Split(',')); // リストに入れる
            Debug.Log("reading:" + height);
            height++; // 行数加算
        }
        for (i = 0; i < height; i++)
        {
            for (j = 0;  j < size; j++) {
                Debug.Log("csvDatas["+ i +"]["+ j +"]:" + csvDatas[i][j]);
            }
        }
    }
}

csvファイル

1,マイコンの問題その1,選択肢1,選択肢2,選択肢3,選択肢4,答え5
2,マイコンの問題その2,選択肢A,選択肢B,選択肢C,選択肢D,答えE

表示の仕方

f:id:hakonebox:20180517004745p:plain

  1. 作成したスクリプトをGameObjectにアタッチ
  2. Data Nameに問題テーマを記述
  3. csvファイルの名前をtheme_[問題テーマ]にする
  4. Assetsフォルダに、Resources->CSVフォルダを作成
  5. CSVフォルダに読み出すcsvファイルを入れる

将来の自分へ

csvファイルに日本語を使用する場合には文字コードに気を付けること。

UnityのCreate->C# Scriptで作成されるスクリプト文字コードutf-8のようです。

csvファイルもutf-8にしておかないと、エラーが出てしまいます。

おわりに

書き込みは調べてないのでできません。 必要になったら調べる方向で。

とりあえず外部ファイルが読めるようになったので、 使える知識が一つ増えてよかったです。

あと、今回はあくまでエディタ上の読み込みなので、 ビルドしてスタンドアロン状態ではまだ未検証。

参考にさせていただきました

qiita.com