2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Hee-SanAdvent Calendar 2024

Day 3

Unityで、ポケポケみたいにカードを傾ける🃏

Posted at

リクエストがあったので、今日はUnityを触ってみようと思います!
3年ぶりのUnityなので、簡単なところから。

(Unityのバージョニング、一桁数字に戻ったんですね〜)

今回の目標

最近遊んでいるポケポケ(Pokémon Trading Card Game Pocket)のカードを眺められる画面を作ってみようと思います!

執筆時間の関係上、今回は「スワイプでカードを傾ける」までを目標にしたいと思います!

ゆくゆくは、立体的に見えるイラストや、シェーダーを使ったキラキラの再現などもしたいと思っています!

制作の流れ

自分のUnityリハビリも兼ねて、今回はシンプルな実装にします。
Unityを触ったことがないという友人からの執筆リクエストのため、丁寧めに書いていこうと思います!

  1. Unityプロジェクトの作成
  2. カードオブジェクトをシーンに配置
  3. カードを傾けるコードの作成
  4. 動作確認
  5. デプロイ

では始めていきましょう!

1. Unityプロジェクトの作成

Unity公式ページから、Unityをダウンロードしましょう

Unity公式ページ

Unityのバーションやプロジェクトを管理するためのデスクトップアプリ「Unity Hub」がダウンロードできます。
ダウンロードしたら、Unityアカウントでログインするなどしてください。
(自分はもともと環境が整っていたので、細かい手順はわからず...公式を参考にしてください!)

Unity Hubが立ち上がったら、右上のNew Projectからプロジェクトを作成できます。
今回は3Dのプロジェクトにしたいので、Universal 3Dを選びましょう。
右メニューでは、プロジェクト名や保存場所を指定できます。
一番右下にあるConnect to Unity cloudという設定は、今回は使わないのでOFFで構わないです。
プロジェクト作成画面

Create Projectを押して、以下のようなウィンドウが立ち上がれば、プロジェクト作成の完了です!
初期状態のProject

2. カードオブジェクトをシーンに配置

さて、現在見えているエディタ内のパネルについて説明しておきましょう。

  1. 真ん中のGameパネル
    • 完成したゲームの見た目・動作を確認できるパネルです。ウィンドウ上部の再生ボタンを押すっと、ゲームを起動できます。(今はまだ何も動かないと思いますが...)
    • Sceneタブに切り替えることで、ゲーム内オブジェクトの編集画面を開けます。ゲームを作っているときは、こっちを使いことが多いです
  2. 左のHierarchyパネル
    • 配置中のゲームオブジェクトの一覧です
    • デフォルトでは、「Main Camera」「Directional Light」「Global Volume」の3つが用意されています
      • Main Camera: その名の通りカメラです。Gameパネルで見えている景色は、このカメラを通した視点です
      • Directional Light: ライトです。これを消すと、Gameパネルでの視点が真っ暗になります
      • Global Volume: 少し難しいのですが、カメラのフィルタだと思ってください。いろんなエフェクトを付けたりできます
  3. 右のInspectorパネル
    • ゲームオブジェクトの詳細画面です
    • Hierarchyパネルで、例えば「Main Camera」を選択すると、色々出てきます。上部のTransformでは位置や角度などの調整、その下のCameraではカメラ特有の視野の調整などができます
  4. 下のProjectパネル
    • 見た目の通り、ゲームに関わるファイルを管理できます。表示されているのは、プロジェクト作成時に指定したフォルダ内の、プロジェクトフォルダの中身です
    • いろんな種類のファイルがあるので詳細は省きますが、Scenesフォルダ内にあるSample Sceneが、いま開いている"ゲームの世界"です。このSceneの中に、いまは3つのオブジェクト(Main Cameraなど)があると思ってください

では早速、カードを作りましょう!

左のHierarchyパネルの空いているところを右クリックして、「3D Object > Cube」を選びましょう。
すると、中央のGameパネルの真ん中に、小さな立方体が登場しました:tada:

Cubeがある世界

左のHierarchyパネルでCubeを選択した後、右のInspectorパネルで立方体の大きさを変えてみましょう。
Inspectorパネル内の、「Transform > Scale」が大きさの設定です。

今回は、以下のような設定にしてみましょう

  • X: 5.5
  • Y: 7.6
  • Z: 0.1

以下のような、カードっぽい大きさになりました!
(数値はポケポケの画面を定規で測って決めました笑)

これは誰がどう見てもカード

3. カードを傾けるコードの作成

次はコードを書いていきましょう。Unityで扱う言語はC#です。

