UE4覚書 コントロール定義の追加

UE4のサブスクを買ったので忘れないように覚書
まずはブループリントを覚えるためにコントロール定義をいじったりしてみる。
さくっとインストールしてThird Personプロジェクトを作成。
SnapCrab_アンリアルプロジェクトブラウザ_2014-12-29_22-24-47_No-00
どうやら、このひな形は実行すると「走る」「ジャンプする」「カメラ位置移動する」の操作が可能な模様。
いじり方を覚えるために、まずボタンを押すと「早く走る」を実装してみる。
最初に早く走るボタンの定義を追加する。
メニューの「編集」>「プロジェクト設定」で「エンジン」>「入力」の「Action Mappings」に名前を「Boost」として追加してみた。
ボタンはゲームパッドのBボタンに割り当ててみた。
SnapCrab_プロジェクト設定_2014-12-29_22-31-40_No-00
で、メインウインドウにもどって画面左下にあるコンテンツブラウザから「Game」>「Blueprints」内にある「MyCharacter」をダブルクリックしてエディタを開く。
SnapCrab_MyCharacter_2014-12-29_22-37-10_No-00
どうやらこのノードで色々やって動作を制御している模様。
操作は右クリック&ドラッグで画面スクロール、マウスホイールで拡大縮小、blenderとかのノード編集画面でも見たような構成。
さて、移動速度ってどこに書いてるんだ、、と画面左上の「デフォルト」をクリックするとキャラクタに与えられてる各種値が列挙されてる。
SnapCrab_MyCharacter_2014-12-29_22-40-40_No-00
ここの、「Max Walk Speed」がそれっぽい。これをブループリントで書き換えれば良さげ。
ということで早速やってみる。
グラフの何も無いところで右クリックするとノードの選択ウインドウが出るので検索しながら目的のノードを追加していく。
Character Movementノードは画面左の「マイブループリント」下にある「継承した変数を表示」にチェックを入れるとCharater以下に現れるのでそこからドラッグ&ドロップした。
「グラフ」に戻って、、こんなかんじでノードを作成してつなぐ。
白い枠は「コメントを追加」で作成可能。
SnapCrab_MyCharacter_2014-12-29_22-44-2_No-00
Boostボタンが押された時に、キャラクタのMax Walk Speedを1200に、ボタンが離れたら、600にする感じにしてみた。
この状態で「プレイ」してみると、Bボタンを押してる間倍の速度で動く様になった!

ゲームエンジン比較

3Dゲームエンジンが気になったので調査中。

 unity4.6unreal engine 4補足
長所・無料から始められる
・日本語資料多い
・アセットストアが充実
・公式説明書がちゃんと日本語化されてる
・お安く全機能使える
短所ポストエフェクトは有料版でしか使えない(16万)・最初に$20要る
・まだ解説してるブログとか少ない
・重い
とはいえ$20なら安い。
使用言語C#C++
BluePrint(ノードベース言語)
c#,C++はwindowsならどっちでも
VisualStudio Community Editionが無料で使える。
3Dファイル形式FBX他
blenderも直接読み込んで内部でコンバートする
FBX(2013)unrealはFBX(2013)なので、古い形式の場合コンバートが必要。
UI機能uGUIが標準で存在標準でありunityは4.5までは有料だった。
有名ドコロDQ8,テラバトル,LIMBOGears of war
GGXrd
どっちも知ってるゲームで使われてる。
その他機能アニメーションキーがエディタで編集可能

3Dプリンタの使い方メモ

1ヶ月以上書くのサボってたので今まで覚えたことをまとめておく。

ハードウエア周り

  • Reprapはネジを多用してるが、こいつら振動で緩む。メンテナンス大事。
  • ヒートベッド+ガラス+ヘアスプレーでABS印刷もバッチリ!(ヘアスプレーなしだとおもいっきりABSが反るのだけど、ヘアスプレーをガラス面にさっと噴きつけるだけでバッチリくっつく)
  • 剛性大事(印刷時に結構prusa mendel横方向に揺れるので改造してでも剛性を上げること)

モデル作成

  • 寸法ありきのCAD的に作成するならAutodesk Fusion 360が使いやすい。
  • Autodesk 123Dでもいいが、Fusion 360のほうが作図機能が多い。
  • ノンスケールモデルならSTLが吐ければなんでもいい。

