誰でもVTuberになれる?「3tene(ミテネ)」を使ってみました(1)

色々試してみたいことがありますが時間が取れない昨今ですが、

今日は「3tene」を試してみました。

 

3tene(ミテネ)とは

公式サイト様より

http://3tene.com/

>これからバーチャルユーチューバーを目指す方に、簡単に手軽に扱えることを目的として作られたアプリです。

公開されたばかりのアプリケーションですが、具体的には以下の機能があります。

VRM形式で作られたアバターを表示できます。

・ウェブカメラがあれば、顔認識で頭の移動、まばたき、リップシンクを行えます。

・キーボードやゲームパッド入力で表情やポーズを変更できます。

・クロマキー合成用のブルーバック表示や、エフェクト機能があります。

・録画、スクリーンショット機能などがあります。

OBS Studioなどの配信ソフトと連携して、YouTubeで配信を行うことが出来ます!

起動

現時点ではWindows用のFree版のみが公開されています。

zipファイルをダウンロード、展開して、exeファイルを実行すればOKです。

6/3時点で、私のメインPC(Windows10)では何故か起動が出来ませんでした。ユニティちゃんライセンスのロゴが表示された後にエラーメッセージの表示が何も無く閉じてしまいます。何かのドライバかセキュリティソフトが悪さしてるのでしょうか……? 今後の修正に期待致します。ノートPC(実はこちらの方がスペックが少し良い)では無事に起動しました。

起動に成功したところ、背景に何もないスカイボックスと、左右にメニューが表示されています。

ボタンの説明は、公式サイト様の最初のスクリーンショットに書かれております。

f:id:chirotec:20180604002556p:plain

VRMファイル

VRMとは

VRMとは、2018年4月にドワンゴが提唱した、VRアプリケーション向けの人型3Dアバターデータを扱うためのファイルフォーマットです。

VRM - dwango on GitHub

人型に特化した統一データ形式、プラットフォーム非依存、ライセンスファイルを埋め込めるといった特徴があります。

VRMファイルの入手

ドワンゴが提唱した形式ですので、ニコニコ動画の関連サービス「ニコニ立体」では当然いち早く対応しております。

3d.nicovideo.jp

ニコニ立体でのダウンロードは、ニコニコ動画のアカウント(無料で可)が必要です。

利用条件、ライセンスは必ず確認しましょう。

この記事では、利用条件が非常に緩い「ニコニ立体ちゃん」を利用させて頂きます。

3d.nicovideo.jp

また、VRMファイルは自作することも出来ます。機会があれば取り扱いたいと思います。

アバターの読み込み

先ほどダウンロードしたVRMファイルを分かりやすい所(マイドキュメントの中など)に置いておきます。

3tene画面の右列・上から2番目のファイル選択ボタンを押し、このVRMファイルを選択します。

ライセンスに同意すると、アバターが読み込まれます。

f:id:chirotec:20180604003217p:plain

WebCamの起動

ウェブカメラがPCに接続されていれば、右上端のボタンを押すと、ウェブカメラを起動できます。

ウェブカメラの表示は、右列一番下のボタンでON/OFFが出来ます。放送中にうっかり押さないように気を付けましょう。

首やまぶたを動かすとちゃんと追随してくれます。可愛い。気が付くと本人の顔が緩んでいます。

 

スペックについて

Core i7-7700HQ、GeForce GTX 1050TiのスペックのノートPCでも、アバターのみ表示時には60fpsをキープ、カメラ起動時には30~50fpsが出ていました。 

ただし録画機能を使うと3~15fps程度になります。録画する場合はShadowPlayを使った方がいいかも。

f:id:chirotec:20180604005215p:plain

まとめ

このように非常にお手軽に試すことが出来ます。

興味ある方は、是非とも触ってみて下さい。

【雑記】Unityのアセットを買ってみました

いそがし

多忙で更新できず、本当にすみません。

更新ペースを回復しようと、リハビリに雑記を書こうかなーとしております。

 

セールで沢山買ってみた

というわけで近況報告です。

現在は既に終わってますが、5月上旬に行われたUnity Assete StoreのMADNESS SALEで多数のアセットを購入してみました。

昔は毎日日替わりでセールが行われていたのですが、去年あたりから日替わりセールは無くなってしまいました。(´・ω・`) NGUIとか安く買えたのにねー

基本的に半年に一度行われるこのセールが、アセットを安く購入できる手段になってしまいました。次回は秋の終わり頃かなぁ、今後もあるとは限りませんが……

 

当時のセールの情報およびアセットの情報は、こちらのブログを参考に致しました。

いつも読ませていただいてありがとうございます! 

www.asset-sale.net

 

今回は以下のアセットを購入しました。

Dynamic Bone

OpenCV for Unity 

Final IK

Bolt

Mesh Effects

Realistic Nature Environment

Ultimate Fantasy Creator

Low Poly Series: Landscape

Toony Colors Pro 2

Universal Sound FX

Graph And Chart

Vegetation Studio

 Riko

Camera Filter Pack

SPACE for Unity - Space Scene Construction Kit

 30%~50%割引とはいえ、今回は多少お高いアセットが多いので、全部で$400を超えていて結構な出費です。もちろん全部自腹(´・ω・`) 