下のProjectパネルの空いている箇所を右クリックして、「Create > MonoBehaviour Script」を選びましょう。
「#」マークの付いたファイルが作られるかと思います。
ファイル名は、「CardTilt.cs」にしましょう!
CardTilt.cs作成

ファイルをダブルクリックで開いてください。

エディタが開き、以下のようなコードが見えたでしょうか?
環境設定にもよるかなと思うのですが、VS Codeを使って開くことができるはずです。
はじめてのMonoBehaviour

ここにコードを書いていきましょう。

...今回は、いきなり完成コードから出してしまいます!
完成コード

using UnityEngine;

public class CardTilt : MonoBehaviour
{
    private Vector2 dragStartPos;

    void Update()
    {

        if (Input.GetMouseButtonDown(0))
        {
            dragStartPos = Input.mousePosition;
        }

        if (Input.GetMouseButton(0))
        {
            Vector2 difference = ((Vector2)Input.mousePosition - dragStartPos) * 0.1f;
            transform.rotation = Quaternion.Euler(difference.y, -difference.x, 0);
        }

        if (Input.GetMouseButtonUp(0))
        {
            transform.rotation = Quaternion.identity;
        }
    }
}

上からひとつずつ見ていきましょう!

using UnityEngine;

Unity用のいろいろをインポートするための設定です