GCode生成または印刷ソフト

  • slic3r&pronterfaceの組み合わせはギアなどを作るのに向いている(小さい面積の部分を確実に塗りつぶしてくれる、curaだとサボる場合あり)
  • curaのほうはできるだけ出力モデルにゴミが付着しないようにホットエンドを動かすみたいで、基本的にはcuraをつかうといい結果が出る感じ。

後処理

  • ABSはアセトン、PLAはメチルエチルケトンで溶けるのでそれぞれの溶剤薄めた奴に入れて撹拌すればいいらしい。
  • 上のはkickstarterでの情報
  • http://www.kickstarter.com/projects/1809448130/3d-refiner-by-3dprintsexpresscom
  • 両方の溶剤が混じっているのがラッカー薄め液らしいのでこれ使えば積層跡消しできる?(実験してない)

ギークハウスに3Dプリンタ勉強会いてきた

2013/3/30にギークハウス新丸子にて行われたこれからの「3Dプリンタ」の話をしように行ってきました。
写真は、イベント主の持ってる3Dプリンタ “cube 3D”
2013-03-30 15.03.02

内容箇条書きあとでまとめる。いつか、、そのうち、、、

  • イベント主はcube 3d持ち。
  • 自分はLunavast PrusaV2 3Dプリンターキットじつはこれを輸入してるだけの模様
  • イベント主の持ってたやつではホットベッドなし。糊でベッドにくっつける方式。
  • 平たく印刷したものを見せてもらったけど、やっぱり盛大に反ってる模様。
  • ギークハウス関係者のお子さんから「javaで会話する」という言葉が出てきて衝撃。
  • これがデジタルデバイド、、または情報格差か、、
  • で、3Dプリンタで何するの?って話になったけど今のところはオーダーメイド一点ものを作るって位しか想像できず。想像力がほしい。
  • 「ロボットつくりてぇ!」っていってたところで「配線ガー」って否定されてたけど、ZPrinterとかで背中の動力部から全部ギアとかからくりで動かせたらかっこいいなーとか妄想してみたり。
  • 持っていったギアキューブで話の腰を折ってしまって申し訳ありませんでした。m(__)m
  • cube 3Dはヘッドが大きく移動する際、Z軸を少し移動してからXY移動してた。 reprap系ではデフォルト設定ではしない動作(設定するとできる)なので若干興味深い。

Lunavast PrusaV2

Lunavast PrusaV2 3Dプリンターキットを購入するため年末に入金したんだけど、後どれくらいで送付されるだろうか、、入金確認のあと連絡がない、、、
入金当時はリードタイム5週間って書いてたんだけど。

入金してから部品調達している雰囲気もあるし、気長に待つかー。

Arduinoでリモコン

こちらの方のページを参考にArduinoでリモコン作ってみた。
参考にしたページでは受信したリモコンデータを一旦テキストエディタ等で加工しなければ送信データとして使えなかったので、コピペで送信できるようにソースを都合よく改変。
使った部品は秋月電子で買える受光部赤外線LED
LEDは+の方をリモコン出力ピンにもう片方をGNDに接続。
受光部はOUTPUTをリモコン入力ピンに、あとGND、5Vにそれぞれ接続。
こんな感じ。
2013-01-18 01.43.17
これに向かってリモコンのボタンを押してやるとシリアルモニタにデータが表示されるのでコロン以降の文字列をそのままコピーしてArduinoに送信してやるとそのままリモコンとして動作する。
スクリーンショット 2013-01-19 22.58.24
※ただし、80bytesを超えるような長さの文字列を送信すると取りこぼすっぽいので分割して送信すること。

ソースはこんな感じ。

#define DLEN 512
// リモコン入出力ピン
#define IR_IN  A1
#define IR_OUT A0

// リモコンデータ保存配列
unsigned char data[DLEN];

// リモコン受信状態制御 0:Leader受診前 1:Leader受信後受信完了まで -1:赤外線受信停止(未実装)
char recvStatus = 0;

// リモコン入力ピンの値保持
char last = 0;   

// -1,0,1しか使わない。
char onOff = -1; 

// 赤外線基本の時間 (μsec) リモコンで違うため可変
int tlen;        