Graph And Chart とか何で買ったんだろと思いましたが……物欲って素敵ですね☆(正直に申しますと、エディタ拡張などの参考にしようとも思っています)

 

この中で一番欲しかったのはOpenCV for Unity ですかね……御存じオープンソースの画像処理ライブラリが元となっていますが、こちらはなんとWebGL版にも対応しています。(どこまで使えるかはまだ検証していませんが、デモを見ると可能性を感じました)

assetstore.unity.com

Final IKとかDynamic Boneなども併用すると、今流行のばーちゃるゆーちゅーばーっぽいことが出来るかもしれません。

 

Vegetation Studioは新しいアセットでお値段が張りますが、可能性を感じるので購入。

草木を大量に配置したいですよねー(*´・ω・)(・ω・`*)ネー

assetstore.unity.com

 

SPACE for Unityで、宇宙をつくってみたいですよね。

これから宇宙を舞台にしたゲームを作るかどうかは分かりませんが……

assetstore.unity.com

 

Rikoちゃんは可愛いから買いました!(危険な発言) 以上!

assetstore.unity.com

こういった感じで欲しいアセットを買ったら、合計$471.40になってしまいました。某ゲームの石が852個買えるよヤバいヤバい

とは言いつつ、有意義な買い物かなーと思います。

終わり

本当はアセットの使用感をレポートしたかったですが、まだそれほど触ってないのでまた次の機会にしたいと思います。

よろしくお願いします。

Unityのゲーム作りをさくっと解説(4)

久しぶりの更新です(二度目)

やっと時間がとれそうです……m(__)m

今回はクリックしたときの判定など、よりゲームらしくしていきます。 

 

GUIを先に作ってしまう(uGUI)

説明が前後してしまいますが、GUI関連のオブジェクトだけを先に置かせていただきます。(クリック判定にイベントシステムを使いたいので)

UnityのGUIの歴史

昔のUnityのバージョンにもGUIシステムは一応ありましたが、それがゲーム中で使うにはあまりにもショボかったため昔は皆 NGUI 等の有料アセットを利用していました。

しかし、Unity4.6あたりで公式に新しいGUIが実装されました。このシステム公式では「Unity の新しい UI システム 」等と書かれていますが、一般的には「uGUI」と呼ばれています。(古い方のGUIシステムはエディタ等で使うため IMGUI として現在でも残っています。)

uGUIをシーンに追加

さっそくuGUIをシーンに追加してみましょう。

GameObject => UI => Text

を選択すると、CanvasEventSystemがまだない場合にはシーンに追加され、TextオブジェクトがCanvasの下に追加されます。とりあえず追加したTextオブジェクトの名前を分かりやすくScoreTextに変更しておきます。

(先にイベントシステムだけ触りたい場合は単にEventSystemだけを追加しても良いです。なお、EventSystemはシーン中に複数同時に作成することは出来ません。)

f:id:chirotec:20180428172141p:plain

f:id:chirotec:20180428172137p:plain

CanvasとTextの設定

Canvasの設定を少しだけ触ってみます。

Canvasでは、UIをシーン内のどこに描画するかを設定します。Render ModeをScreen Space - Cameraとすると、カメラに合わせて描画します。

  • Render Cameraで描画する基準となるカメラの指定を忘れずに。
  • Plane DistanceではUIを描画するカメラからの距離を設定します。普通はオブジェクトの手前にUIが描画されるようにします。

Canvas Scalerでは、画面のサイズが変更されたときにどのようにスケーリングするかを設定します。UI Scale ModeをScale With Screen Sizeにすると、画面サイズに合わせてスケーリングします。

  • Reference Resolutionで、基準となる解像度を指定します。

f:id:chirotec:20180428194641p:plain

また、先ほど作られた"ScoreText"オブジェクト内のTextコンポーネントで、表示するテキストを設定することが出来ます。

現在は仮のテキストを置いておきます。

f:id:chirotec:20180428194638p:plain

 

GameManagerのシングルトン化

GameManagerを他のオブジェクトのプログラム中から触りたいので、シングルトンとして扱います。この場合GameManagerもしくはそのアタッチされたGameObjectを一つしか使わない前提となります。シングルトンって何?と気になる方は「シングルトンパターン」等で調べてみて下さい。

基本はGameManagerクラスのstatic変数を用意して、作成時に自身を入れる、これだけです。

多重作成を防ぐために、代入時に判定し、すでにある場合はDestroyします。

また、外部からはgetのみを呼べるようにし、setは呼べないようにしておきます。

現在はまだ行いませんが、シーン遷移した場合もこのGemeObjectを残すようにDontDestroyOnLoad()を呼び出しておきます。

    // シングルトン
    private static GameManager _instance = null;
    public static GameManager Instance
    {
        get{return _instance;}
    }
    (略)
    private void Awake()
    {
        if (Instance == null)
        {
            _instance = this;
        }
        else
        {
            Destroy(gameObject);
            return;
        }
        DontDestroyOnLoad(gameObject);
    }
    

 

クリックイベントの処理

ここまでで前準備が終わりました。

ピースをクリックした判定を、 イベントシステム で受け取り、処理を行います。

ピース側の処理

まず下記のようなPieceControl.csスクリプトを作り、各ピースのプレハブにアタッチしておきます。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems; // ← 必要

public class PieceControl : MonoBehaviour, IPointerClickHandler{
    // ピースの種類(色)
    public int PieceType;

    // 選択されたピースのフラグ
    public bool SelectFlag;
    // 選択されたピースに接続しているかのフラグ
    public bool JoinFlag;
    (略)
    public void OnPointerClick(PointerEventData eventData)
    {
        GameManager.Instance.OnClickPiece(this);
    }
}

 ついでに自身の色の情報も割り当てます。各ピースのプレハブのPieceTypeに、異なる数値を割り当てておきます。

SelectFlag, JoinFlagはこの記事の下の方で扱います。

f:id:chirotec:20180428194644p:plain

 

イベントシステムからクリックイベントを受け取るために、IPointerClickHandlerインターフェースを継承しています。

Colliderは既に(衝突判定を行うために)追加済みですので、実行中にGame画面をクリックするとOnPointerClick()関数がイベントシステムより呼び出されます。 

クリックされたことを検知したときに、GameManager側のOnClickPiece()を呼び出します。GameManagerはシングルトン化しているので、FindComponent()等で検索しなくても済みます。

 

GameManager側の処理 

GameManagerクラスに、次の処理を追加・変更します。

まずは、毎回ピースをシーン内から検索しなくても済むように、リストで管理します。

Update()の生成処理も書き換えます。

    // 生成したピースのインスタンス
    public List<PieceControl> pieceList;// ピースがクリックされたときに呼ばれる
    (略)
    void Update () {
        // ------------- ピース生成処理 ---------------
        // 一定回数呼ばれる毎にピース生成処理を行う
        tCount++;
        if (tCount >= genFrame)
        {
            if (pieceList.Count < pieceCountMax) // ←リストから判定
            {
                // 存在するピースの数が一定数以下の場合、新しくピースを生成する
                int pieceColor = Random.Range(0, 4);
                float pieceX = Random.Range(-2.0f, 2.0f);
                float pieceY = 6.0f;
                GameObject pieceObject = Instantiate(piecePrefab[pieceColor], new Vector3(pieceX, pieceY), Quaternion.identity);
                pieceList.Add(pieceObject.GetComponent<piececontrol>()); // ←追加
            }
            tCount = 0;
        }
    }
    // 対象のピースを削除する
    public void EracePiece(PieceControl piece)
    {
        // リストから除去
        pieceList.Remove(piece);
        Destroy(piece.gameObject);
    }

単純に C#のListコレクション で管理しています。生成時にリストに追加し、削除時にリストから除去しています。

次にGameManagerにクリック処理が呼ばれたときの関数を追加します。前段落のGameManager.Instance.OnClickPiece(this);で呼び出しているところです。

    // ピースがクリックされたときに呼ばれる
    public void OnClickPiece(PieceControl _piece)
    {
        EracePiece(_piece);
    }

これでクリックすると、ピースが一個消え、新しいピースが一個降るようになります。

f:id:chirotec:20180428203828g:plain

繋がったピースの判定 

クリックしたピースと同じ色で繋がったピースを消すようにしたいと思います。

この辺りからやや難解になりそうですが、

まずはソース一式を貼ります。

    public void OnClickPiece(PieceControl _piece)
    {
        // クリックしたピースとの接続判定を行います。
        OnSelectPiece(_piece);

        // 接続されたピースを全て消します。
        pieceList.FindAll(x => x.JoinFlag).ForEach(x =>
        {
            EracePiece(x);
        });
    }
    // ピースが選択されたときに呼ばれる
    public void OnSelectPiece(PieceControl _piece)
    {
        // フラグを一旦クリア
        pieceList.ForEach(x => { x.SelectFlag = false; x.JoinFlag = false; });
        pieceList.Find(x => x == _piece).SelectFlag = true;

        // ------------接続されたピースを探索します。------------------
        // 接続されたピースのリスト
        List<PieceControl> joinedPieceList = new List<PieceControl>();
        joinedPieceList.Add(_piece);
        // 接続判定対象の残りのピース
        List<PieceControl> fieldPieceList = new List<PieceControl>(pieceList);
        fieldPieceList.Remove(_piece);

        // 接続されたピースのフラグをON
        while (true)
        {
            List<PieceControl> addJoinedList = new List<PieceControl>();
            foreach (var joinedPiece in joinedPieceList)
            {
                foreach (var fieldPiece in fieldPieceList)
                {
                    // 色が違うか
                    if (fieldPiece.PieceType != joinedPiece.PieceType) continue;
                    // ピース間の距離が一定以上か
                    float d = Vector3.Distance(fieldPiece.transform.position, joinedPiece.transform.position);
                    if (d <= pieceRadius * 3.0f) // 半径1個分のスペースは許容する
                    {
                        // これも接続する。接続リストの末尾に追加する。
                        addJoinedList.Add(fieldPiece);
                    }
                }
            }
            // もう接続ピースが無い場合は抜けます。
            if (addJoinedList.Count == 0) break;
            // 接続リストに追加します。
            joinedPieceList.AddRange(addJoinedList);
            // 未接続リストから除外します。
            addJoinedList.ForEach(x=> fieldPieceList.Remove(x));
        }

        // 接続フラグを立てます。
        joinedPieceList.ForEach(x => x.JoinFlag = true);
    }
    

 

特に

 pieceList.FindAll(x => x.JoinFlag).ForEach(x => EracePiece(x););

て何だ! と感じる方が多いと思われます。

これはラムダ式と言います。上の例では最初のFindAll()関数ではpieceListの要素のうちからJoinFlagが立ったオブジェクトを集めたものをリストとして取得して、次のForEach()関数では前述のリストの各要素毎に、EracePiece()関数を呼び出しています。

そもそもListって何? コレクションって何? なC#やプログラムの初心者さん向けでやる内容じゃないと思いますが

許してください(´・ω・`)