public class CardTilt : MonoBehaviour
{

クラス名を、ファイル名に合わせてCardTiltにしました。
MonoBehaviourは、これを継承することでゲームオブジェクトのコンポーネントとして動作するクラスを作れます。
"Behaviour"はイギリス英語のスペルで、アメリカ英語で言う"Behavior"です。

{の改行に気持ち悪さを感じる方もいると思いますが、今回は、Unityが作るデフォルトコードのスタイルに従っておきます...

private Vector2 dragStartPos;

Vector2は、2次元ベクトルです。
これから、「スワイプでカードを傾ける」という機能を作ります。
このスワイプ時の、初期地点を保存しておく変数です。

今回のコードでは、タッチパネルでの指の操作とマウスによる操作を区別せずに実装します。
とりあえずマウスのドラッグ動作の気持ちでコードを書くので、変数名はdragにしました。
完成したものを実行する際には、マウス操作と指操作を区別すること無く、同じコードで処理できます。

    void Update()
    {

Update()関数は、初期コードのコメント分にも書かれていましたが、常に実行が繰り返される処理です。
だいたい1秒間に60~80回とかの頻度ですが、環境やCPU負荷によって変動します。

今回はこのUpdate()関数で、カードの傾きの更新処理を行います。

        if (Input.GetMouseButtonDown(0))
        {
            dragStartPos = Input.mousePosition;
        }

「もしマウスが左クリックされたら、dragStartPosに現在のカーソル位置を保存する」というコードです。
Input.GetMouseButtonDown(0)は、左クリックされた瞬間のみTrueになります。
("Down"が、”指を押し下げる動作”のイメージです)
0で左クリック、1で右クリック、2でミドルクリックを検知できます。

Input.mousePositionはその名の通り、カーソル位置を取得できます。

Input.GetMouseButtonDownの公式ドキュメントを見ると、僕が知らないうちに非推奨となっていたようです...ですが、今回は簡単のために使わせてください:pray:

        if (Input.GetMouseButton(0))
        {
            ...
        }

次はInput.GetMouseButton(0)です。
これは先ほどと異なり、"Down"がついていません。
これは、左クリックが押されている間ずっとTrueになります。

この中で、カードの傾きを更新します。

            Vector2 difference = ((Vector2)Input.mousePosition - dragStartPos) * 0.1f;

「ドラッグでどれだけカーソル移動したか」を保存しています。
これをもとに次の行でカードを傾けるのですが、そのままだとカードがぐるんぐるん回転してしまったので、0.1fを掛けてちょうどいい大きさにしています。(ffloatの頭文字です)

            transform.rotation = Quaternion.Euler(difference.y, -difference.x, 0);

さて、この行が今回のプログラムの難所です。

まずは、ざっくり説明から。
Quaternion.Euler()は、引数を3つ取って、"オイラー角"という傾きを管理する値を作ってくれます。
transform.rotationを更新することで、実際にゲームオブジェクトの傾きに反映されます。

では、詳しく説明しましょう。
Quaternion.Euler()の引数は、Quaternion.Euler(x軸の回転, y軸の回転, z軸の回転)という意味があります。

各軸の回転は、カードの回転でいうと、以下のようなイメージです。

  • X軸回転
    • カードが「うなずく」ような回転
    • カーソルを上に動かす → カードの上が奥に傾いてほしい
    • カーソルを下に動かす → カードの上が手前に傾いてほしい
  • Y軸回転
    • カードが「首を振る」ような回転
    • マウスを右に動かす → カードが右を向いてほしい
    • マウスを左に動かす → カードが左を向いてほしい
  • Z軸回転
    • カードが「首をかしげる」ような回転
    • 今回は使わない

また、コード内で引数にわたしている値は、以下のような意味です。

  • X軸回転: difference.y
    • カーソルの上下移動量
  • Y軸回転: -difference.x
    • 左右反転した、カーソルの左右移動量
  • z軸回転: 0
    • 今回は回転させないので0

ちなみに、Quaternion.Euler()が生成する値は、数学で言う"四元数(Quaternion)"という値です。
"複素数"が実部と虚部の2パラメーターを持っているのに対し、"四元数"は4パラメーター持っている数だと考えてください。
3次元回転の管理では"ジンバルロック"という厄介な"四元数"問題が発生しがちなのですが、それを解決するために、Unityでは"四元数"を使っています。

        if (Input.GetMouseButtonUp(0))
        {
            transform.rotation = Quaternion.identity;
        }

Input.GetMouseButtonUp(0)は、「マウスの左クリックを離したとき」です。
このとき、オブジェクトの傾きを、デフォルトの傾き(Quaternion.identity)に戻しています。

以上のコードで、カードを傾けられるようになりました!

4. 動作確認

では、実際にカードを傾けてみましょう!

CS Codeでコードを保存し、Unityに戻ると、1,2秒のモーダルが開いてコードの読み込みが行われます。

読み込みが終わったら、左のHierarchyパネルでCubeを選択してください。

その後、下のProjectパネルからドラッグアンドドロップで、作成したCardTiltファイルを、右のInspectorパネル内の下の方の何も無い場所に入れてください。

下記画像のように、Inspectorパネル内にCardTiltというコンポーネントが表示されればOKです!
CardTiltコンポーネント作成

たったこれだけで、このオブジェクトでCardTiltプログラムが動くようになりました!

早速、ウィンドウ上部の再生ボタンでゲームを起動してみましょう。

中央のGameパネル内でマウスをドラッグすると、カードが傾きます!!:tada:

5. デプロイ

最後に、せっかくなので、このプロジェクトをデプロイしてみましょう。
ブラウザで動かせるように、GitHubで配信してみましょう。

まずはUnity画面内でCmd+SCtrl+Sを押して、プロジェクトを保存してください。

次に、画面左上のメニューから、「File > BuildSettings」を開き、Platformを「Web」にします。
PlatformはWeb

自分の場合、この画像のような注意書きが出たので、Install with Unity Hubを押しました。
出てきた設定のまま、"WebGL Build Support"をインストールしましょう。

Unity Hubがインストールしてくれます...
Install WebGL Build Support

インストールが終わったら、Unityプロジェクトを一度閉じて、Unity Hubから再度開きましょう。
もう一度、画面左上のメニューから「File > BuildSettings」を開くと「Web」が使えるようになっています。

BuildSettings Web

「Switch Platform」を押し、処理が終わったら「Build」を押しましょう!
ファイル名を聞かれますが、自分はCardTiltにしました。
Save as CardTilt

ビルドには少し時間がかかります。

ビルドが終わったら、再度VSCodeを開いてみましょう。
プロジェクトファイル内に、CardTiltというフォルダが作成され、その中にindex.htmlがあります!!
VSCodeでビルド成果物を確認

最後にこれを、GitHubPagesでホストしましょう!

GitHubで、新しいリポジトリを作りましょう。
READMEも含めず、完全に空っぽの状態で作るのがおすすめです。
空のリポジトリ

ページ真ん中の、echoから始まるコマンドをコピーしちゃいましょう。

VS Codeに戻り、コマンドパレットを開いてください。
cd CardTiltで、ビルド成果物のフォルダに移動しましょう。

cd CardTilt

ここで、先ほどコピーしたコマンドを実行しましょう!
initial commit

また、ビルド成果物もコミットしちゃいましょう!

git add .                                                 
git commit -m "Add build files"
git push

GitHubでも確認できるはずです!
pushされたGitHub

最後に、「Settings > Pages」にて、Branchでmainを選択しましょう。
image.png

「Save」を押した後、しばらく待ちます。

1分ほど待ってリロードすると、ページが公開されます!
ページが公開

「Visit site」からページに移動してみましょう!!!

Unable to parse Build/CardTilt.framework.js.br!

:cry:


ビルド、デプロイには失敗してしまいましたが、エディタ上では動作が確認できたのではないでしょうか?

また次回、最後のエラーを解消する記事を書けたららなと思います!

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?