// 0:点灯時間 1:消灯時間保持
unsigned int prevMem[2]; 

unsigned long us = micros();


// 消灯、点灯時間比率テーブル
// NECテーブル
unsigned char nec[5][2] = 
{
  {1,1},  // '0':数字の並びはoff, on の時間の並び
  {3,1},  // '1'
  {4,16}, // repeat
  {8,16}, // Leader
  {0,1}, // END
};

// 家製協テーブル
unsigned char aeha[5][2] = 
{
  {1,1},  // '0'
  {3,1},  // '1'
  {8,8}, // repeat
  {4,8}, // Leader
  {0,1}, // END
};


// セットアップ
void setup() {
  Serial.begin(57600);    // シリアル通信速度の設定
  pinMode(IR_IN, INPUT);  // 入出力ピンの設定
  pinMode(IR_OUT, OUTPUT);
}

// dataからリモコン信号を送信
void sendSignal() {
  char onoff = 1; // 必ず点灯から始まるため。 
  unsigned char state = 0;
  unsigned int len;
  unsigned char (*p)[2]; // necとaehaのtの長さテーブル参照用ポインタ。
  
  for (int cnt = 0; cnt < DLEN; cnt++) {
    // len に必要な点灯または消灯時間をセット
    if(cnt == 0){
      // 点灯、消灯時間比率テーブルの決定
      p = (data[cnt] == 'A') ? aeha : nec ;
      state = 3;
    }else{ // 0 or 1 or 2 or 4(END)
      state = data[cnt] - '0';
    }
    for(onoff = 1; onoff >= 0; onoff--){
      // テーブルから、点灯/消灯時間を決定
      len = tlen * p[state][onoff];
  
      // 長さ0のデータを見つけたら、リモコン信号送信終了
      if(len == 0)
        break;
      unsigned long us = micros();
      do {
        digitalWrite(IR_OUT, onoff); 
        delayMicroseconds(8);  // キャリア周波数38kHzでON/OFFするよう時間調整
        digitalWrite(IR_OUT, 0);
        delayMicroseconds(7);
      } 
      while (long(us + len - micros()) > 0); // 送信時間に達するまでループ
    } 
    // 長さ0のデータを見つけたら、リモコン信号送信終了
    if(len == 0)
      break;
  }
  Serial.print("OK\n");
}

// シリアルからの受信をチェック
// 入力エラーチェックなど全くしていないので注意。
void checkSerial() {
  unsigned char state = 0;
  unsigned int datacnt = 0;
  unsigned char c;
  if (Serial.available() > 0) {
    c = Serial.read();
    if(c == 'R'){
      sendSignal();
    }else if (c == 'P') {  // 入力開始
      // 念のため受信バッファ初期化
      for(datacnt = 0; datacnt < DLEN; datacnt++)
        data[datacnt] = 0;
      tlen = 0;
      datacnt = 0;
      Serial.print(">");
      while (1) {
        while (Serial.available() == 0) {
        } // 次のバイトが来るまで無限ループで待つ
        int a = Serial.read();
        switch(state){
          case 0: // N(EC) or A(AEHA)
            data[datacnt] = a;
            datacnt++;
            state++;
            break;
          case 1: // tlen
            if('0' <= a && a <= '9'){
              tlen = tlen * 10 + (a - '0');
            }else{
              state++; // ’S'受信
            }
            break;
          case 2: // 0 or 1 or 2 or 4
            if('0' <= a && a <= '2'){
              data[datacnt] = a;
              datacnt++;
            }else{
              // '4' データ終端
              data[datacnt] = a;
              datacnt++;
              state++;
            }
            break;
        }
        if(state == 3){
          Serial.print("data read end.[t=");
          Serial.print(tlen,DEC);
          Serial.print(",len=");
          Serial.print(datacnt,DEC);
          Serial.print("]\n");
          Serial.write(data, datacnt);
          Serial.print("\n");
          sendSignal();
          state = 0;
          break;
        }
      }
    }
  }
}