代わりにラムダ式を使わないでforeach文などを使って書くと以下のようになります。

    public void OnClickPiece(PieceControl _piece)
    {
        // クリックしたピースとの接続判定を行います。
        OnSelectPiece(_piece);

        // 接続されたピースを全て消します。
        List<PieceControl> listJoinedPiece = new List<PieceControl>();
        foreach(var x in pieceList)
        {
            if (x.JoinFlag) listJoinedPiece.Add(x);
        }
        foreach(var x in listJoinedPiece)
        {
            EracePiece(x);
        }
    }
    // ピースが選択されたときに呼ばれる
    public void OnSelectPiece(PieceControl _piece)
    {
        // フラグを一旦クリア
        foreach (PieceControl p in pieceList)
        {
            p.SelectFlag = false;
            p.JoinFlag = false;
        }
        // 選択したピースのフラグをON
        foreach (PieceControl p in pieceList)
        {
            if (p == _piece)
            {
                p.SelectFlag = true;
                break;
            }
        }

        // ------------接続されたピースを探索します。------------------
        // 接続されたピースのリスト
        List<PieceControl> joinedPieceList = new List<PieceControl>();
        joinedPieceList.Add(_piece);
        // 接続判定対象の残りのピース
        List<PieceControl> fieldPieceList = new List<PieceControl>(pieceList);
        fieldPieceList.Remove(_piece);

        // 接続されたピースのフラグをON
        while (true)
        {
            List<PieceControl> addJoinedList = new List<PieceControl>();
            foreach (var joinedPiece in joinedPieceList)
            {
                foreach (var fieldPiece in fieldPieceList)
                {
                    // 色が違うか
                    if (fieldPiece.PieceType != joinedPiece.PieceType) continue;
                    // ピース間の距離が一定以上か
                    float d = Vector3.Distance(fieldPiece.transform.position, joinedPiece.transform.position);
                    if (d <= pieceRadius * 3.0f) // 半径1個分のスペースは許容する
                    {
                        // これも接続する。接続リストの末尾に追加する。
                        addJoinedList.Add(fieldPiece);
                    }
                }
            }
            // もう接続ピースが無い場合は抜けます。
            if (addJoinedList.Count == 0) break;
            // 接続リストに追加します。
            joinedPieceList.AddRange(addJoinedList);
            // 未接続リストから除外します。
            foreach(var x in addJoinedList)
            {
                fieldPieceList.Remove(x);
            }
        }

        // 接続フラグを立てます。
        foreach (var x in joinedPieceList)
        {
            x.JoinFlag = true;
        }
    }
    

