原カバンは鞄のお店ではありません。

Unityを使ったゲーム制作のあれこれを綴っていきます。

ゲームアプリ開発振り返り(4)

お知らせ

unityroomに開発中のゲーム(Cutie Circuit)のトレーニングモードを公開しました。
サークルを使った3マッチパズルです。
ステージクリアとかゲームオーバーとかはないので延々とプレイできます。
暇つぶしにどうぞ。

 

https://unityroom.com/games/cutiecircuit-training

 

これまでの話

  1. ゲーム製作者になりたいのにゲームが完成しない
  2. なんとか手軽にパッパッと作成できる方法はないか?
  3. そうだ!出来合いのゲームを改変すればいい!
  4. 早速、アセットストアから購入して改変しようと試みる
  5. 。。。一から作ったほうが早いな ← イマココ

 

忘れていた事

そうなんですよ。忘れてました。自分が作った1,000stepのコードよりも他人の作った100stepのコードの方が読み辛いってことを。
しかも今回はコメントが全て英語だし。英語なんて訳分からないし。学生時代に担当教授から英語で論文書けといわれて死ぬほど辛かったし。しかも、一生懸命書いた文章を教授に見せたらページ丸ごと×印をつけられて返却されるとか、あああああ・・・・

 

そんな感じでトラウマも呼び起こしてしまうレベルで英語の文章はなるだけ読みたくない
→だがしかし、コメントを読まないとコードの解析が進まない
→進まなくていいから英語読みたくない
→じゃぁ、一から作ってしまおう。 Q.E.D.

 

なるほど、だったらしょうがないと自分に言い聞かせて、結局素材だけを使ってソースは一から製作開始。

 

まるで「PGなんてオフショアしとけばええねん!この会社では上流工程しかやらんで!!」と威勢よく軽い気持ちで立ち上げたはいいものの、オフショア先の中国の会社から反日レベルでバグ満載のコードを返され、結局そのメンテナンスで炎上するといった、絵に描いたようなデスマーチプロジェクトですが、なにぶん作業者は私一人なので誰かに文句を言われるわけでもなく、「あれ?今日あの子来てないね?無断欠勤?」からそのまま永久に欠勤するといった、IT業界ではよくある光景も見ることなく作業を進めたわけです。

 

とりあえず出来上がり

それで二週間ほど掛かってできたのが上で紹介したゲームです。
大事なことなのでもう一回貼っておこう

 

https://unityroom.com/games/cutiecircuit-training

 

あとはこれに広告を貼り付けて、適当にタイトルつければ出来上がり!!
。。。と、思ったのですが、

 

。。。う~ん。。。物足りない。。。。

 

あまりにゲームが淡々とし過ぎていて、山場とか見所とかまったくゼロ。
一、二回やれば飽きてしまうんじゃないかと。

 

近年はパズルゲームでも戦闘要素を加えたり、クエスト要素を取り入れたりで、「パズル+何か」で構成されているゲームが多い。
いくら個人製作のゲームとはいえ、やっぱりここは時流に乗って「+何か」を作り込むべきなんじゃないか。
ただ、自分が作りたいものを作るのではなく、時代にコミットするようなものを作るべきじゃないか。
プレイしてくれるユーザのコンセンサスを得られように新しい潮流を追い求めていくスキームの中でカスタマーとデベロッパーとのシナジーは生まれるのであって、インセンティヴを得ことはジャストアイデアでできることじゃない、しっかりとしたガバナンスとプライオリティを持って、って、アホっぽいのでここら辺でやめますが、とりあえずこれをベースとして、もうちょっと作り込もうと思い立ったわけです。

 

すでにベースはできているので、あとちょっと作りこめばいいだけじゃん!

そんな軽い気持ちで

 

ええ、こんな軽い気持ちだから未だに完成してないんですけどね。

 

Curved World を使ってたら謎の現象が発生…

Curved Worldというアセット

Unityのアセットに「Curved World」とアセットがあります。

assetstore.unity.com

 

その名前の通り「平面状の世界を湾曲した状態に変形させて表示することができる」アセットで、奥行きのある表現が簡単にできるので結構人気のアセットです。

(3DモデルにCurved Worldのシェーダを設定するだけ)

www.asset-sale.net

トラブル発生