// 点灯、消灯時間からどのデータ(CustomerCode or Data or Leader or Repeat)であるか判断する。
// 送信開始から終了までに複数回Leaderを送るものには対応していない。
void chkData(){
  unsigned int t;
  if(prevMem[0] < 900){
    // Customer Code or Data
    if(recvStatus == 1){
      if(prevMem[0] * 2 < prevMem[1]){
        Serial.print("1");
      }
      else{
        Serial.print("0");
      }
    }
  }
  // 最初の点灯の長さでNEC/AEHAどっちのフォーマットかいい加減な感じで判断。
  else{
    if(recvStatus == 0){
      if(prevMem[0] > 8000){
        t = prevMem[0] / 16;
        Serial.print("NEC Leader:[t=");
        Serial.print(t, DEC);
        Serial.print("]:PN");
      }else{
        t = prevMem[0] / 8;
        Serial.print("AEHA Leader:[t=");
        Serial.print(t, DEC);
        Serial.print("]:PA");
      }
      Serial.print(t, DEC);
      Serial.print("S");
      recvStatus = 1;
    }else{
      if(recvStatus == 1)
        Serial.print("2");
    }
  }
}

void loop() {
  unsigned int val;
  unsigned int cnt = 0;

  // Wait for incoming IR signal
  while ((val = digitalRead(IR_IN)) == last) {  // パルスが切り替わるまで待機
    if (++cnt >= 30000) {  // 30000回ループで信号が終了したとみなす
      if (cnt == 30000 ){
        if(flames > 0 && recvStatus == 1){
          Serial.print("4\n");
        }
        recvStatus = 0;
        onOff = -1; // 最初に赤外線ONを受信した時に赤外線off時間の値を無視するため
        flames = 0;
      }
      else{
        checkSerial();   // シリアル通信が来ているかチェック
      }
      cnt = 30000;
    }
  }

  unsigned long us2 = micros();
  unsigned int len = (us2-us);
  if(onOff >= 0){ // 最初に赤外線ONを受信した時に赤外線off時間の値を無視するため
    prevMem[onOff] = len;
    if(onOff == 1){
      chkData();
      flames++;
      onOff = -1;
    }
  }

  last = val;
  us = us2;
  onOff++;
}

アクリルレーザーカット

Emerge+ 様のところに依頼したアクリルレーザーカット先日届いたので組み上げてみる。

A4のアクリル素材1枚から写真のDACエンクロージャが2個取れるように図面を作成。

初めてレーザーカットというのを試してみたけど、FAQに合った通り、切断する線から±0.1mm広がるということを考慮して図面を作成すればあとは難しいこと考えなくてもサイズ通りになるいうことがわかったので、これから色々活用してみたい。

アクリルカットで作成したDACエンクローシャ

C#でSQLite3を使う

MySQL使うほどでもない場合にSQLite使いたかったので調べてみた。

  1. ここ から System.Data.SQlite ライブラリを入手。
  2. サクっとインストール
  3. C#プロジェクト設定を .net framework 3.5にする。
  4. 参照設定に以下DLLを追加する。
    C:\Program Files (x86)\SQLite.NET\bin\System.Data.SQLite.dll
  5. 使う。
    using (SQLiteConnection cnn = new SQLiteConnection("Data Source=mydatabase.db"))
    using (SQLiteCommand cmd = cnn.CreateCommand())
    {
      cnn.Open();
    
      // CREATE文の実行
      cmd.CommandText = "CREATE TABLE FOO (ID INTEGER PRIMARY KEY, MyValue NVARCHAR(256))";
      cmd.ExecuteNonQuery(); // Create the table, don't expect returned data
    
      // INSERT文の実行
      cmd.CommandText = "INSERT INTO FOO (MyValue) VALUES('Hello World')";
      cmd.ExecuteNonQuery();
    
      // SELECT文の実行
      cmd.CommandText = "SELECT * FROM FOO";
      using (SQLiteDataReader reader = cmd.ExecuteReader())
      {
        while (reader.Read())
        {
          Console.WriteLine(String.Format("ID = {0}, MyValue = {1}", reader[0], reader[1]));
        }
      }
    }

Insyncの右クリックフリーズ回避

insyncが右クリック拡張使うときになぜかexploler巻き込んで止まるので右クリック拡張機能使わないようにして回避してみた。

  1. insyncをquit
  2. regeditで’InSyncExt’の名前を含むキーを検索して全部削除
  3. %APPDATA%\Insync\Appの以下2ファイルを別のフォルダに移動
    InsyncShellExtensions.dll
    InsyncShellExtensions64.dll
  4. insync再起動