お絵かき FF12 ヴァン
ちょっとArtRageで画像をトレースして書いてみました。こんだけ書いてから思ったんですがトレースってもしかして元の絵に合わせて修正してくれる機能とかありますかね?こんな私にうまくかけるわけないです😓これじゃ絵の練習にならない...
ちなみに書いたのは今PS4でやっているFF12より主人公のヴァンです。キャラデザインもとても良いですし、設定やストーリーもめちゃくちゃ面白くてガンビットシステムなんか特にずっと考えていられるくらい楽しいです。しかしこのガンビットシステムもそうですがL1ボタンの早送り機能や取り返しのつかない要素が多い点など、結構ゲーム好きな人じゃないととっつきにくいんじゃないかとも感じました。
最新作のFF15はストーリーやキャラクター、丸ボタンだけの戦闘などネットでは叩かれている部分が多いですが私は楽しめました!今日のFFは体験する映画のようなスタイルで作られていて、現実から少し離れたファンタジー体験ができるのが他のゲームとは違う強みではないかと私は思っています。今回のFF15はまさにその体現のような作品で、新規プレイヤーには特に好印象だったんではないでしょうか。どうもヴェルサス13の時の初期案のイメージが尾を引いていて過剰に叩かれているように思えます。もちろん私もとても楽しみにしていましたが、それはキングダムハーツⅢに引き継がれているようなのでそちらに期待しています😆
久しぶりの更新
ロックアイランド - パラオ
みなさんこんにちは🌚
梅雨もあけてとても暑い日々かと思ったら豪雨に見舞われたり今年の夏は中々荒れていますね。ある理由でブログの更新をしていなかったブルーノです。
というのもこれが今回の記事のメインで、実はこの2ヶ月の間に私の初アプリを開発、販売していました!🤯🤯🤯🤯もしよかったら遊んでみてください
直リンク
本当に対したものではないし、粗が目立ちますが今回の経験の全てが私自身にとって大きな一歩になりました!
2ヶ月の間がありましたが制作期間は実は1ヶ月のみで、あとは販売までの手続きでいろいろ私がヘマをして手間取ってしまい、時間としては倍になってしまいました。でもこれで次からはスムーズに販売まで行ける...はず。作ってる間にも思ったのですが制作のフローをこのブログに載せてその間に起こった問題とその解決方法をここに残しておけばよかったなーと後悔しています笑。次のアプリ制作時にはちょっとやってみようと思います👺
全てが初めてで、これまでの勉強の知識を総動員しても次から次に新たな問題が出てきたので結局ネットでの検索の繰り返しでした。結局あれこれ考えても何もしないのでは意味がないなんて当たり前のことを再認識した2ヶ月です。
これからもどんどんアプリを作って色んな事にチャレンジしてみたいと思います😡😡
Unityスクリプト / レンダラー編
クスコ - ペルー
みなさんこんにちは🌚
昨日はディズニーシーに急に思い立って友人と遊びに行ってきたブルーノです。もうファストパスも発券できなかったし乗れた大きなアトラクションはタワーオブテラーくらいだったけどめちゃくちゃ楽しかったです。エンターテイメントの代表的な一角としてゲーム作りの上でキャラクターやアトラクションなど参考にできそうです🤓
さて今回は、あらゆるゲーム画面上に描画されるオブジェクトを我々が視認するのに欠かせないメッシュやマテリアルといったレンダラーについてまとめていきます。
メッシュとレンダラー
CreatePrimitive()メソッド等で生成されるオブジェクトも含み、我々がゲームシーン上で目にするオブジェクトにはほとんどの場合Mesh FilterとMesh Rendererコンポーネントがついています。この二つはどうやらどちらも欠かすことはできないようです。
メッシュフィルターがその頂点(ポリゴン)情報をもち、メッシュレンダラーがそれを画面上に描写するコンポーネントのようです。そしてこのメッシュレンダラーにマテリアルの情報を送ることでそれを元にポリゴン情報に絵をつけていくといった流れでしょうか。
スクリプトからこのメッシュを追加したり編集するにはUnityEngine.MeshFilterクラスからアクセスします。
そしてメッシュはmeshプロパティで取得または追加できます
meshプロパティ
public Mesh mesh { get; set; }
そして追加したメッシュ情報を描画するためのレンダラーはUnityEngine.MeshRendererクラスを用います。
以前学習した[SerializeField]とコルーチンの機能を使っていますね。外部からは勝手にアクセスされないようprivate修飾子を使いつつもインスペクター上からメッシュを設定できるようにし、コルーチンを使うことでUpdateメソッドを使わずに3秒おきにメッシュ変数m1とm2のメッシュ情報を交互にメッシュレンダラー変数mf1に代入しています。
SerializeFieldによりprivateでもこの欄から設定できます。試しにCubeとCapsuleを入れてみました。
交互にオブジェクトのシルエットが変わりますね。でもこの新たに生成したオブジェクトにはマテリアルの情報がないため色や質がわからず、とりあえずピンクっぽい色で表示されています。
マテリアル
マテリアル(Material)はその名の通りその物質の情報です。ザラザラした感じやツルツルした光沢、色やくすみなどの情報を持っています。先ほど自前で用意したゲームオブジェクトには形の情報があるのにこのマテリアルの情報がなかったためにどこからみても全ての部分が同じピンク色という不気味な物質になってしまっていたんですね。
まあ今までにも何回かこのマテリアルを編集したことはありますがインスペクタービューではこんな形でしたね。
メッシュレンダラーのマテリアルの欄から指定することで使用でき、デフォルトでは真っ白になっています。ではこれをスクリプトから使用・追加するにはどうするのでしょうか
マテリアル関係のオブジェクトはUnityEngine.Materialクラスに属します。
UnityEngine.Materialクラス
public class Material : Object
スクリプトからマテリアルを生成する際には元のマテリアルを複製して使用するか、シェーダーを使うという2パターンがあるそうです。シェーダーについてはまだよくわからないので別の機会に勉強します。MeshRendererオブジェクトからmaterial(s)プロパティにアクセスした場合にマテリアルが初期化されていない場合はデフォルトマテリアルが自動で実装されるそうです。ここから色や質感を指定できるので個人的にはこの機能はポイントだと思います。
色の変更はcolorプロパティから取得もしくは変更します。
colorプロパティ
public Color color { get; set; }
しかし色だけでは全ての質感を表現するのは難しいです。確かに本物そっくりに陰影をつけたりして見分けがつかない絵などもありますが角度が変わればわかってしまいますね。そのためマテリアルには表面にテクスチャを一緒に貼り付けることが多いです。
MaterialクラスのmainTextureプロパティからテクスチャを設定できます。
mainTextureプロパティ
public Texture mainTexture { get; set; }
実際に使ってみます
先ほどと似たコードのようですね。空のゲームオブジェクトを作成し、3秒ごとにランダムな色を持たせます。
スクリプトから形状を指定すると
色が変わりましたね!
Default-Materialが生成されているのも確認できます。
メッシュの頂点生成などもあるのですが、スクリプトでこれを制御するのはちょっとコアすぎるのでやめておきます笑
今回はここまでにしておきます。
ついに始まったUnite Tokyo 2018!!初日の基調講演から行っているのですがもう全てが最高ですね!!🤩専門的なことは難しいですが実践しながら見せてくれる講演もあって違いが視覚的にわかりやすいし、私でもわかるレベルに噛み砕いてくれる講演も多々あって本当に初心者から上級者まで楽しめるものだと思います!絶対に行く価値がありますよ!
明日最終日もいろんなこと聞いてみて回るかー🙃😙
Unityスクリプト / レンダリング編
モハーの断崖 -アイルランド-
みなさんこんにちは🌚
早くゲームを作り始めたいのに他のサイトで情報を仕入れようとするたびに新しいワードや概念が出てきて自分の知識の無さにやきもきしながらも焦燥に駆られているブルーノです。さあ早く今回の分を勉強していきましょう!!
今回からはレンダリングについてです。レンダリングとは、ゲームの無機質なデータにあらゆる手法で彩りを持たせることを言います。今回やるのは主に照明やカメラワークについてです。
カメラ
カメラはUnityに最初に触れた時からずっと使い続けているコンポーネントですね。プロジェクトを新規に立ち上げた際にデフォルトで用意されているMain Cameraはいわゆるカメラコンポーネントを持ったゲームオブジェクトです。グランツーリスモなど視点が急に切り替わったりするゲームにみられるように、複数配置することができます。
コンポーネントからカメラをコントロールする場合はUnityEngine.Cameraクラスによって表されます。
UnityEngine.Cameraクラス
public sealed class Camera : Behaviour
ゲーム空間でのオブジェクト同士の当たり判定はそれぞれ3次元座標内で交差しているかどうかで判断できますが、我々が覗いているゲーム画面は2次元です。クリックやタッチがオブジェクトに触れているかどうかを判定するにはスクリーン上の座標から光線を取得するScreenPointRay()メソッドを使用します。
ScreenPointRay()メソッド
public Ray ScreenPointToRay(Vector3 position);
positionパラメータにスクリーン上の座標を指定することでそこから画面奥方向へ向かう光線を取得できるので、PhysicsクラスのRaycast()メソッドでそれが何かと衝突しているかを取得できます。ちなみにScreenPointToRay()メソッドの引数はVector3型ですが奥行きのz座標は使われません。
Raycast()メソッド
public static bool Raycast(Ray ray, out RaycastHit hitinfo);
rayパラメータには先ほどのような光線の情報を入れ、hitinfoパラメータには光線に衝突したオブジェクトの情報を格納するRaycastHit構造体を指定します。引数の変数を変更するためref, outキーワードを使っています。構造体にいちいち値を代入しておかなくてもいいようにoutキーワードの方を使っていますね。
RaycastHit構造体
public static RaycastHit
RaycastHit構造体には衝突したゲームオブジェクトの情報が入っています。
では例を書いてみます。
マウスがおかれている座標から光線を飛ばし(14行目)、それが衝突したオブジェクトの情報をhit構造体に格納し座標を加工して返す(17, 18行目)というものですね。短い中に色々工程が詰め込まれている。。。
マウスがcubeに乗っている間だけ回転する!
照明
照明はゲームにおいてもドラマや映画などにおいても非常に重要ですよね。雰囲気から心情や状況の描写まで照明によってその印象は全く違うものになってきます。
UnityのLightコンポーネントには4種類の照明が用意されており、Typeの欄からその種類を変更できます。
Spot :文字通り一箇所を円錐状に照らします。スポットライトですね
Directional :イメージとしては太陽の光のように、光源の座標に関係なくある角度から全てのオブジェクトを照らします。
Point :ある一点から周り全方位を照らします。蛍みたいです。
Area(baked Only) :四角形の範囲で照らす光ですが、演算処理の負荷が大きいらしく、リアルタイムでの描写はできないようになっています。そのため、ベイクしてもう周囲のオブジェクトへ反映のさせ方を決めておく必要があります。しかし柔らかくリアリティのある光が演出できるそうです。
スクリプトからLightコンポーネントのこれらの種類を変更するにはLightTypeプロパティから取得もしくは変更します。
LightTypeプロパティ
public LightType type { get; set; }
このtypeはエディター上で設定する時と同じ名前で大丈夫です。
ではプログラムを作成していきます
Start()メソッド内で光を写す床と光源を持ったオブジェクトを用意し、位置を整えます。
そしてUpdate()メソッドでは時間に応じて光がDirectionalとSpotを交互に変えるようになっています。16, 27, 30行目でライトを変更するLighttypeプロパティが使われています。
2秒ごとにスポットライトとディレクショナルライトが切り替わるようになりました。
このようにスクリプトからもエディター上でできる全ての変更を行うことができるんですね。今回はここまでにしておきます。
久々の更新です😇今も色々準備やら何やらで忙しいんですがこうして合間を縫って勉強しています。このGWも予定がいっぱいっぱい...Unite Tokyoもいくしお金がかつかつだな笑
Unityスクリプト / Mathematics編
山の羊の群
みなさんこんにちは🌚
テニスの錦織がまた最近浮上してきてくれて嬉しいブルーノです。ノーシードのタフさを感じたと言っていましたがやはり一度落ちると調子を取り戻すのは大変のようですね。リスクとの兼ね合いも考えながら頑張って欲しいです🤯
さて今回は、今までのものとは少し違い、目に見えないけどゲームやアプリを作る上で欠かせなさそうな数学的要素の取り扱いについて学んでいきたいと思います。
乱数
乱数という言葉の存在や仕組みはポケモンのおかげで今やだいぶ普通の人にも浸透してきたのではないかと勝手に推測していますが、乱数とは実行するまで結果が確定できないランダムな値のことを指します。乱数を使うにはUnityEnigine.Randomクラスのvalueプロパティから取得します。
UnityEnigine.Randomクラス
public sealed class Random
valueプロパティ
public static float value { get; }
このプロパティを使用することで、0.0 ~ 1.0までのランダムな値を取得します。乱数は呼び出すたびに新しいものが用意されます。実際に書いてみましょう
Vector3の各座標を0 ~ 5の値で生成してはその座標にcubeを作るというのを100回繰り返すコードです。結果は以下の通りになります。
なんか綺麗ですね。この結果は再生するたびに違うものになります
先ほどはvalueプロパティの値に色々引いたりかけたりして5という範囲までの数字を得ましたが、それをしなくても同じくRandomクラスのRangeプロパティを使用することで最初から指定した範囲内で乱数を得ることもできます。
Rangeプロパティ
public static float Range(float min, float max);
public static int Range(int min, int max);
minとmaxパラメータにそれぞれの型の数字を入力することでその範囲内の乱数を得ることができます。ちなみにmaxの値は含まれません
先ほど乱数はランダムな数値と言いましたが、実は完全にランダムではありません。シード値と呼ばれるタネをもとに作られます。基本的にシード値には現在時刻を利用しますが、Randomクラスのseedプロパティを利用すると自分でシード値を設定できます。つまり、シード値を保持しておけばそれを基に同じ乱数を生成することができるのです。
seedプロパティ
public static int seed { get; set; }
我々はUnityの中で角度を扱う場合、一般的にオイラー角を使用します。オイラー角は区間上にX, Y, Z軸のそれぞれの角度を持っていて、Vector3変数でそれを扱うことが多いです。しかしオイラー角ではジンバルロックという問題があり、正確に回転を表現できないことがあります。そこで4番目の数字を使うことでこれを回避しようということで、実際のUnity内部では四元数というものを用いています。まあ難しい解説は私にもわからないのでポイントだけ抑えると、「なぜUnityでは四元数で計算しているのに我々がUnityエディタ等で触れるのはオイラー角だけなのか」ということ。つまり四元数を我々に触れさせる前にオイラー角に直してくれているんですね。
まず四元数はQuaternion構造体を用いて表されます。
Quaternion構造体
public Quaternion(float x, float y, float z, float w);
そして四元数をオイラー角に直すには、Euler()メソッドを使います。
public static Quaternion Euler(Vector3 euler);
public static Quaternion Euler(float x, float y, float z);
引数にVector3型の情報を入れることでQuatrnion構造体に変換してくれます。これで、Unityが扱う他の空間系のメソッドに使うことができます。
では当然逆のもの、つまりQuaternion構造体からオイラー角を出してくれるメソッドもあるはずですね。それがeulerAnglesプロパティになります。
eulerAnglesプロパティ
public Vector3 eulerAngles { get; set; }
四元数とオイラー角間の計算にはコストがかかるため、Updateメソッドなどで連続して使用するのは避けたほうがいいらしいです。
他にも掘り出せばキリがないので、ゲームのときに頻出しそうなコンテンツだけを抜粋してみました。今回はこれで終わります。
人の気持ちというのはとても単純で複雑ですね。見方を変えれば全く理解できなかったものの気持ちというのも理解できるもんですね😙そしてそのきっかけは結局自分に回帰するのだと思います😎気の持ちようで周りは変わる
あーきのこスープ飲みたい
Unityスクリプト / 入力編(2/2)
オカバンゴ・デルタ - ボツワナ
みなさんこんにちは🌚
いきなり夏みたいな暑さで溶けそうなブルーノです。少し家を空けたら家の外より中の方が暑くなっていました🤑
さて今回は前回に引き続きUnityの入力について、少し特殊な入力方法について勉強していきます。
インプットマネージャー / Input Manager
Unityには、インプットマネージャーと呼ばれる機能があり、これを使うと複数の入力デバイスからの操作を1つのコマンドで設定することができます。簡単に説明すると、例えば「垂直方向」という名前をつけてその操作方法の中身を作っておけば、PSのコントローラーでもGCのコントローラーでも垂直方向キーにこの「垂直方向」インプットマネージャーを適応すれば微妙な調整や検証もいらずに直感的に操作方法を当てることができます。もう一つの特徴としては、単純にON・OFFで操作しないカーブや移動といった動作を滑らかに自然にしてくれる効果があります。百聞は一見に如かず ↓
インプットマネージャーは[Edit]→[Project Setting]→[Input]から設定します
色々メニューがありますが、[Horizontal]を覗いてみましょう。
AxisのSizeはこの入力の設定の数ですね。デフォルトでは18個入っているようです。足したい場合はこの値を増やしてリストを増やします。ちなみに個々の設定を仮想軸と言い、2方向の入力の仕方を設定します。(水平や垂直など。1方向でも可)
では上から順に各項目を説明します
Name: この仮想軸の名前を決めます。
Descriptive Name:仮想軸の正方向の説明です。ゲームランチャーでボタンを割り当てる際に表示されます。
Descrictive Negative:負方向の説明になります
Negative Button:負方向のボタンを設定できます
Positive Bottun:正方向のボタンを設定できます
Alt Negative Bottun:負方向の予備を設定できます
Alt Positive Bottun:正方向の予備を設定できます
Gravity:ボタンを話したときにどれくらいの速度で0に戻ろうとするかを設定します。大きいほどすぐ0に戻ります
Dead:0の範囲を設定します。つまり絶対値が0以上の値を入力しておけばそれ以下の時は反応しなくなります。
Sensitivity:反応の感度です。高ければすぐに反応し、低ければ鈍くなります。
Snap:反対方向の入力をされた時、値をすぐに0から始めるかを設定できます。
Invert:正負の方向を逆にします。
Type:仮想軸の操作を適応するデバイスの種類を設定します。
Axis:方向を指定します。例えば上のTypeでマウスの仮想軸を[X axis]に設定していた場合、カーソルを水平方向に移動した場合反応します。
Joy Num:コントローラーの番号を指定します。デフォルトでは全てのコントローラーを受け付けます。
そして設定した仮想軸を扱うにはGetAxis()メソッドを使用します
GetAxis()メソッド
public static float GetAxis(string axisName)
axisNameパラメータに使用する仮想軸の名前を記述します。例を書いてみます。
とてもわかりやすい。だからGetAxisメソッドの中はstring型で戻り値はfloatなんですね。たまに使うことはありましたが疑問に思っていました。
わかりにくいですが、キーを押した瞬間からは少しだけ加速し、離してから滑らかに停止します。
加速度
デバイスの動きを感知する加速度センサーは今やどんなあらゆるケータイに搭載されており、ゲーム機にもその機能を取り入れたものはどんどん出ています。いまいちその使い方に成功したように思えるゲームを私はあまり知らないのですが、新しい機能はどんどん開拓してみたいですね。
accelerationプロパティは現在の加速度をVector3型で取得できるプロパティです。
そのままオブジェクトのRotateに適用できるので設定は楽ですね。
IPhoneを振るとその方向によってCubeも異なる方向へ回転し始めます。操気弾を使ってるみたいで気分が良いです。
加速度センサーではデバイスの動きを感知することはできますが、傾きは感知されていません。一般的にスマホなどの傾けて遊ぶゲームは加速度センサーよりもこちらのジャイロスコープの方が使われているのではないでしょうか。
ジャイロスコープから得られる情報はgyroプロパティから取得することができます。
gyroプロパティ
public static Gyroscope gyro { get; }
このプロパティはジャイロスコープからの情報をUnityEngine.Gyroscopeクラスオブジェクトを返します。
なお、デフォルトではジャイロスコープの機能はOFFになっているのでスクリプトから利用する場合はまずenabledプロパティで有効にします。
enabledプロパティ
public bool enabled { get; set; }
このプロパティにtrueがセットされていればジャイロスコープの情報を得ることができます。そしていよいよ、現在のデバイスの姿勢をattitudeプロパティから取得します。
attitudeプロパティ
public Quaterion attitude { get; }
実際に作ってみましょう
25行目で一度Quaterion型の変数anglesに角度を格納し、その中の数値をGUIに表示します
デバイスを傾けるとそれに応じてCubeも傾きました。意思を持ってるみたいで面白いですね。今回はここまでにしておきます。
最近よく自分で料理を作ってみようとチャレンジしているのですが結局煮るか炒めるかになってしまうんですよね。なんかワンランク上のおしゃれな料理入門に最適な料理ってないですかねー🤔
Unityスクリプト / 入力編(1/2)
キューケンホフ公園 - オランダ
みなさんこんにちは🌚
ミッチ・アルバムの作品を勉強中のブルーノです。人間が決められた原子の組成でこの記憶も感情もあるのなら私が今ここに存在している確率でもう一度この私でいつか蘇ることができるのではないかと思うんですがどうでしょう?
さて今回は、あらゆる機器からの入力を受け取る方法について書いていきます。
我々が機械に物理的に意思を伝える方法としてはマウスやキーボード、タッチなど様々なものがあり、自分が作るゲームやアプリを使うデバイスが持つ入力装置からの入力を受け取れるようにしなければなりません。Unityでどうやってそれを行うのかを見ていきます。前編はマウス・キーボード・タッチの超基本的な入力についてです。
マウス入力
まず、全ての入力はUnityEngine.Inputクラスに内包されています。
UnityEnigine.Inputクラス
public sealed class Input
マウスカーソルの座標はmousePositionプロパティです。
mousePositionプロパティ
public static Vector3 mousePosition { get; }
ゲーム画面の左下隅を(0, 0)としてマウスカーソルの座標をピクセル単位で返します。Vector3なのでx, y, zは横・高さ・奥行きがありますが奥行きのzの値は常に0です。
例を見てみましょう
OnGUIメソッドから現在の座標を入力してみました。GUI.Label関数の引数の文章は""を入れてstring型にしないと直接Input.mousepositionプロパティの値(float型)を入れることはできないんですね。いやstring型にしないといけないのはわかってるけどこんな簡単でいいのか😃
このスクショをとるときの最後の地点が限りなく左下でした笑
マウスボタン
マウスのボタンが押されているかはGetMouseBottun()メソッドから得ます。
GetMouseBottun()メソッド
public static bool GetMouseBottun(int button);
buttonパラメータにはそれぞれ左ボタンの0, 右ボタンの1,真ん中のボタンの2のいずれかが入ります。指定したボタンが押されていればtrue,そうでなければfalseを返します。
例を書いてみます。
16行目でvar rに、マウスが押されていれば10を、そうでなければ1を代入し、次の17行目でY軸の回転量にそれを代入します。
マウスを押した時と通常時で回るスピードが変わる!
ところでこれだと、Update()メソッドに記述すると押された時のフレーム全てにtrueを返してしまうので決定ボタンとかの時は変な反応になってしまいますね。そこで「押してない→押してる」や「押してる→押してない」の時だけ反応するメソッドもあります。それが以下の二つです
GetMouseBottunDown()メソッド
public static bool GetMouseBottunDown(int button);
GetMouseBottunUp()メソッド
public static bool GetMouseBottunUp(int button);
Downの方は押された瞬間のみtrueを返し、Upは話された瞬間のみtrueを返します。どちらも戻り値はtrueです。
キーボード入力
キーボードのキーが押されているかはGetKey()メソッドを使用します。
GetKey()メソッド
public static bool GetKey(KeyCode Key)
public static bool GetKey(String name)
KeyCodeとは列挙型の変数で、中には全てのキーに対応した変数があります。そしてそれは文字通り標準的なキーボードのキー名を入れると出てきます。例えばスペースキーならSpace, AならAといった感じです。string型のnameパラメータはその文字を小文字で表します。今の例ならスペースは"space"、Aなら"a"といった感じです。
例を見てみましょう。
さっきとほぼ同じですが、17行目がスラッシュ(Slash, / )キーを押された時、に変わっています。
結果も同じですね。
当然マウスの時と同じように「押してない→押してる」や「押してる→押してない」の時だけ反応するメソッドも存在します。
GetKeyDown()メソッド
public static bool GetKeyDown(KeyCode Key);
public static bool GetKeyDown(string name);
GetMouseBottunUp()メソッド
public static bool GetKeyUp(KeyCode Key);
public static bool GetKeyDown(string name);
マルチタッチ
スマホのタッチはマウス同様座標を取得するポインティングデバイスという種類のうちの一つに入りますが、マウスとは違いスマホでは複数の入力を得ることができ、それをマルチタッチと呼びます。現在画面をタッチしているポイントの数を取得するにはtouchCountプロパティを使います。
touchCountプロパティ
Public static int touchCount { get; }
それぞれのタッチされているポイントの情報を扱いたい場合はGetTouch()メソッドから使います。
GetTouch()メソッド
public static Touch GetTouch(int index);
indexパラメータにはtouchCountプロパティの返した値、つまりタッチされているポイントの数だけ範囲を持つインデックスになります。3本指でタッチしている間はインデックスは最大3になり、最初のポインタのインデックスは0にあたります。
全てのタッチ情報を配列で得たい場合はtouchesプロパティで得られます。
touchesプロパティ
public static Touch[] touches { get; }
得る情報はUnityEngine.Touch構造体で表されています。
UnityEngine.Touch構造体
public struct Touch
タッチ情報の座標はpositionプロパティから得ることができます。
public Vector2 position { get; }
これもまたマウスの時と同じように左下隅を原点として(横, 縦)の座標を返します。
では実際に書いてみます。
for文のiをインデックスにもつtouch.positionの座標を全て表示します。
GUI.Label()メソッドだけだとインデックスの数を一つ送りにできなかったので別のint型のmで計算しました。
結果は以下のようになります
5本指でスマホに触れながらスクショをとりました。タッチ入力はUnityRemoteというアプリからできるのでそれを使いました。
得られたタッチの開始された瞬間や離された瞬間、現在移動しているかどうかの情報もphaseプロパティを使うことで得ることができます。
phaseプロパティ
public Touchphase phase { get; }
TouchPhaseは列挙型の変数で、中にはそれぞれ
Beganメンバ → タッチされた瞬間
Endedメンバ → 離された瞬間
Movedメンバ → 動いている間
Statinaryメンバ → 停止している間
Canceldメンバ → 何らかの原因でタッチの状態を追跡できなかった場合
が入っています。実際に確かめてみます。
一方の指は動かしながら、もう一方の指は止まった状態でスクショしました。ちゃんと「Moved」と「Stationary」と表示されていますね。
タップ
タップ?タッチとどう違う?と一瞬思いますが
タッチ → タッチパネルに触れている
タップ → タッチパネルに短い間隔で押して離す
という違いがあるんですね。このタップの回数はtapCountプロパティで取得できます。
tapCountプロパティ
public int tapCount { get; }
個々のタッチにはそれぞれIDが割り振られ、連続して押されたものなのかどうかを判断できます。そしてその連続でタップされた回数分だけこのプロパティに蓄積されるというわけです。実際に書いてみます
短い間隔でタップするとその指の回数はカウントされていきます。
では最後に、先ほど少し触れたタッチ情報のIDの識別の仕方を学びます。
タッチ情報を格納するTouch構造体はクラス(参照型)ではなく構造体(値型)なのでインスタンス化して識別はできません。そこで、Touch構造体にはfingerIDプロパティというIDが割り振られています。では確かめてみます
一度4本指で画面をタッチし、最初の2本を離したのち、また一本の指で画面に触れました。最初の2本を離してIDナンバー0と1は消えましたが、2と3は残ったままでした。そこで新たに触れるとまたナンバー0が生成されました。確かにそれぞれのタッチに識別番号が割り振られているようですね。
我々が普段何気なく行なっている操作も細分化するとこんなにいっぱい種類があってそれら全てに対応する物が用意されているんですねー🙂
今回はここまでにしておきます。
仕事の定義って何でしょう。私は社会的に需要があることと責任が伴うことが条件だと思っています。いや、責任が伴うから社会的に需要が生まれるのか?いずれにせよ、その条件を満たせば趣味も仕事にできるのではないのでしょうか。どうでもいいか笑