私も自作ゲームで使用しているのですが、また例によって「PCではきちんと表示されるのに、実機(Android)になるとうまく表示されない」問題が発生。何度目だ。

 

今度はCurved Worldのシェーダを設定した一部のモデルが真っ白に表示される、という問題で、最初はTextureのせいかと思いTextureの圧縮形式を色々変えてみても解消されない。頼みのGoogle先生を使ってみてもCurved World自体の記事が少ないので当該のトラブルに関する記事が見つからず、もうお手上げ状態に。

 

途方に暮れて見慣れない服を着て外に出ていこうかと思ったのですが、ちょっとその前にCurved Worldのシェーダを設定をもう一度見直してみる…

 

f:id:Karvan:20180203004502p:plain

 

で、Androidでもきちんと表示されているモデルの設定は

 

f:id:Karvan:20180203004736p:plain

 

ん?Emission?

もしやと思って、EmissionをONにしてMapにモデルのTextureを指定してみると・・・

 

f:id:Karvan:20180203005022p:plain

 

実機(Android)でも奇麗に表示された!!!\(^o^)/ (何度目だ)

これもEmissionの設定がデフォルトでONになっているのかな?

 

お知らせ

Twitterの方にはすでに投稿しているのですが、開発中の自作ゲーム(Cutie Circuit)のPlay動画を撮ってみました。

一通りPlayできる状態にはなったと思うのですが、メニュー画面やステージセレクト画面等が手付かずなので、まだまだ先は長いですが今月中には完成させたい(希望)と思っています。

 

www.youtube.com

スプライトマスク(SpriteMask)を使ってみよう、って話

スプライトマスク(SpriteMask)機能

unity 2017.1からスプライトマスク(SpriteMask)という機能が追加されています。

 

これまでもMaskという機能がありましたが、こちらはImageに対して切り抜きを行うための機能で、SpriteMaskは文字通りSpriteに対してMask処理を行うためのものです。

 

一体、何が違うんだよ!という方には以下の記事に詳しく書かれているので参照してください。

tsubakit1.hateblo.jp

kan-kikuchi.hatenablog.com

で、せっかく機能が追加されたのだから、なにかしらで使ってみたくなるじゃないですか、「せっかくだから俺はこの赤を扉を選ぶぜ」的な気持ちで。

 

なので、このSpriteMaskを使ったちょっとした演出を考えてみました。

 

 スプライトマスク(SpriteMask)の機能

 前述のとおり、SpriteMaskはSpriteに対してMaskを行う機能ですが、独自の特徴として

 切り抜きの範囲をMaskの内側か、外側か、指定できる

という機能を持っています。

 

これまでのMask機能は画像(Image)をMaskの形に切り抜くのみでしたが、SpriteMaskの場合は、逆にSpriteをMaskの形でくり抜く(穴をあける)こともできるようになっています。

 

今回はこの機能を利用して、Maskが動くことで画像(Sprite)が切り替わる、みたいな演出を作ってみたいと思います。

 

スプライトマスク(SpriteMask)を使った演出

まずは同じ形で色違いの画像(Sprite)を用意します。

 

 f:id:Karvan:20180127001620p:plainf:id:Karvan:20180127001728p:plain

 

次に二つのSpriteが重なるように同じ位置に設置し、一つのSpriteに対してMask Interactionの設定を「Visible OutSide Mask」(Maskの外側を表示)に指定

f:id:Karvan:20180127002821p:plain

 

もう一方のSpriteに対しては「Visiblie Inside Mask」(Maskの内側を表示)を指定します。

f:id:Karvan:20180127002844p:plain

 

そして、メニューのGameObject→2D Object→Sprite Maskを指定してSpriteMaskを作成し、Mask用の画像をSpriteに設定します。

 

f:id:Karvan:20180127003520p:plain

 

このSpriteMaskはMaskを掛けたいSpriteと親子関係にする必要はないので、Spriteを動かさずにSpriteMaskだけを動かすことができます。(逆も可能)

 

なので、Tween系の処理でSpriteMaskを適当に動かしてみると・・・

 

f:id:Karvan:20180127004846g:plain

 

こんな感じになります。

 

ちなみに同じ方法でパワーゲージっぽいものも作ることができます。

 

f:id:Karvan:20180127005556g:plain

 

まぁ、地味ながら使えるかな?

