ツインスティックでLEDを光らせてみる。

ハードオフとかでジャンクを漁るのがめっちゃ楽しくなった今日この頃です。
で、先日見つけたのがこちら。
ツインスティック
セガサターン用ツインスティックです。525円(だったはず)!
ゲームコントローラーよりも直感的に操作できると思いますし、ロボットゲーム等のコントローラーとして使えそうです。

バラしてみると恐ろしくスッカスカでした。スティックの入力ってマイクロスイッチを4つつけて実現してるんですね〜。なるほど〜。攻撃ボタン?はタクトスイッチ、ターボボタンはなぜかアナログのスイッチになっていました。押す力によって抵抗が変わります。

方向レバーは黄色がGND、茶色が上、黒色が下、オレンジ色が右、赤色が左となっており、ボタンは黒色がGND、他2つがタクトスイッチだったりアナログボタンだったりです。(適当)

Arduinoでスイッチが認識されているか(電流が通っているか)はデジタルピンに4つ差し込んで、ブレッドボード上でLEDと抵抗をかましてGNDに接続しました。抵抗とLEDをかまさないとArduinoが壊れる・・・のかな?
で、こんな感じ。
ツインスティックでLチカ
画像ではシャッターが遅くて光ってるところが写せませんでしたが、方向レバーを傾けることでLEDが光ります。

次回は各ピンのアクトプットの情報を検知してキーボード入力してみます。
これができればMacのUnityゲームでもツインスティックが使えることになります。

ジャイロセンサーで回転の加速度を取得する

プログラムの最初はハローワールド、電子工作の最初はLチカ(LEDをチカチカさせる)をさっさと済ませましてから急に進みますが、ジャイロセンサーの値を取得してみました。