どちらが分かりやすいでしょうか?

初心者向けではないとは思いますが、この考え方は色々な言語で役に立つと思います。多分。

 

話を戻します。

上記の処理のうちOnSelectPiece()では、選択したピースと同色で繋がっているピース全てをリストアップし、JoinFlag を立てています。全てのピースの繋がりを調べて、繋がっているピースをjoinedPieceListに貯め、最後にJoinFlag を立てます。

次に JoinFlag が立ったピースを全て削除します。

f:id:chirotec:20180428205428g:plain

 

基本のゲームシステムが出来上がりました。

次回は、演出を加えて豪華にしていきます!

姿勢推定とVRのお勉強

突然ですが、アニメとかゲームのキャラを自由に動かせたら楽しいと思いませんか?

バーチャルYouTuberさんもいいですね。私はシロさんが好きです。それ以外にも自由自在にキャラを動かせたら……と思うと夢が広がりそうです。

 

色々な手法があるようです。大まかには

モーションキャプチャーシステムやモーションセンサーでキャプチャ

・カメラ映像からそれっぽく生成

・あらかじめ大量のモーションを事前登録してその中から再生 ……など

 

機材用意する手間や費用を考えると、カメラを使えるとお手軽そうです。

カメラ映像からモーションを生成する手法のひとつについて調べてみました。

 