UIの手前に3Dオブジェクトを表示したい。

冬真っ盛りということで、最近は出社途中に缶コーヒーを購入して飲みながら歩いているのですが、つい先日、女子高生の集団からすれ違いざまに

「ってか、コーヒー飲んでるしwwww」

 と声を掛けられました。モテるって辛いですね。おっさんでもコーヒーくらい飲むわ。

 

ここから主題

 

さて、メニュー画面やショップ画面などでUI(uGUI)より上に3Dオブジェクトを表示したいケースってあると思います。

そんな時は大抵、UIのキャンバスのRender Modeを「Screen Space - Camera」に設定して、UIの前に3Dオブジェクトを置くことで実現できるのですが、例えば下の画像の帽子や杖のように、3DモデルをUIに合わせて画面の端に表示したい場合、その方法ではちょっと難しいです。

 

f:id:Karvan:20180120003038g:plain

 

携帯は機種によって画面のサイズが異なります。

UIはAnchorsを設定することで画面サイズが変わっても相対位置が変わらないようにできるのですが、3Dオブジェクトの場合は画面サイズが変わっても表示位置は変わらないので、上の画面の場合、画面サイズの幅を広くするとUIの枠線だけ画面端に表示されて、3Dオブジェクトは枠線からずれて表示されてしまいます。

 

なので、その対応としてRender TextureとRawImageを使った方法を紹介したいと思います。

 

作成手順

1.3Dオブジェクトを表示するためのTextureを作成する

 

まずはProjectsタブのAssetsフォルダ内で右クリック→Create→Render TextureでRenderTextureを生成します。

 

2.3Dオブジェクトを表示するためのカメラを作成する

 

次に3Dオブジェクトを表示する専用のカメラを作成、そしてカメラのTargetTexrureの設定に先ほど作成したRenderTextureを指定します

 

f:id:Karvan:20180120005247p:plain

 

3.カメラの前に表示する3Dオブジェクトを設置する

 

作成した3Dオブジェクト表示用カメラの前に3Dオブジェクトを並べます。

f:id:Karvan:20180120005804p:plain

 

 こんな感じで

 そうするとRenderTextureにカメラの撮影した画像が表示されるようになります。

 

4.RenderTextureを表示するためのRawImageを作成する。

3Dモデルを表示させたい位置にRawImageを作成し、Textureの項目に作成した

RenderTextureを指定します。

f:id:Karvan:20180120010921p:plain

 

今回の場合、RawImageをUIの子オブジェクトとして作成すれば、UIの上に3Dモデルが表示されるようになるのですが、このままでは余計なものまで表示されてしまいます。

 

f:id:Karvan:20180120011621p:plain

 

5.Maskを使って必要な箇所だけ表示する

MaskをUIの子オブジェクトとして作成し、Maskの子オブジェクトとしてRawImageを定義してあげます。

f:id:Karvan:20180120011657p:plain

 

実際に作成して

この方法によりRawImageのAnchorsを指定することで画面サイズが変わっても相対的な位置が変わることはなくなります。

 

また、アイテムの切り替え等のアニメーションもオブジェクトの位置を横にずらすだけならので実装が簡単になりました。

 

f:id:Karvan:20180120013358g:plain

 

今回は長めでしたね。ここまで読んでくれてありがとうございます。

 

 

走るキャラクターに土煙を付けたい

最強寒波とやらで極寒の中、健気にエナジードリンクのサンプルを配布しているお姉さんがいたので、「くそ寒いから要らないけど貰ってあげよう、可哀そうだし、家に持って帰って飲もう」と思って、鼻の下が伸びないように注意しながらお姉さんに近寄っていったのですが、そのお姉さんが「ありがとうございます。」とか言いながら、プシュッと蓋を開けて渡したわけです。

ここで飲めと?

とりあえず、雪が舞う中 でエナジードリンク飲んでも体は暖かくならないことは分かりました。

 

さて、移動するキャラクターが土煙を巻き上げて走っているように見せたい場合、キャラクターの足元に煙のパーティクルを出す方法があるみたいです。

 

tsubakit1.hateblo.jp

車やバイクとか高速で移動する物体だとこの表現で十分なのですが、一般的な人型のキャラクターにこれを付けるとちょっとオーバーかな?と思えたり。みんなアラレちゃんになるし。

 

