2013年7月31日水曜日

【Unity】複数カメラを使ってみてつまづいたこと。分かったこと。

今日はUnityのカメラについて調べたこと、分かったことをまとめておこうと思います。

はじめに

なぜいきなりカメラを調べたかって言うとこんなバグにぶつかったから。
残像いっぱい
結局簡単に直せたんですが意味不明すぎて気持ち悪かったので調べました。

いきなりまとめ

ちょっと今日の記事はだらだらと長くなりそうなので結論だけ先に書いときますね。
素人のたどり着いた結論なので詳しい人が見たら間違ってるかも…。

複数カメラを使うときに知っておくこと

  • 深度(Depth)の浅いカメラから順に描画される
  • 各カメラの背景はクリアフラグ(Clear Flags)に従って塗りつぶされる

クリアフラグについて

  • Skybox
    カメラごとに設定されたSkybox(空模様マテリアル)で塗りつぶされる
    カメラにSkyboxが設定されていない場合、既定のSkyboxで塗りつぶされる
    既定のSkyboxも設定されていない場合、Backgroundに指定した色で塗りつぶされる
  • Solid Color
    Backgroundに指定した色で塗りつぶされる。
  • Depth only
    より深度の浅いカメラに任せる?このカメラでは塗りつぶさないよ的な…。
  • Don't Clear
    コレわかんない。

では色々やってみたこと載せときます。

カメラの深度について

とりあえず見てみましょー。

新規Sceneを作成し、下記オブジェクトを配置します。

・Main camera(最初からあるやつ)
 ・座標(0,0,-10)
 ・その他全てデフォ

・Hierarchy->Create->Cube
 ・座標(0,0,0)
 ・サイズ(1,1,1)

・Hierarchy->Create->Directional light
 置くだけ。

・Hierarchy->Create->Camera
 ・名前をSubCameraに
 ・座標(5,2,-5)
 ・回転(0,-45,0)
 ・Clear Flagsを"Skybox"に
 ・Depthは0

SubCameraから見たCube

SubCameraから見た(斜めから見た)Cubeが表示されましたね。

今はMainCameraのDepthが-1、SubCameraのDepthが0なので描画順は

①MainCameraのCube
②MainCameraの背景塗りつぶし
③SubCameraのCube
④SubCameraの背景塗りつぶし

なんだと思います。MainCamera無意味ですね。

ここでMainCameraのDepthを1にすると…

MainCameraから見たCube
MainCameraから見たCubeに変わりましたね。
描画順が入れ替わりました。

Depthの小さいものから描画されて、Depthの大きいものが手前に表示される。

たぶんこんな感じ。カメラ深度終わり。かんたんですね。