姿勢推定

CMUカーネギーメロン大学)で公開された

[1611.08050] Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields

という論文があります。

姿勢推定、画像中の複数の人の2D姿勢を効率的に検出する手法とのことです。

映像から、リアルタイムに人間の姿勢を取得するのですね。

内容

こちらの方のメモを参考にさせて頂きました。

yusuke-ujitoko.hatenablog.com

構造はCNN(畳み込みニューラルネットワーク)で、

・まず一つ、Part Confidence Mapsを作り、体部位の位置を予測する

・もう一つ、Part Affinity Fieldsを作り、体部位間の繋がりを予測する

・これらを連結して、結果を出力する。

これをひとつのstageとし、これを繰り返して、精度を高める。

 

ただPart Affinity Fieldsを解くのはNP困難なので、問題を緩和する。

・エッジの数が最小になるように条件を決定する

・隣接する部位の間のみを解く

 

と問題を単純にするようです。

 

うーん、まだ正直よく分かってない、もう少し調べないと……

もっと機械学習を勉強して、プログラムを作ってみるのが良いのでしょうか。

 

実装例

CMUではOpenPoseというC++ライブラリを公開されています。研究用、非商用だと無料で扱えるとのことです。

 

また、DeNAの研究開発の方がPythonとChainerで実装されていたりします。

こちらの記事もとても参考になります。

engineer.dena.jp

サンプルプログラムを実行しましたが、顔の輪郭や体の姿勢がリアルタイムで取れていました。素晴らしい。

 

おわり 

あまりまとまってなくてすみません。

近いうちに実際に組んでみたいかと思います。

Unityのゲーム作りをさくっと解説(3)

久しぶりの更新です……

多忙により前回の更新より少し間が開いてしまいました、すみません。

 

Unityの初心者向けさくっと解説です。

今回はスクリプトを導入します。

出来ることが大幅に広がり、いよいよゲームらしくなってきます。

 

コンポーネントの追加

現在、シーン内に機能を持たない玉オブジェクトがぽつんと置かれている状態です。(※厳密にはスプライトを描画する機能だけを持っています)

Unityでは、このオブジェクトコンポーネントを足して機能を追加します。

参考:ゲームオブジェクト - Unity マニュアル

物理エンジン関連コンポーネントの追加

HierarkeyウインドウまたはSceneウインドウで玉オブジェクトを選択すると、Inspectorウインドウにコンポーネントが表示されます。

現在の玉オブジェクトには「Transforrm」と「Sprite Renderer」コンポーネントのみがあります。

f:id:chirotec:20180407175243p:plain

玉オブジェクトに、コンポーネントを追加します。 InspectorウインドウのAdd Componentボタンよりコンポーネントを追加(アタッチ)出来ます。

ここではPhysics 2Dカテゴリーの「RigidBody 2D」を追加してみます。 f:id:chirotec:20180407175237p:plain

動かしてみます。「Play」ボタンを押すとエディタ内で動作します。

f:id:chirotec:20180407175531g:plain

玉が落ちていきました。RigidBody 2Dにより、このようにオブジェクトが物理エンジンによる影響を2D空間内で受けるようになります。

次は、玉に「Circle Collider 2D」を、周囲の壁3つに「Box Collider 2D」をアタッチします。

f:id:chirotec:20180407175524g:plain

接触判定が行われるようになりました。

 

プレハブ化

次は玉を大量に生成したいですが、その前に「プレハブ化」を行います。

オブジェクトをプレハブに格納しておくことで、複製が容易になります。

プレハブの作成

上のメニューからAssets -> Create -> Prefab

またはAssetsウインドウで右クリックしてCreate -> Prefabを選択します。

f:id:chirotec:20180407175233p:plain

空のプレハブ「New Prefab」がプロジェクト内に作られます。分かりやすいように名前を付けておきます。

f:id:chirotec:20180407191235p:plain

Hierarchyウインドウのオブジェクトをプレハブにドラッグアンドドロップすると、オブジェクトの内容がプレハブに格納されます。

f:id:chirotec:20180407192715g:plain

また、これまでシーン中にあったオブジェクトはプレハブに関連付けされ、このプレハブのインスタンス(実体)となります。

試しにプレハブをシーン中にドラッグアンドドロップしてみると、プレハブの複製が新しいインスタンスとしてシーン中に配置されるのが分かると思います。

プレハブのインスタンスはHierarchyウインドウ内では青文字となり、Inspectorウインドウでは「Prefab」の項目が表示されます。

f:id:chirotec:20180407193825p:plain

例えばシーン中に配置したインスタンスを更新した後にApplyボタンを押すと、プレハブが同じ状態に更新されます。
なお、メニューの「GameObject -> Break Prefab Instance」を選択すると、このオブジェクトとプレハブの関連付けを解除できます。