できれば一定間隔で土煙が巻き上がる感じの表現にしたい。

f:id:Karvan:20180112222527g:plain 

こんな感じで。

 

なので、その方法を模索してみまた。

 

まず、土煙のパーティクル本体に以下のスクリプトを設定して、パーティクル再生後に一定期間で消滅するようにします。

 

public class Dust_AutoDestructShuriken : MonoBehaviour {
    // 生存時間
    float lifeTime;

    public void OnCheckOn()
    {
        // パーティクルの開始
        ParticleSystem myParticleSys = this.GetComponent<ParticleSystem>();
        myParticleSys.Play();

        // アクティブ監視処理実行
        StartCoroutine("CheckIfAlive");
    }

    IEnumerator CheckIfAlive()
    {
        while (true)
        {
            yield return new WaitForSeconds(lifeTime);
            if (!GetComponent<ParticleSystem>().IsAlive(true))
            {
                GameObject.Destroy(this.gameObject);
            }
        }
    }
}

 

次に、上記スクリプトを設定したパーティクルオブジェクトが一定間隔で生成されるように、走るキャラクターオブジェクト側に以下のスクリプトを設定。

Update関数で一定時間間隔でパーティクルオブジェクトが生成されます。 

 

    // タイムアウト時間
    float timeOut;

  // 土煙のパーティクルオブジェクト
  BackDustPrefab void Update () { timeElapsed -= Time.deltaTime; // タイムアウト発生時 if (timeElapsed <= 0) { // 走行時の砂埃エフェクト生成 RunEffectCreate(); timeElapsed = timeOut; } } /// <summary> /// 走行時の砂埃エフェクト生成 /// </summary> public void RunEffectCreate() { // エフェクトオブジェクトの生成 GameObject crObj = Instantiate(BackDustPrefab, Vector3.zero, Quaternion.identity, this.transform.parent); crObj.transform.localPosition = this.transform.localPosition; // エフェクトの実行 Dust_AutoDestructShuriken crPar = crObj.GetComponent<Dust_AutoDestructShuriken>(); crPar.OnCheckOn(); }

 

ここで気を付けるのは生成するパーティクルオブジェクトがキャラクターオブジェクトの子オブジェクトにはならないようにすること。

子オブジェクトにするとキャラクターにくっ付いて一緒に移動してしまいます。

 

 これを実際のゲーム画面(開発中)で動かしてみるとこんな感じ。

 

f:id:Karvan:20180112222623g:plain 

 

ハイ、そこ!オナラしてる、とか言わない!

iTweenのValueToを使ったアニメ動作

前回の記事の訂正

前回、Crunch圧縮の定義を外す手順で、
 「Use Crunch Compression」のチェックボックスをチェック⇒チェックを外す
と書きましたが、そのあとに
 Unityの再起動をする
という手順が必要でした。再起動しないと設定が有効にならないみたいです。

ここから本題

ゲーム中の演出で、下のような

f:id:Karvan:20180106002945g:plain

アイコンが徐々に現れるアニメを作ろうとした場合、

アイコンのImage(上の場合は矢印のImage)のImageTypeをFilledにしてFillAmountの値をUpdate関数内で徐々に大きくしていくのが一般的かと思いますが、それをiTweenのValueToを使って実現しようというお話。

まずはValueToを実行する関数

    GameObject TargetTweenObj;        // アニメ動作させたいゲームオブジェクト

    /// <summary>
    /// 矢印アニメ動作開始
    /// </summary>
    private void TweenAnimationStart()
    {
        // ValueToの開始
        Hashtable hash = new Hashtable(){
            {"from", 0.0f},
            {"to", 1.0f},
            {"time", 1.0f},
            {"delay", 0.0f},
            {"easeType",iTween.EaseType.linear},
            {"loopType",iTween.LoopType.loop},
            {"onupdate", "OnUpdateArrow"},
            {"onupdatetarget", gameObject},
        };
        iTween.ValueTo(gameObject, hash);
    }


ValueToを実行すると"onupdate"で指定した関数に"from"から"To"まで徐々に変化させた値が引数として渡されてくるので、それを使ってfillAmountの値を変更します。

    /// <summary>
    /// iTweenによるValueToのコールバック
    /// </summary>
    /// <param name="nextValue"></param>
    void OnUpdateArrow(float nextValue)
    {
        // 矢印オブジェクトのImage取得
        Image TargetImage = TargetTweenObj.GetComponent<Image>();

        // 矢印オブジェクトのfillAmount更新 
        TargetImage.fillAmount = nextValue;
    }


今回はValueToの"loopType"にloopを指定しているので、ループを止める場合には以下の関数をコールします。

    /// <summary>
    /// 矢印アニメ動作停止
    /// </summary>
    private void TweenAnimationStop()
    {
        iTween.Stop(this.gameObject);

        Image TargetImage = TargetTweenObj.GetComponent<Image>();
        TargetImage.fillAmount = 1.0f;
    }


で、これを実際のゲーム画面(開発中)で使用してみるとこんな感じ
iTweenを使用するとアニメの動作時間やループの設定等が簡単に行えるので以外と有用な方法かと思います。

f:id:Karvan:20180106005413g:plain

Unity2017.3にアップデートしたら困った事態になった話

12月になってUnity2017.3.0f3がリリースされたのでアップデートはしたものの、暫く実機(Android端末)テストはしてませんでした。

 

で。久しぶりに、ってかアップデートしてからは初めてプロジェクトをビルドして実機で動かしてみると困った問題が発生

 

スプライトが表示されない

 

PCではきちんと表示されているのにAndroidで動かしてみるとスプライトが表示されない、ビルド時にエラーは出てないし、実機でエラーログを出力するようにしても特にエラーが発生しているわけではないみたい。う~ん、困った・・・

 

色々調べていると表示されないスプライトは決まっていることが判明、InspectorのOverride for Androidの設定で圧縮形式にETC2を指定していたスプライトが駄目っぽい。

 

ならばと他の形式に変えてApplyボタンを押してみると今度はconsole上に

Assertion failed: TLS Allocator ALLOC_TEMP_THREAD...

と表示されてエラーとなった。

 

ん~。。。どうにもならん。。。

 

仕方ないのでグーグル翻訳先生の手を借りながらUnityのフォーラムを漁ってみるとそれらしき答えが、どうやらUnity2017.3.0f3から「Crunch圧縮」がデフォルトで有効になっているのでそれを外す必要があるみたい。

 

Crunch圧縮」・・・どこ?

 

QuaritySettingsにはないし、当該のスプライトのInspectorには

f:id:Karvan:20171230230106p:plain

 

ないし・・・(。´・ω・)ん?・・・・あった!!

 

f:id:Karvan:20171230225534p:plain

 

Defaultタブにありました。

表示上ではチェックされてないけどUnity内部ではデフォルトで有効になっているらしい。なので、このチェックを有効⇒無効とした後にApplyボタンを押してスプライトを変更する。

これで再度プロジェクトをビルドして実機で動かしてみると・・・

 

表示されたーーーー!!!

 

( ´Д`)=3 フゥ・・・

 

アップデートされたからといってホイホイ手を出すと痛い目を見る、という話でした。

◇プライバシーポリシー

●個人情報の利用目的

当ブログでは、メールでのお問い合わせ、メールマガジンへの登録などの際に、名前(ハンドルネーム)、メールアドレス等の個人情報をご登録いただく場合がございます。

これらの個人情報は質問に対する回答や必要な情報を電子メールなどをでご連絡する場合に利用させていただくものであり、個人情報をご提供いただく際の目的以外では利用いたしません。

●個人情報の第三者への開示

当サイトでは、個人情報は適切に管理し、以下に該当する場合を除いて第三者に開示することはありません。

・本人のご了解がある場合
・法令等への協力のため、開示が必要となる場合

個人情報の開示、訂正、追加、削除、利用停止
ご本人からの個人データの開示、訂正、追加、削除、利用停止のご希望の場合には、ご本人であることを確認させていただいた上、速やかに対応させていただきます。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Googleアナリティクス」を利用しています。

このGoogleアナリティクスはトラフィックデータの収集のためにCookieを使用しています。このトラフィックデータは匿名で収集されており、個人を特定するものではありません。
この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。

●免責事項

当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

当サイトのコンテンツ・情報につきまして、可能な限り正確な情報を掲載するよう努めておりますが、誤情報が入り込んだり、情報が古くなっていることもございます。

当サイトに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

●プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直しその改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。