購入したのは秋月電子の「小型圧電振動ジャイロモジュール」です。なんで2軸買ったんだろう・・・。3軸ないと3Dで使えないじゃんていう(ノД`) まぁ安いからいいんですけど。

さて、はんだでピンをくっつけて(すんごい久しぶりで緊張した)、説明書通りに配線を繋げてみたのが以下の写真。
ジャイロセンサーを繋ぐ
プログラムもそうですけど、やったことがない最初は「こんなことできるのか?」ってすごい不安なんですけど、できてしまえば「余裕じゃん!」ってなりますね。電源電圧は2.7〜5.25VDCってあったから抵抗無しでもいいはず・・・。

スケッチの記述

Arduinoではスクリプトのことを「スケッチ」と呼びます。ジャイロの値を取得するだけなら以下のスケッチで確認できます。
アナログはA0とA1に繋ぎました。説明書によるとGNDは全部繋いどけってことなのでそうしときました。

void setup()
{
     // シリアルモニターの初期化をする
     Serial.begin(9600) ;
}
void loop()
{
     long x , y ;
     
     x = analogRead(A0) ;  // 軸1を読込む
     y = analogRead(A1) ;  // 軸2を読込む
     
     // 読み込んだ各軸をそのまま表示する
     Serial.print("X=") ;
     Serial.print(x) ;       // 軸1
     Serial.print(" Y=") ;
     Serial.println(y) ;     // 軸2

     delay(1000) ;
}

やってみて気付いたんですけど、ジャイロって加速度センサーと同じで、動いたブレ幅を取得するんですね。
例えば何も動かしていない時の数値が「0」の場合、動かすと大きく数値が変化するんですが、静止するとまた0に戻る。3Dなら取得した値を常に足していく感じになる。ただし、100動いて100戻したら全く同じ位置になるかというとそう正確にはいかないようで、必ず数値のズレが出てくる。これを「ドリフト」というらしい(響きがかっこいい・・・)。
なのでどこかで数値をリセットしないとズレがどんどん激しくなっていくのは注意しないといけませんね。

Arduinoことはじめ。

非常に久しぶりにブログを更新。今まではUnity関連だったけど、今後はArduinoとOculusも更新していく予定です。

さて、Arduinoですが、詳しい話は他サイトでたくさん出てくるので割愛するとしまして、要するにLEDをチカチカさせることから自作のロボットを作ることまでできてしまうシステムで、これを使えばかなり簡単に(といっても相応の知識が必要ですが)色んなデバイスを自作できるようになります。これに最近流行の3Dプリントがあれば、個人でも音が鳴ったり光ったりするオモチャのサンプルができてしまいます。いい時代になったもんですねぇ。

始めるにあたって以下のモノを購入しました。

【Arduino Uno R3】
Arduino UNO R3
オープンソース・ハードウェアなので、様々なディベロッパーが大本の設計図を元にボードを売っているわけですが、まずは最初なので本家イタリア製を購入。厚み・塗装などの作りがしっかししている美しいボードです。
実際にはセットでお得なエントリーキットを購入しました。

【本:たのしい電子工作 Arduinoで電子工作をはじめよう!】
電子回路のことは小学生以来なので基礎から勉強したくて購入したのですが、そういう要望に応えてくれる本ではなかったです・・・。でも今後のこともあり持っておいて損はないと思います。

【はんだ】
Arduinoとブレッドボードがあれば、はんだなしでも遊べるのですが、せっかくなので。コツを覚えれば楽しくできます。熱くなってると熱気が?目がしみる。

そんな感じで電子回路は小学生以来な自分ですが、楽しく勉強していきます。

Unityで影(陰)が無いシーンを作る。

かなり前に書き留めてあったやつ。

Directional LightやPoint Lightを配置すれば陰がつきますが、その分負荷がかかっているはずです。
Unityで影(陰)が無いシーンを作ろうと思っても、ライトを削除すれば画面は真っ暗になってしまいます。どうすればいいのかと調べてみました。

Ambient Lightを明るくする

Unityのメニューから「Edit」→「Render Setting」を選択し、InspectorにRender Settingを表示させます。そこの「Ambient Light」を設定してやるだけ。これでライトが無くても画面が明るくなります。気分はプレステレベル。
Ambient Lightの設定

サンプル

このやり方の場合、キャラクターは全部の面をテクスチャ使わないといけなくなるので作業の手間が増えることになるかな。

しかし自分のキャラクターがバイオハザードな感じに動かせるだけで凄い愉快な気分になります(サンプル)。特にジャンプ中に歩かせるエアウォークさせると。

Unityでスクリーンショットscreenshotを取る

Unityでスクリーンショットを取るのはApplication.CaptureScreenshot(ファイル名.png)を記述するだけと非常に簡単なのですが、AndroidアプリとしてSDカードに記録させようとした時にちょっと詰まったのでメモ。

記述の仕方

OnGUIのボタンをクリックするとキャプチャする場合。
[javascript]function OnGUI () {
if(GUI.Button(Rect(10 ,10,200,50),”スクリーンショットを撮る”)){
Application.CaptureScreenshot(“screenshot.png”);
}
}[/javascript]

“screenshot.png”の部分はそのまま保存されるファイル名になります。ファイル名が重複した場合は問答無用に上書きしてくれます。「上書きしますか?」などというポップアップも表示されません。

《Application.CaptureScreenshot》

保存される場所

Androidだとデフォルトでは変な場所に保存されます。
[javascript]”/sdcard/Android/data/[パッケージ名]/files/”内[/javascript]

ちなみにUnityのプレビュー上でキャプチャするとプロジェクト内に保存されます。

保存される場所を変えるには

色々なサイトを見ると、Application.CaptureScreenshot()の引数にパスを指定してやれば?って記事がありましたが、できませんでした。
[javascript]// できない
“/sdcard/DCIM/端末ごとのフォルダ/screenshot.png”
// これもできない
“/mnt/sdcard/DCIM/端末ごとのフォルダ/screenshot.png”
[/javascript]

結局どうするかというと、htmlを記述する時と同じようにしてやります。
[javascript]”../../../../DCIM/端末ごとのフォルダ/screenshot.png”[/javascript]

追記:指定したフォルダが無い場合は記録されないみたいです。

以下のサイトを参考にしました。
http://forum.unity3d.com/threads/134430-Capturing-screenshots-to-sdcard

できるようになったとはいえ、シャッターボタンが画面にある場合はシャッターボタンごとキャプチャされるので、シャッターボタンを押した瞬間にボタンを消してキャプチャする必要があったりとか工夫が必要ですね。

Unityで簡単なAndroid用レースゲームを作ってみた。

Unityで簡単なAndroid用レースゲームを作ってみた。
Unityで簡単なAndroid用レースゲームを作ってみた。iPhoneでも動くと思うけどDeveloper登録してないので未確認。
データはサーバーにアップしてあるので、下記リンクからapkファイルをダウンロードして、Android機にインスコすれば遊べます。

http://www.uxic.net/webpocket/fitrace.apk

操作方法

操作方法はタッチのみ。タッチしていればアクセルになり、離せばブレーキになります。ちなみに無限に加速します。
端末は横向きで左右に傾けると曲がります。
アプリを終了するにはHome長押しなどで。
つくばサーキットが走れます!が車の大きさとかデタラメです。

ハマったところ

当初、車にBoxcolliderとrigidbodyを付加して動かしてみたんですが、なんかガタガタして変な動きだったんです。
Gravityを切ったり、コンストレイントしたりすれば大丈夫なんですが、それじゃぁ車がひっくり返らなくなりおもしろくないわけで。色々と調べてみたら、ただ単にphysics materialの摩擦係数の問題でした。
車を動かすゲームといえばUnityのサンプルのレースゲームではタイヤに対してWheelCollider使ってますが、なんか設定項目が多くて難しそうなんで止めました。

スクリプトについて

かなりでたらめなjavascriptなんで晒すのが恥ずかしいですが・・・。
車の座標はCharactorController使わずにMathf.SinとMathf.Cosで対処してます。(恐ろしや)
[javascript]private var Power_f:float;
private var Power_v3:Vector3;
private var PowerCos_v3:Vector3;

private var AccelerationY_f:float;
private var AccelerationY_s:String;

private var Handle_f:float;
private var Handle_v3:Vector3;
private var Handle_q:Quaternion;
var HandleSpeed_f:float;

function FixedUpdate () {

//—————————- Acceleration
AccelerationY_f = Input.acceleration.y;
AccelerationY_s = AccelerationY_f.ToString();

// ローパスフィルター
Handle_f = (AccelerationY_f + 1) / 2 – 0.5;

// アクセルの値をy軸に作用するVector3に代入
Handle_v3 = Vector3(0,-Handle_f * HandleSpeed_f ,0);

// アクセルのspeedとかけた値をQuarternion.Eularに代入
Handle_q = Quaternion.Euler(Handle_v3 * Time.deltaTime);

//—————————- Touchしていない時
if(Input.touchCount == 0){

// 一応進んでる処理
CarMove();

// 減速処理
Power_f -= 0.5;
if(Power_f <= 0.0)Power_f = 0.0;// 0以下になったらずっと0

// 速度がある時だけrotationを変えられる
if(Power_f > 0.0) CarRotate();

}

//—————————- Touchした時
if(Input.touchCount == 1){

for (var touch : Touch in Input.touches) {

// touchした瞬間
if (touch.phase == TouchPhase.Began){

}

// 加速時(touchして動かしている時、もしくは止めている時)
if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary){

// 加速処理
//Power_v3 += Vector3(Power_f, 0, Power_f);
Power_f += 0.1;
CarRotate();
CarMove();
}

// 離した瞬間
if (touch.phase == TouchPhase.Ended){

}
}

}

}

function CarMove(){
var RadianX_f:float = ReturnRadian(transform.eulerAngles.y);// radianを代入
PowerCos_v3 = Vector3(Mathf.Cos(RadianX_f),0,-Mathf.Sin(RadianX_f));
rigidbody.MovePosition(rigidbody.position + Power_f * PowerCos_v3 * Time.deltaTime);// 減ったり増えたりが加算されてる
}

function CarRotate(){
rigidbody.MoveRotation(rigidbody.rotation * Handle_q);
}

function ReturnRadian(euler:float){
var radian_f = Mathf.PI/180*euler;
return radian_f;
}
[/javascript]

あとAndroidとiphone用のtouchについてはphaseの状態ごとに処理を分ける必要がある。まだtouchが1つなのでいいけど,マルチタッチになるとこんがらがってきそう。

Input.Compassでコンパスの値を取得する。

Input.Compassを使えばiPhoneやAndroid機のコンパスの値が取得できます。
ただ、リファレンスを見る限りでは、Input.Compass.magneticHeadingで取得する場合はいいけど、Input.Compass.trueHeadingで取得する場合はInput.location.Start()しなくちゃいけないよって書いてある。う〜ん・・・なんのコッチャ。

方位磁石の向きを取得する。

[javascript]function Update(){
Debug.Log(Input.compass.magneticHeading);
Text2 = .ToString();
}[/javascript]
北を0(ゼロ)として、オイラー角の値が取得できます。端末を横向きとした場合は長辺側が上の扱いになる。

Inputは他にもマウスの値とかジャイロの値とか(端末が対応していれば)取得できる素晴らしい関数ですね。

Inpaintを購入してみた。

App Storeをたまたま覗いていたら、Inpaintという写真のいらない部分を簡単に削除してくれるソフトが85円のセールをやっていたので購入してみました。で、Twitterで反応がよかったので試して見ました。
Inpaintでいらない部分を削除してみた。

う〜ん・・・。photoshopで手でやった方がきれいに仕上がると思いますが、何しろソフトがシンプルで使いやすいので、まぁいいんじゃないでしょうか。85円だし。
ついでにこれは無理だろって画像も試して見ました。
Inpaintで無理やり背景を消してみた。

ですよね・・・。
これは別にInpaintが問題なのではなくて、Photoshopでやっても大して変わらないと思います(比べてませんが)。
Adobeがサンプルで出しているやつは大抵うまくいくような素材を使ってますからね・・・。

App Storeはこういった単機能に絞ったソフトがよく出ていて、しかもたまに安くなっているのでいいですね。

オブジェクトの回りに動的なGUIを配置する。

UnityのGUIは動かないというイメージがありますが、実際には毎フレームごとに座標を与えてグリグリ動かすことができます。
今回は戦国無双みたいなゲームとかで、よく敵キャラクターの頭の上にある体力ゲージとか名前をイメージしたスクリプトをやってみました。

以下はデモです。Shiftキーを押しながらドラッグすることで動かせます。
でもなぜか私の環境のmacでは、safariだとライトがおかしいとかchromeだとそもそも動かないです・・・。

デモ

ワールド座標をスクリーン座標に変換する。

まず、ゲームオブジェクトのワールド座標をスクリーン座標にするためには、カメラオブジェクトのメソッド、WorldToScreenPoint(Vector3)を使います。
[javascript]Vector3 ScreenPosition = camera.WorldToScreenPoint(target.position);[/javascript]
これをカメラオブジェクトにつけます。
ちなみにスクリーン座標をワールド座標にするのはScreenToWorldPoint(Vector3)です。

オブジェクトの回りに動的なGUIを配置する。

流れとしては、Update関数でオブジェクトの座標(Vector3)を取得してスクリーン座標に変換し、その変数のXとYの数値をOnGUI関数のRectの引数に渡しています。

[javascript]using UnityEngine;
using System.Collections;

public class LookATGUI_C : MonoBehaviour {

public Transform GUIWatchPoint;

private Vector3 ObjectPoint;// オブジェクトのワールド座標
private Vector3 ObjectPointPlus;// オブジェクトのちょっと上の座標
private Vector3 GUIScreenPoint;// オブジェクトのスクリーン座標

private float ScreenHeight = Screen.height;

void OnGUI () {
GUI.Box(new Rect(GUIScreenPoint.x-60,ScreenHeight – GUIScreenPoint.y + 40,120,40),”Hello!”);
}

void Update () {
// Objectの座標を代入
ObjectPoint = GUIWatchPoint.position;
ObjectPointPlus = new Vector3(0,0,0) + ObjectPoint;

GUIScreenPoint = camera.WorldToScreenPoint(ObjectPointPlus);
}
}[/javascript]
注意点としてオブジェクトのY座標は、上に上がるとプラス、下に下げるとマイナスなのに対して、GUIのRectの引数のY座標は上に上がるとマイナス、下に下げるとプラスになるところです。
あとスクリーン変換した座標をそのままいれればよいというわけではなく、最初にスクリーンの高さを取得してそれにマイナスしてやる・・・もう書いててワケわからないのでスクリプトを参照のこと。
これだけのためにかなり時間かかりました・・・。

UnityのC#でXMLを読み込む。

xmlデータを取得して内容を読み込むことができると、例えばTwitterのタイムラインを表示させたりブログの記事を読み込んだりと、様々なWEBアプリケーションと連携することができて夢が広がります。

javascriptならxmlを簡単に読み込める形にしてくれる外部jsを読み込むか、C#ならxmlクラスがあるのでそれを使います。で、javascriptだと日本語の情報が無いのもありなかなかうまくいかないので、どうせならということでC#でやってみました。

Twitterのタイムラインのxmlについて

読み込むxmlはTwitterのタイムラインの方が今っぽいですかね。
以下のアドレスで@motar_24のTweet(20件)がXML形式で取得できます。ブラウザのアドレスに直接打っても確認できますが、safariだと改行されずそのまま表示されます。Chromeだと整形して表示してくれますね。
[javascript]http://twitter.com/statuses/user_timeline/motar_24.xml
[/javascript]

XMLの記述内容についてはここでは省略しますが、タグで囲まれているTweetテキストがあるのがわかると思います。このテキストを引っ張ってきて表示させるわけです。
注意点として、ローカルからならTwitterのAPIにアクセス(XMLを取得)できますが、Unityのプロジェクトがウェブに公開される場合(webプレーヤー)はクロスドメインの関係で取得できないようです。flashの場合はphpをかましてできるみたいですが、Unityはわかりません。
http://d.hatena.ne.jp/nakamura001/20110730/1312044175

XMLを取得するC#

Macでやりたい場合は、Monoをインストールする必要があります。
mono

Windowsの場合、7やVistaなら問題ないですが、XPなら.NET Frameworkをインストールする必要があるかもしれません。

内容をコメントしてあるので参考にしてください。
[javascript]
using UnityEngine;
using System.Collections;
using System.IO;// 追加で記述
using System.Xml;// 追加で記述

public class XMLLoder : MonoBehaviour {

// TwitterのxmlデータのURL
string XMLFilePath = “http://twitter.com/statuses/user_timeline/motar_24.xml”;

XmlDocument doc;// XMLオブジェクト
XmlNodeList nodeListtext;//テキストの配列

void Start () {
doc = new XmlDocument();// XMLオブジェクトを生成
doc.Load(XMLFilePath);// XMLのファイルを読み込む

// 全部配列
nodeListtext = doc.SelectNodes(“statuses/status/text”);// テキストの配列のできあがり

// あとは配列を読み込むだけ
Debug.Log(nodeListtext[0].InnerText);

}
}
[/javascript]

上記のスクリプトをコピペしてGameObjectとかに貼りつけてプレビューすれば、ConsoleにTweetが表示されているはずです。
実際に使うときにはGUI.Labelに入れたりします。できてしまえば簡単ですね!

« Older posts

© 2016 UXIC.net

Theme by Anders NorenUp ↑