スクリプト

ここではゲームのシーン全体を管理するスクリプトを追加します。

スクリプトの導入

ここでは空のオブジェクトを作ってスクリプトを置きます。どこに追加するかは迷うところですが、例えばカメラのオブジェクトに追加してもいいと思います。

HierarchyウインドウかGameObjectメニューの「Create Empty」で空のオブジェクトを生成します。

InspectorウインドウのAdd ComponentボタンからNew Scriptを選択すると、新しいスクリプトがAssetsフォルダに追加されると同時にオブジェクトにアタッチされます。

f:id:chirotec:20180407175230p:plain

Projectウインドウのスクリプト(歯車のアイコン)をダブルクリックすると、スクリプトエディタが起動します。Windows版のUnity2017の標準的なインストール設定だとVisual Studio 2017 Communityが起動するはずです。(標準的にはMonoDevelopがあります。Visual Studio Codeなどを使用することも出来ます。)

f:id:chirotec:20180407175543p:plain

※右上のアカウント情報は伏せてます

スクリプトの編集

C#の解説は少な目です(すみません……他サイト様のC#の解説なども参照願います)

Unityのスクリプトは基本的にはMonoBehaviourクラス ※リファレンス の派生クラスとなります。ここにゲームオブジェクトの振る舞いを実装します。

(画像)

f:id:chirotec:20180407175540p:plain

(テキスト)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

    // フレームのカウンター
    private int tCount = 0;
    // ピース(現在はボール)
    public GameObject peace;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        tCount++;
        if (tCount>=30)
        {
            // 新しくピースを発生させる
            Instantiate(peace, new Vector3(1.8f, 5.0f), Quaternion.identity);
            // カウントを0に戻す
            tCount = 0;
        }
    }
}

Update()関数は毎フレーム呼び出される関数です。30フレームごとにInstantiate()関数 ※リファレンス を呼び出し、ボールのプレハブのインスタンスを生成します。

 

メンバ変数のpeaceが初期化されてないように見えますが、これはInspectorで行うためです。 後で気が付きましたが、pieceのスペルを間違ってました

publicの変数はインスタンスが生成されるときに初期化されます。GameObject型の変数にはプレハブやシーン中のオブジェクトを入れられます。ここで先ほど作成したボールのプレハブを指定しましょう。 

f:id:chirotec:20180407175537p:plain

publicの変数はインスタンスが生成されるときに初期化されます。ここで先ほどのボールが入ったプレハブを指定しましょう。 

 

実行してみます。

f:id:chirotec:20180407220259g:plain

上から降り続けるようになりました。

スクリプトの改良

もう少し修正してみます。

  • 4色ランダムで降るようにする
  • 降ってくる位置をランダムにする
  • 降ってくる頻度を変更できるようにする
  • シーン中に存在する玉数の上限を決め、一定以上降らないようにする

生成元のプレハブを配列にし、複数の中からランダムで選ばれるようにします。

Random.Range()は乱数を生成する関数です。引数が整数(int)型のときと小数(float)型のときは振る舞いが少し異なります。※リファレンス Random.Range

降ってくる玉の種類を0以上4未満のうちからランダムで選択し、生成するx座標を2.0f以上2.0f以下からランダムで決定します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour {

    // フレームのカウンター
    private int tCount = 0;
    // ピースを一個生成するフレーム数
    public int genFrame;

    // これまでに生成したピースの数
    private int pieceCount = 0;
    // ピースの最大生成数
    public int pieceCountMax;

    // 生成するピースのプレハブ
    public GameObject[] piecePrefab;

    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        tCount++;
        if (tCount >= genFrame)
        {
            if (pieceCount >= pieceCountMax)
            {
                int pieceColor = Random.Range(0, 4);
                float pieceX = Random.Range(-2.0f, 2.0f);
                // 新しくピースを発生させる
                Instantiate(piecePrefab[pieceColor], new Vector3(0, pieceX), Quaternion.identity);
                pieceCount++;
            }
            // カウントを0に戻す
            pieceCount = 0;
        }
    }
}

 

色違いのボールのプレハブを3種類用意します。

f:id:chirotec:20180407210917p:plain

配列となったGameObject型変数pieceのサイズに4を入力して、プレハブを入れます。他のパラメータにも値を入れましょう。ついでにスペルミスも直しました

f:id:chirotec:20180407210923p:plain

実行

 

f:id:chirotec:20180407214158g:plain

非常にそれっぽくなりましたね。 降ってくる最大数のパラメータを変更すると、その通りになるのが確認出来ると思います。

 

次回予告 

次回はユーザーの操作も入れて、よりゲームらしくします。 今度はなるべく早いうちに……

 

Unityのゲーム作りをさくっと解説(2)

御礼

前回の初心者向けUnity記事を公開したところ、アクセスが急増して

私たいへん驚いておりますΣ(・ω・ノ)ノ

ご覧になってくださった皆様、ありがとうございます! 

前回の記事はこちらです。

chirotec.hatenablog.com