でもこれじゃ複数カメラ置いた意味がないですよね。
ゲーム画面用カメラとGUI用カメラとか同時に描画したい。
それを可能にするのがクリアフラグ(きっとそうだと信じたい

クリアフラグについて

冒頭にも書きましたがクリアフラグは4種類から選べます。

クリアフラグ - Depth only

まずMainCameraのDepthを-1に戻しておきましょう。
その状態でSubCameraのClearFlagsをDepthOnlyにしてみましょう。

両カメラから見たCube
2つのカメラから見たCubeがどちらも表示されました。

①MainCameraのCube
②MainCameraの背景塗りつぶし
③SubCameraのCube
④SubCameraの背景塗りつぶさない(DepthOnly)

こんな感じかな?

クリアフラグをDepthOnlyにするとそのカメラの描画しない部分が塗りつぶされなくなります。
より深度の浅いカメラ任せってことですね。

クリアフラグ - Skybox

Skyboxを使うと簡単に空とか背景っぽいものを表示できます。
カメラごとに指定することもできるし、既定の設定として指定することもできます。

背景塗りつぶしのの優先度は
(優先度高) > CameraのSkybox > 既定のSkybox > Background > (優先度低)
みたいです。

MainCameraにSkyboxを設定して確認してみましょう。

カメラにSkyboxを指定

・Assets->Import Package->Skyboxes
標準Skyboxをインポート
・全て選択してImport
インポート
・MainCameraの Inspector->Add Component->Rendering->Skybox

・MainCameraのSkyboxComponentにImportしたSkyboxMaterialをドラッグ
CameraにSkyboxを設定

晴れた空の背景が映りました。

既定のSkyboxを指定

カメラごとにSkyboxを設定しなくてもプロジェクト既定のSkyboxを指定することができます。

・Edit->RenderSettingのSkyboxMaterialに指定できます。
既定のSkybox
何度も書くけどカメラのSkyboxの方が優先されるからね!

クリアフラグ - Solid Color

これはもう名前の通りですね。
Backgroundに指定した色で塗りつぶされます。
Skyboxを選択しててもMaterialが指定されていないとこの動作になります。
Solid Colorで塗りつぶし

クリアフラグ - Don't Clear

これが全然分からなかった。いろいろ触ったけどどういう変化が起きるのか分かりませんでした。
マニュアルでもあまり使わないって書いてあるし別にいいかな。

まとめ

これで結構カメラについての知識が深まりました。
少なくとも複数カメラへの恐怖は無くなったかなw

最初の不具合もすっきり!
カメラ1つでDepthOnlyになってたからうまく背景をクリアできてなかったんですね。
よかったよかった。

Unity系記事まとめ

2013年7月28日日曜日

Google Maps SDK for iOS で現在地をマップ中心に表示し続ける



MapKitよりGoogle Maps SDK for iOS のほうが使いやすいって噂なので使ってみた。
とりあえず現在地表示。

やりかた

1.Google Maps SDK for iOSの導入

ここに書いてる通りやる。とっても親切に書いてる。
http://qiita.com/shu223/items/bfb5ef3e45682c2bb763
・ちょっとだけつまずいたところ
ビルド設定の「Architectures を armv7 にする」なんだけど、
俺のはStandard(armv7,armv7s)ってなってて、ん?って思ったけど、そのままでいけた。

2.コード書く

マップ表示して現在地表示するためにちょっとコード書く。
なんだかインポートのコードの表示がおかしい。。。

ViewController.h
#import 
#import 

@interface ViewController : UIViewController

@end

ViewController.m
#import "ViewController.h"
#import 

@interface ViewController ()

@end

@implementation ViewController

GMSMapView *_mapView;
CLLocationManager *_locationManager;

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 地図の表示
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.86
                                                            longitude:151.20
                                                                 zoom:6];
    _mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
    _mapView.myLocationEnabled = YES;
    _mapView.settings.myLocationButton = YES;

    self.view = _mapView;
    
    _locationManager = [[CLLocationManager alloc] init];
    
    // 位置情報サービスが利用できるかどうかをチェック
    if ([CLLocationManager locationServicesEnabled]) {
        _locationManager.delegate = self;
        // 測位開始
        [_locationManager startUpdatingLocation];
    } else {
        NSLog(@"Location services not available.");
    }

}

// 位置情報更新時
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    [_mapView animateToLocation : [newLocation coordinate]];
    
    //緯度・経度を出力
    NSLog(@"didUpdateToLocation latitude=%f, longitude=%f",
          [newLocation coordinate].latitude,
          [newLocation coordinate].longitude);
}

