初めに
皆さんこんばんは~!
クリスマスをいかがお過ごしでしょうか?
クリスマスの定番と言ったら何でしょうか?…そうクソアプリ開発ですよね!!
ということで今回は自分が作ったクリスマスにぴったりのクソアプリとその作り方について紹介していこうと思います
今回作るもの
今回作るもの(作ったもの)はこちらになります。
このアプリについて簡単に説明すると、スマホの画面をタッチした場所に某漫画の人気キャラクターが勇ましいBGMと共に3Dで登場するというものです。
聖夜に作るにふさわしいクソアプリですよね!
Unityでapkファイルとしてこのアプリを作り、それをAndroid(バージョンは7以上ならOK)のスマホで動かしています。
もしこのアプリを自分のスマホで動かしたい方は自分のGitHubのリポジトリからダウンロードしてください
作り方
このアプリは以下のサイトの情報をもとに作りました。
このアプリの作成手順は上記の記事(特に一番目の記事)で詳しく説明されているので、この記事では作成手順については扱いません。しかし、その代わりにこの記事ではこのアプリの動作(挙動)を担うスクリプトを詳しく見ていこうと思います。(スクリプトについて興味がない方は読み飛ばしてしまって大丈夫です!)
アプリの動作(挙動)を担うスクリプト
そのスクリプトは以下の通りです。コメントアウト部分は解説用につけたものや元から書いてあるのを消し忘れたものなので、気にしなくてよいです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems; // .......(1)
public class PlaneDetection : MonoBehaviour
{
ARRaycastManager raycastManager;
[SerializeField] GameObject obj;
AudioSource audioSource;
[SerializeField] AudioClip sound1; // .......(2)
// Start is called before the first frame update
private void Awake() // .......(3)
{
raycastManager = GetComponent<ARRaycastManager>();
audioSource = GetComponent<AudioSource>();
audioSource.clip = sound1;
}
// Update is called once per frame
private void Update() // .......(4)
{
if(Input.touchCount == 0 || Input.GetTouch(0).phase != TouchPhase.Ended || obj == null)
{
return;
}
var hits = new List<ARRaycastHit>();
if(raycastManager.Raycast(Input.GetTouch(0).position, hits, TrackableType.Planes))
{
var hitPose = hits[0].pose;
Instantiate(obj , hitPose.position, hitPose.rotation);
audioSource.Play();
}
}
}
ここからはコメントアウトとして付け加えた番号順でこのスクリプトの解説をしていきます。(このアプリの作成を通じて初めてC#を触れた身ですので、解説がガバいところがあります)
(1)まずは宣言されている名前空間の確認をします。
-
System.Collections
およびSystem.Collections.Generic
はC#においてコレクションの利用のために宣言されています。コレクションとは配列よりも縛りの緩い要素の集合体です。(自分が使用してきたPHPやJSだと要素の集合体にコレクションや配列という区別がなく、基本的には要素の集合体=配列です) -
UnityEngine
にはUnit内の要素の操作に必要なものが含まれていて、この名前空間内のMonoBehaviour
クラスやInput
クラスの利用のためには宣言必須のものとなっています。 -
UnityEngine.XR.ARFoundation
には3Dオブジェクトを表示する場所の検知するクラスなどが含まれており、ARを利用する上では必須のものとなっています。 -
UnityEngine.XR.ARSubsystems
には検知する場所の形状を表す定数などが含まれており、こちらもARを利用する上では必須のもの(?)となっています。
(2)次に継承するクラスや初めに宣言する変数について見ていきます。
-
PlaneDetection
クラスが継承しているのはMonoBehaviour
クラスというものであり、このクラスを継承することで継承先のクラスはUnity内のオブジェクトのコンポーネントが参照できるGetComponent
メソッドやUnityの世界内に新たなオブジェクトを配置するInstantiate
メソッドが使えるようになります。 変数raycastManager
は後程行われるUnityEngine.XR.ARFoundation
内のARRaycastManager
クラスのインスタンスの代入のために宣言されます。 - 変数
obj
にはこのアプリで表示するオブジェクトが入ります。変数の前に[SerializeField]
と書くことで、Unityのインスペクターウィンドウから表示したいオブジェクトを指定できます。 - 変数'audioSource'は後程行われる
UnityEngine
内のAudioSource
クラスのインスタンスの代入のために宣言されます。 - 変数
sound1
には再生したい音声ファイルが入ります。これもUnityのインスペクターウィンドウから表示したいオブジェクトを指定できます。
(3)そして今度はAwake
メソッドを見ていきます。Awake
メソッドはMonoBehaviour
クラスが所有するメソッドで、このスクリプトが実行される際に最も早く、そして一度だけ行われるメソッドです。
-
GetComponent
メソッドを使用し、変数raycastManager
、audioSource
にそれぞれGameObject内のコンポーネントであるAR Raycast Manager
、Audio Source
が代入されます。ちなみにGetComponent
の横にある<>
はジェネリック
と呼ばれ、これによりこの中に書かれた型に対応したクラスを返してくれるそうです。(PHPにはこんな簡単に返り値の型を指定できる方法が(おそらく)ないので良いな~) -
audioSource
のclip
プロパティに先ほどセットしたsound1
を代入します。
(4)最後にUpdate
メソッドを見ていきます。Update
メソッドもAwake
メソッドと同様にMonoBehaviour
クラスが所有するメソッドで、このアプリの毎フレームごとに呼び出されます。公式サイトでは、Not every MonoBehaviour script needs Update.と書かれていたので、Unityの動作をつけるうえでは基本となるメソッドのようです。
- 最初のif文では、
Input
クラスを使用してアプリの使用者が画面のタッチを行る状態の場合かつ表示するオブジェクトが指定されている場合のみ次のステップへ進み、それ以外は何もしません。 - 変数
hits
にSystem.Collections.Generic
内のList
クラスによってコレクション化されたARRaycastHit
が代入されます。ARRaycastHit
にはアプリ内のオブジェクトを表示する場所の位置情報などが書き込まれます。 - 二つ目のif文では
ARRaycastManager
クラスのRaycast
メソッドを使用し、アプリ内でオブジェクトが配置可能な場所に使用者がタッチした場合次のステップへ進み、そうでない場合は何もせずに次のUpdate
メソッドへ進みます。Raycast
メソッドについてもう少し詳しく言うと、第一引数Input.GetTouch(0).position
が第三引数TrackableType.Planes
において検知可能とされた場合に、その位置情報を第二引数のhits
へ渡すという感じです。 -
Raycast
メソッドで渡された位置情報を変数hitPose
へ代入し、第2、3引数にその情報による場所と表示する向き、そして第1引数に表示するオブジェクトがセットされたInstantiate
メソッドが実行され、アプリ内にオブジェクトが表示されます。 - 一番最後に
AudioSource
クラスのPlay
メソッドが実行され、変数sound1
としてセットした音声ファイルが鳴ります。
終わりに
初めてUnityやC#を触り、またWebアプリしか作ってこなかったにも関わらず簡単にAndroidで動くアプリを作れて感動しました。
今度はARマーカーを使ったアプリやWebで動くARアプリなんかも作れたらな~と考えています。