今回は一から自分でゲームを作成していきます。

これどう考えても3、4回じゃ終わらないですね…… 

 

ゲーム作り

まず、どんなゲームを作ってみようかと考えます。

今回は以下のようなゲームをイメージしました。

・パズルゲームっぽいゲーム

・フィールドはコップを横からみたような形状、そこに色の付いた玉が敷き詰められている

・玉は自然にそれっぽく動く(物理演算で落下し衝突する)

・玉をタップ/クリックしたら繋がった同じ色の玉が消え、消した分だけ次の玉が降ってきて補充される

イメージ図としては次のようになります。

f:id:chirotec:20180323110729p:plain

それでは、作ってみましょう。

 

プロジェクトと最初のシーンを作成

まずは新規プロジェクトを作成します。

ここで2Dか3Dを選択しますが、2DにするとEditorの設定が2Dゲームを作るのに適した状態となります。(後で変更可能(公式マニュアル)です)

今回は2Dで作成します。

f:id:chirotec:20180323102053p:plain

 

開いたときにデフォルトのシーンが作成されていますので、そのシーンをmainなど分かりやすい名前を付けて保存します。(File->Save Scene)

f:id:chirotec:20180323102333p:plain

不慮の事故で作業状況が失われると非常に悲しいので、ctrl+Sで頻繁にシーンを保存する癖を付けるべきかも。 

 

 

ゲーム作り開始

前回は完成品のプロジェクトをそのまま使いましたが、

今回は自作の画像を取り込んで、シーンを作成していきます。

素材のインポート

 壁と玉の画像を用意します。

(今回は仮の画像なので、すごく適当な画像です)

f:id:chirotec:20180323104316p:plain:f:id:chirotec:20180323114957p:plain:f:id:chirotec:20180323115003p:plain:f:id:chirotec:20180323115006p:plain:f:id:chirotec:20180323115011p:plain:

ProjectウィンドウのAssetsのところで右クリックして「Import New Assets...」を選択するか、もしくはエクスプローラーから直接ドラッグアンドドロップします。

f:id:chirotec:20180323120331p:plain

画像ファイルから生成されたスプライトが、プロジェクトに追加されました。

ここで3Dモードだと、テクスチャが追加されてしまうはずです。 

 

壁の作成

現在、シーン中にはカメラしかありません。

まずは壁を作ってみましょう。

“GameObject->2D Object->Sprite”

とすると、空の2Dスプライトがシーン内に追加されます。

左のHierarchyを見ると、"New Sprite"が追加されているのが分かると思います。

このままだと、ゲーム中では何も見えません。

f:id:chirotec:20180323122926p:plain

左のHierarchy内に追加された"New Sprite"をクリックすると、右の"Inspector"内にオブジェクトの詳細が表示されます。これはオブジェクトの種類によって変わります。

"Transform"が位置、"Sprite Renderer"が2Dスプライトとその描画設定を表します。

カメラをクリックした後に先ほどの操作をすると、追加されたスプライトの位置がカメラに重なっている場合があります。Positionのz座標が0になっていない場合は、0にしておいて下さい。

"Sprite"の右の丸をクリックし、壁の画像を選択すると、スプライトが描画されるようになります。

f:id:chirotec:20180323130052p:plain

実はProjectビューからアイコンをSceneビューにドラッグアンドドロップしてもシーンに追加出来ます。

側面と底のスプライトをそれぞれ追加して、サイズと位置を調整して壁を作ります。名前もwall_leftなど分かりやすくしましょう。

f:id:chirotec:20180323130121p:plain

玉の仮作成

同様に玉も置いてみます。とりあえず一個だけ配置します。

f:id:chirotec:20180323131702p:plain

……

どうするの?

しかし、本来玉はランダムで沢山降ってくるはずです。

・玉を落下させるにはどうすればいいのか?

・ゲーム中で玉を新しく作るには? 

・クリックしたら消える処理は?

 

これからひとつひとつ解決します。

・玉にRigidbodyを追加、玉と壁にColliderを追加し、物理演算で動かす

・玉をプレハブ化して、同じ物を大量に降らせる

クリック判定玉を消す処理を作る

 

いよいよゲーム作りらしくなってきました。

ここで一旦区切り、ひとつひとつ解説します。

次回へ続く。

 

次回予告

今回はゲーム中の画面をそれらしく作ってみました。現状では「ただそこにある」だけで動きません。見栄えもたいへん地味です。

次回は先ほど追加した球が物理演算で動くようにし、さらに玉がゲーム中で降ってくるようになります! スクリプトにも触れますのでお楽しみに!

更新頑張ります。多分土日くらい?

Unityのゲーム作りをさくっと解説(1)

特別編

今日は気分転換です。

下のミニゲームがどのように作られているかを紹介したいと思います。

https://unityroom.com/games/minibakery 

使い方とかはぶっちゃけ公式のマニュアルUnity User Manual (2017.3) - Unity マニュアルを参考にすればいいのですが、軽く流れを触れます。