// 測位失敗時や、位置情報の利用をユーザーが「不許可」とした場合などに呼ばれる
- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error{
    NSLog(@"didFailWithError");
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

良い感じに書けたら完成。
左上の再生ボタンを押すとiPhoneのSimulatorが起動して実行される。


今回も皆さんのおかげでとってもいい感じに出来ました。

今回参考にしたサイト Google Maps SDK for iOSの導入
http://qiita.com/shu223/items/bfb5ef3e45682c2bb763

現在地の表示
http://www.atmarkit.co.jp/ait/articles/1104/04/news117_2.html


2013年7月26日金曜日

【Unity,NGUI2.x】NGUIでボタン作成

久々Unityネタです。 ちょっとだけ時間に余裕が出来てきました。

折角NGUI買ったのですが使えてません。全然分かりません。
分からないなりにボタンぐらいはおけるようになったのでまとめておきます。

練習用に作ったサンプル



  • 画面にCubeを表示
  • 右矢印ボタンでCubeを右回転
  • 左矢印ボタンでCubeを左回転
動いたけど分からないところだらけです。
正しいやり方は定かじゃないですが動いたのでヨシ!

※Unity4.2リリースされましたがまだダウンロードしてません。
 この記事書いてるときはUnity4.1.5f1+NGUI2.6.3です。


では行ってみましょー。

つくりかた

1.プロジェクトの作成

いつもどーり。
testNGUIButtonってプロジェクトを作成

2.Cubeの作成、カメラの調整

・Hierarchy->Create->Cube
 ・座標(0,0,0)、角度(0,0,0)、スケール(1,1,1)
・Hierarchy->Create->Direction light
 ・座標とかそのまま
・HierarchyにあるMain Cameraを調整
 ・座標(0,0,-2)、角度(0,0,0)、スケール(1,1,1)
Cube表示完了

3.NGUIのインポート

・Window->Asset Store->購入済み一覧->NGUI->Import
フォントとか作るのめんどいのでサンプル込みで全部Importします。
全部入りでインポート
Projectビューに追加された
ここにあるFantasy AtlasとFantasy Fontを使います。

4.NGUIのUIを作る

・NGUI->Open the UI Wizard
UI Wizardを開く
LayerとCameraはデフォルトのままでCreate Your UIを押す
UIの作成
HierarchyにUIRoot、Camera、Anchor、Panelが追加されます。
ここのPanelにNGUIで作成する要素を追加していくみたいです。
MainCameraとは別にNGUI用のCameraが追加されますが、
ここらへんほんとさっぱり分かりません。
とりあえずカメラが重なってるとうまく表示できなかったのでUIRootをずらしました。

・UIRootの座標を(0,3,0)に移動(メインカメラと離す)
NGUIのUIを追加。メインカメラと重ならないように移動。
この辺り説明してる資料とかブログとかあれば誰か教えてください…

5.NGUI Buttonを作る

・NGUI->Open the Widget Wizard
Widget Wizardを開く
・AtlasをNGUIのサンプルからドラッグ
・FontをNGUIのサンプルからドラッグ
・TemplateはButtonを選択
・Back GroundはFlat Outlineを選択
・Add toが"Panel"になっていることを確認してAdd toボタンを押す
PanelにNGUIボタンを追加
これだけで画面にボタンが表示されます。
実行すると分かりますがマウスオーバーやクリック時のエフェクトまであります。
あら簡単!
ボタンが追加された
サイズとテキストを修正します。
・ButtonのBackgroundを選択して、
 ・Scaleを(50,50)に変更
ボタンの背景サイズ変更
・ButtonのLabelを選択して、
 ・Scaleを(50,50)に変更
 ・テキストを">>"に変更
ボタンのテキスト変更
・Buttonを選択して、
 ・座標を(30,-50,0)に移動
 ・NGUI->Attach a Colliderを押す
  →緑の枠(Collider)のサイズが自動調整される
 ・ボタンの名前を"RightButton"に変更
ボタンの調整
名前を分かりやすく変更
全く同じ手順でLeftButtonも作っておきます。
2つのボタンができた

6.Cube用スクリプトを用意

・Project->Create->C# Script
・名前をCubeScriptに変更
・内容を下記のように変更

using UnityEngine;
using System.Collections;

public class CubeScript : MonoBehaviour
{
    /// <summary>右ボタン押してるか</summary>
    private bool isRightButtonPressed;
    
    /// <summary>左ボタン押してるか</summary>
    private bool isLeftButtonPressed;

    void Update()
    {
        if (this.isRightButtonPressed)
        {
            //右回転
            this.transform.Rotate(0, 100 * Time.deltaTime, 0);
        }
        else if (this.isLeftButtonPressed)
        {
            //左回転
            this.transform.Rotate(0, -100 * Time.deltaTime, 0);
        }
    }

    /// <summary>右ボタン押された</summary>
    void RightButtonPressed() { this.isRightButtonPressed = true; }

    /// <summary>左ボタン離れた</summary>
    void RightButtonReleased() { this.isRightButtonPressed = false; }
    
    /// <summary>左ボタン押された</summary>
    void LeftButtonPressed() { this.isLeftButtonPressed = true; }
    
    /// <summary>左ボタン離れた</summary>
    void LeftButtonReleased() { this.isLeftButtonPressed = false; }
}

CubeScript.cs
ボタンが押されたとき、離されたときに各メソッドを呼べばCubeが回転するはず。

・CubeにこのScriptを適用
忘れないうちに適用

7.ボタンからスクリプトを呼び出す設定

NGUIのボタンに戻ります。
RightButtonを選択した状態でInspectorビューを見ると
UI Button XXXってスクリプトがいくつか見つかります。
これらがマウスオーバーやクリック時のエフェクトを設定してるんですね。
いろんなスクリプト
同じようにボタンが押された、離されたとき用のスクリプトを追加します。

・RightButtonを選択した状態で
 ・Add Component->NGUI->Interaction->Button Message
・追加されたButton Messageのプロパティを下記のように変更
 ・TargetにCubeをドラッグ&ドロップ
 ・FunctionNameにRightButtonPressed(CubeScript内の関数名)
 ・TriggerをOnPress

Triggerは6種類から選べます。
・OnClick(クリックされた)
  押して、離した瞬間に発生するようです。
  スマホでも同じ。
・OnMouseOver(マウスが乗った)
  マウスが乗るだけでクリックしなくても発生します。
  スマホでは発生しません。
・OnMouseOut(マウスが外れた)
  マウスが乗って外れるタイミングで発生します。
  スマホでは発生しません。
・OnPress(押された)
  マウスで押された瞬間発生します。
  スマホの場合、タッチされた瞬間発生します。
・OnRelease(離された)
  マウスで押され、離された瞬間発生します。
  スマホの場合、タッチが外れた瞬間に発生します。
・OnDoubleClick(ダブルクリックされた)
  マウスでダブルクリックされた時に発生します。
  スマホの場合もうまくダブルタップを検出できるようです。

ざっとみてOnPress、OnReleaseが使えそうだったので選びました。

全部で4つのUI Button Messageを追加します。

  1. RightButton.OnPress
  2. RightButton.OnRelease
  3. LeftButton.OnPress
  4. LeftButton.OnRelease
こんな感じ
動作的にはTarget.SendMessage(FunctionName)してるだけでしょうねー。
IncludeChildlenのチェックを入れると
Target.BroadcastMessage(FunctionName)されるんだと思います。

完成

回転中
これでボタンを押すと回転するようになりました。パチパチ。

気になる点

ただのボタンとして使うならこれで十分ですが
十字キーみたいな使い方を考えると問題がでてきます。

いちいち指を離さないと次のボタンが押せない

OnMouseEnter,OnMouseOutがスマホで使えればいいんですが使えないんです。
ゲームで使いたいのでOnTouchEnter,OnTouchOutみたいなのを実装してみたいと思います。
作らなくてもありました。
bool UICamera.stickyPress = false
とするだけで解決です!

2013年7月23日火曜日

MapKit で現在地をマップ中心に表示し続ける



MacBookが手に入ったので早速マップ表示するiPhoneアプリを作ってみることにした。
とりあえず現在地表示。

やりかた

1.Xcodeプロジェクト作成

何はともあれ iPhoneアプリを作るのでXcode起動してプロジェクト作成。


どんなアプリケーションにするか聞いてくるので、今回はSingle View Applicationを選択。


プロジェクト名は適当にMapKitSampleとかにした。
「Use Storyboards」にチェック(画面レイアウトするのに使うっぽい)
「Use Automatic Reference Counting」にチェック(コンパイラがオブジェクトの管理してくれるっぽい)


プロジェクトフォルダ作る場所を適当に選んでCreate


プロジェクトできた。わーい。


とりあえず、SimulatorがiPadになってるからiPhoneに変更


2.必要なFrameworkの追加

画面中央の「Summary」のところを下にスクロールしていくと「Linked Frameworks and Libraries」があるので、「+」ボタンで追加。


今回必要なのはMapKitとCoreLocationってやつなので、順に追加する。


両方追加するとこんな感じ。


3.画面にMapViewを貼り付ける

MainStoryboard_iPhone.storyboardを選択して画面レイアウトを表示する。


右下の〜Viewとかがあるところを下にスクロールしていくとMapViewがあるのでドラッグドロップで貼り付ける。
これでもうマップ表示できるみたい。あら簡単。


4.コード書く

今回は現在地を表示するって決めたので、ちょっとだけコード書く。
ViewController.hを選択してソースを開く。
Frameworkを読み込むために下記コードを追加する。(なんかソースの表示がおかしくなっちゃう。)
#import 


良い感じに書けたら、その下のViewController.mを選択してソースを開く。
下記コードを追加する。
MKMapView *_mapView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 地図の表示
    _mapView = [[MKMapView alloc] init];
    _mapView.frame = self.view.bounds;
    _mapView.mapType = MKMapTypeStandard;
    _mapView.showsUserLocation = YES;
    [self.view addSubview:_mapView];
    [_mapView.userLocation addObserver:self
                            forKeyPath:@"location"
                               options:0
                               context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    
    // 地図の中心座標に現在地を設定
    _mapView.centerCoordinate = _mapView.userLocation.location.coordinate;
    
    // 表示倍率の設定
    MKCoordinateSpan span = MKCoordinateSpanMake(0.01, 0.01);
    MKCoordinateRegion region = MKCoordinateRegionMake(_mapView.userLocation.coordinate, span);
    [_mapView setRegion:region animated:YES];
}


これも良い感じに書けたら完成。
左上の再生ボタンを押すとiPhoneのSimulatorが起動して実行される。


とってもいい感じに出来ました。

Objective-Cは全然わかんないけどaideal.jpさんのお陰で出来ました。
http://aidealjp.blog.fc2.com/blog-entry-23.html

調べてるうちにわかったけど、MapKitとGoogleMapは違うんだね。
次はGoogle Maps SDK for iOSを使ってやってみようかな。

2013年7月22日月曜日

MacBookAirがうちにやってきた


こんにちは、いつもだらだらbaiteenです。

ついにMacBookAirが手に入りました。
短冊に書いたり、毎日星にお願いしたりしてたら、リッチなオジサマがくれました。
七夕さまに感謝です。

13インチの128GB、COREi5。十分です十分です、もらえただけでラッキーです。
箱はこんな感じ。

Appleの製品は箱からかっこいいよね。

んで、中身はこんな感じ。もう箱から出しちゃった。


順番にトリセツ(もちろん読んでない)、電源、電源アップ、電源の延長。

電源は以外とおっきかった。ルービックキューブ半分にしたくらい。

そして本体。
順番に足、背中(薄い)、左腕(薄い)、左アップ(SDXC、USB、Thunderbolt)、右腕(薄い)、右アップ(電源、USB、オーディオ)、顔。

とにかく薄い。そしてシルバー。
コネクタ類は、薄いやつだけが生き残ったって感じ。
LANケーブル?Wifiでしょ。光学ドライブ?クラウドでしょ。って感じ。
ここまでやられると諦めつくね。

電源のコネクタが超かわいい。マグネット最高。


ということで、電源つないでー と思ったけど、今日はここまで。
写真のセンスのなさに耐え切れない。
実物はもっとかっこいいので、みんなサンタさんにお願いしましょう。
俺は次は一眼レフをお願いしようと思います。


Related Posts Plugin for WordPress, Blogger...