長いので3~4回くらいの連載になりそうです。Unityのことを知らない方や、初心者の方向けの解説になればいいなあ。

 

Unityとは

Unityと名前が付いたプロダクトはいくつかありますが、もちろんここでは

「Unity Technologies社の公開しているゲームエンジン、開発環境」を指します。

うぶん/とぅのデスクト/ップ環境とは関係無いです

unity3d.com

同社いわく「上位の人気オンラインゲームの内34%がUnityで制作されています。」だそうですよ。

なおライバルとなる製品にはUnreal Engineや、オープンソースのCocos2d-xなどがありますね。

 

Unityのインストール

同社のサイトからUnity Personalのインストーラーをダウンロード、実行します。基本的に画面の指示に従うだけです。

開発のターゲットに応じてインストールするコンポーネントを選択します。例えばChromeFirefoxなどのウェブブラウザで遊ぶゲームを作成する場合は「WebGL Build Support」にチェックを入れておきましょう。

f:id:chirotec:20180321133327p:plain

また、まだインストールされていない場合はVisual Studio 2017 Communityを一緒にインストールすることも出来ます。スクリプトC#ソースコード)の編集やデバッグに使います。

 

アカウントを作成・認証(メールアドレスが必要です)し簡単なアンケートに答えると、いよいよUnityを使用出来ます。

  

プロジェクトの作成

Unityを起動すると、以下のような画面が出てきます。

f:id:chirotec:20180321134719p:plain

「Project」タブに現在PCに保存されているUnityプロジェクトの一覧が、「Learn」タブにはチュートリアル等が表示されています。

右上の「New」ボタンを押し、適当なプロジェクトを作ってみましょう。

 

Unityにようこそ

これから永らくお世話になるUnity Editorの画面です。

f:id:chirotec:20180321140102p:plain

画面内に多くのウィンドウがあります。これはDefaultの配置ですが

・右上のLayoutセレクトボックスを選択

ドラッグアンドドロップ

・Windowメニューから追加

などで自由にレイアウトを弄ることが出来ます。詳しく知りたい方は公式マニュアルのインターフェースについてとかメインウィンドウをお読みください。

個人的には「2 by 3」のレイアウトが使いやすいと思ってたり。

(※この記事では、ウィンドウを見やすくするためちょくちょくレイアウトを弄っています。)

 

アセットの導入

アセットとは、ゲームの部品です。

画像、モデルデータ、エフェクト、音楽、効果音などの素材やスクリプト、完成プロジェクト、エディタの拡張まで様々な種類があります。

アセットストアで無料のものから数百ドルのものまで入手することが出来ます。

https://www.assetstore.unity3d.com/jp/?stay

 

サンプルプロジェクトの導入

今回、試しにサンプルプロジェクト"Tanks! Tutorial"を入れてみます。(これは完成プロジェクトですので、新規プロジェクトを作って追加してください)

https://www.assetstore.unity3d.com/jp/?stay#!/content/46209

 

アセットをインポート後、プロジェクトウィンドウを見ると色々追加されたのが分かると思います。

とりあえずSceneファイル(ここでは「_Complete...」という名前のUnityロゴのアイコン)を開いてみて下さい。

f:id:chirotec:20180321144440p:plain

 

シーンビュー、ゲームビューを見ると、完成品のゲームの一場面があることが分かります。

f:id:chirotec:20180321145654p:plain

 

画面上部のPlayボタン(三角)を押すと、Editor上のゲームビュー上でゲームを動かせます。もう一度押すと元に戻ります。

f:id:chirotec:20180321150648p:plain

(wasdで移動、スペースで弾発射のようです)

 

サンプルプロジェクトのビルド

ゲームは作って終わりではないです。公開するために、ビルドしてみましょう。

メニューの「File」>「Build Setting」を開きます。

f:id:chirotec:20180321151418p:plain

Platformのところで「WebGL」を選択し、「Switch Platform」を押します。

これでWebGLに出力する準備が出来ます。(少し時間がかかります)

 

次に「Add Open Scenes」を押し、現在開いているシーンを0番シーン(ゲームの起動時に開くシーンです)とします。

f:id:chirotec:20180321151755p:plain

 

次に「Build」を押し、出力先のフォルダを選択します。空のフォルダを作ってそこを選択しましょう

以上の手順を踏むと、完成品のゲームが出力されます。結構長いので気長に待ちましょう。

f:id:chirotec:20180321154206p:plain

出力された「index.html」をFirefoxで開くと、ゲームの動作が確認出来ます。

Chromeはローカルにあるファイルは読み込んでくれないようです。サーバーにアップすることで確認出来ます。

・Edgeでも動くはずですが、何故かこのチュートリアルは文字以外のゲーム画面が真っ黒になってました……(調査中)

f:id:chirotec:20180321155150p:plain

 

まとめ

今回は、Unityの導入からゲームアプリケーションの公開までの流れをざっくりと紹介しました。

これでUnityを使ってゲームを作り、公開できるようになりましたね。(多分)

次は、簡単なシーンの編集の仕方を紹介します。