2018年01月25日

(メモ)Unityで直列に処理を書いてみた

やりたかったことは一番下のExecuteね。これ、クリック待ちも文章表示もメインスレッドにやらせて、クリック待ちの時はちゃんと関数の途中で待っている。コルーチンでは書きにくかったことを実現、昔のAPIなのでexperimentalな機能使わなくても出来る。
このクラスを継承して、Executeだけをオーバーライドして使うようなクラス作って、Executeからはまるでコンソールアプリケーションみたいな感覚でコードが書ける。アドベンチャーゲームのシナリオなんかには便利なのではないだろうか。
さらには、トランスパイラの類を書けば他の直列に記述するスクリプトからこの関数を作るのもそう難しいことではないだろう。昔のBASICみたいな環境を作ったり、NScripterやら吉里吉里っぽいスクリプトやらを動かせるようになるかも知れない。
C#の(C++でもCでもJavaでも、多分どんな言語でも可能だが)関数の実行を途中で中断して保存・復帰する方法についてはアイデアがある(ソースの自動生成が前提だけど)。また次の記事で。組み合わせれば高速で単純で柔軟なノベルゲームエンジン作れると思う。
なお、残念なことにこのコードはWebGLでは機能しない。UnityのWebGLではスレッドを作れないようなので。PCとAndroidで動くのは確認済み。他は持ってないので試せない……PS系とかSwitchとか気になるよね。
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;
using System.Threading;

public class ThreadTest : MonoBehaviour
{
    delegate void InvokeDelegate();
    static Object lockObject=new Object();
    List invokeList=new List();
    private bool _b;
    public bool canInvoke
    {
        get
        {
            lock (lockObject)
            {
                return _b;
            }
        }
        set
        {
            lock (lockObject)
            {
                _b = value;
            }
        }
    }
    Thread thread;


    //描画用
    public Text text;

    // Use this for initialization
    void Start()
    {
        canInvoke = true;
        thread = new Thread(Execute);
        thread.Start();
    }

    // Update is called once per frame
    void Update()
    {
        if (canInvoke)
        {
            lock (lockObject)
            {
                foreach (var data in invokeList)
                {
                    data();
                }
                invokeList.Clear();
            }
        }
    }

    void InvokeWait()
    {
        while (true)
        {
            lock(lockObject)
            {
                if (!canInvoke)
                {
                    Debug.Log("canInvoke=falseの時にInvokeWaitを実行してはいけません。");
                }
                if (invokeList.Count == 0) break;
            }
            Thread.Sleep(8);
        }
    }

    void ClickWait()
    {
        bool isMouseDown = false;
        while (!isMouseDown)
        {
            InvokeMainThread(()=>
            {
                if (Input.GetMouseButtonDown(0))
                {
                    isMouseDown = true;
                }
            });
            InvokeWait();
        }
    }

    void InvokeMainThread(InvokeDelegate f)
    {
        lock (lockObject)
        {
            invokeList.Add(f);
        }
    }

    void PutText(string s)
    {
        InvokeMainThread(()=>
        {
            text.text = s;
        });
    }

    void Execute()
    {
        PutText("てきすと1");
        ClickWait();
        PutText("てきすと2");
        ClickWait();
        PutText("直列で実行できてる?");

        //ここでは使ってないけど
        /*
        canInvoke=false;
        Load1();
        Load2();
        Setting1();
        canInvoke=true;
        こう書けば、canInvoke=falseのあいだの命令実行中にInvokeしたものが実行されないことが保証され、正確に同じフレームで実行できる。
        */
    }

}

(追記:バグを修正しました。)
posted by NTak_Indies at 20:50| Comment(0) | TrackBack(0) | 日記

2018年01月01日

コミケ93上京記録

えー、「くのいちボーグしのぶちゃん」、結果から言うとまあ爆死でしたw 最初からある程度の失敗は予想していたのだけど、うーん、せめてコピー代と欲を言えば移動宿泊費用くらいは稼ぎ出したかったねえ。近々DLサイトコムに登録されると思います。その時にはよろしくお願いします。 お誕生日席で両隣がかなり立派な感じだったのもまあ心理的にはプレッシャーきつかった。次に受かるとしたら島中からこつこつやりたいです。 まあそれはともかく、反省点は色々ある。パッケージングを簡略化しすぎて売り込み材料が小さいタブレットのムービーとポスターしかなかった。あまりお金は掛けたくないが、かといってある程度は掛けないとまずいね。あと、内容の分かるような資料はいろいろ用意しておくべき。ムービーももうちょっと短く凝縮したダイジェストが必要だったなあ。 とはいえ楽しかった。いろいろ見物して次にやりたいことのヒントも得られたしね。ダウンロードカードが面白そうだったのと、スマホや紙媒体も巻き込んでメディアミックスしていくのが今後は面白そうだ。 あと、コミケ二日目は行かずに友達と遊んでいたのだが、そこで行ったVRが面白かった! セガのエイリアン的な奴だけど、あれは自分でも作ってみたいなあ。マイクロソフトのVR規格のやつが出てるけど、あの辺のが欲しいなあ……春までには買うかもしれない。 で、今後の方針のことなんだけど、俺の絵面が基本的にSDキャラを目指してるので、エロをやってもしょうがないかなって考えがあるんだよね。ただ、同人のエロの熱気は凄い物があるからねえ……その辺は悩む。いずれにしても、出来るだけ自分のコンテンツを作りたいというのが目標としてあります。何年か先にはポートフォリオに使えるようなのを作りたい。今後とも毎回コミケには応募してそこに出展するのを目標にして刻んでいきます。当選しなくてもDL販売には出すし。 次に開発したいもののイメージも、積み上げたい技術的な目標もあるので、こつこつやって、こまめに出していきますよ! 次は時間も掛けて技術的にも土台をもっとしっかりさせて品質向上ボリュームアップさせてリベンジする!
posted by NTak_Indies at 19:10| Comment(0) | TrackBack(0) | 日記

2017年12月22日

2017年冬コミ新作「くのいちボーグしのぶちゃん〜果たし合い宇宙〜」について技術的メモ

2017年冬コミにサークル名「nscripter.com」で出ます! 12/29(一日目金曜日)東コ46aです、よろしく!
https://webcatalog-free.circle.ms/Circle/13613508
いやあ、完成しましたよ。当選したのは嬉しかったけどお誕生日席だったのがプレッシャーでね、恐れ多い。目立つことはあんまり想定してなかったのね、さすがにこれはちゃんとしたもん出さないとまずいなと。買った人に損をしたと思わせないものを作ろうと頑張りました。500円なら、ゲーセンで数回遊ぶくらいで、あと同人お祭り感覚で出して貰えれば、こういうの好きな人は損はしないと思う。作品の内容紹介に関しては上の動画を観ていただくとして、この記事は技術紹介と今後の方針についてです。

実際の所、当サークルの活動目的は技術研究のモチベ維持(他にも色々イベントに出たいと思ってるし、ネット同人頒布サイトでも出していく予定)とインディーズ活動のノウハウ学習です。5年後10年後に何か見せられる作品もないんじゃ就活もままらないのでね。なので頒布数自体は気にしません。最初は誰でもマイリス2くらいなんだぞ。長期計画で自分の好きなゲームを自由に作れる環境作りを目指します。そんな手作り感覚でやるお話。

まず、開発環境について。
プログラム
使用エンジンは「Unityhttps://unity3d.com/jpです。プログラム系のアセットでは後述のVoxel Importer(URLは後述)以外には「DOTweenhttps://www.assetstore.unity3d.com/jp/#!/content/27676を使っていて、アニメーションや遅延処理の類で大いに活躍してもらいました。コードが書ける人は調べてみるといいかと。最近はUniRXも流行りなのですが、あれちょっと難しそうなので僕はまずこちらから手を出してみました。

モデリング、スキニング
今回、キャラクターは「ボクセル」で作ってるわけですが、このモデリングはフリーソフト「MagicaVoxelhttps://ephtracy.github.io/でやっています。たとえばこんなの作りました。

https://sketchfab.com/models/85ef58c41a514a928544b4926b825668
https://sketchfab.com/models/e352d1ad6fc54dccbd7851420624ac60
他にもいくつか作ってるのでよろしければ見てください。
https://sketchfab.com/NTak_indies

MagicaVoxelの使い方はYouTubeやニコニコで検索すると色々出てくるけど、使いやすくておすすめです。絵心のない僕でもこのくらいは作れます。これをゲームエンジン「Unity」で扱えるようにする(リーズナブルなお値段の)アセットが「Voxel Importerhttps://www.assetstore.unity3d.com/jp/#!/content/62914で、これを使ってボーンを入れて動かしています。これもYouTubeに公式の解説動画があって分かりやすいよ。今回のモデリングは本当にこの二つで完結してしまいました。弾とかポリゴン数をあまり割きたくないものはドット絵で2次元スプライトにしたのですが、こちらを作るのにはSteamで購入できるドット絵エディタ「Asepritehttp://store.steampowered.com/app/431730/Aseprite/?l=japaneseを使いました。その辺工夫はしたので、だいぶ軽め、IntelHDやセレロンの機械でも数年前程度のスペックなら遊べると思います。

エフェクト
Unityに標準で付いてくるShurikenというパーティクルシステムで作っています。ぐぐればだいたいのもんは作例が出てきて用が足せてしまうのがすばらしい。そんなに重くもないみたい。

BGM、SE
BGMは「魔王魂https://maoudamashii.jokersounds.com/さんのフリー素材を使わせていただいてます。SEは「DSP Animehttp://tsugi-studio.com/web/jp/products-dspanime.htmlと「Bfxrhttps://www.bfxr.net/のスタンドアローン版で作ってます。前者は普通のADVでも状況に合わせてハマるものは多そう。後者は、8bitゲーム的なピコピコ音が欲しい的にいい感じ。リアル系の音だと逆に合わない状況のギャップが際立つこともあるので。

あとは、今回気付いたことメモと次にやりたいことについて。
今回は偶然がいくつも重なり合って作業時間がかなりきついことになっていたのですが、間に合った理由はいくつかありました。
第一に、ボクセルは作業が速い。調子がよければ僕でも2、30分で一体作れてしまいます(↑の絡新婦モデルはさすがに力作でもうちょっと時間かけてますが)。テンプレートを改造していく形になるので蓄積が利くのもいいですね。スキニングもVoxel Importerの機能はかなり使いやすく速いのですが、もうちょっと簡易のものを自前で作れそうなら外部から付け足そうかなと思っています。これは完成して要望があれば無料公開すると思う。僕の使い方の場合、ボクセル単位で所属ボーンでゼロイチで塗り分けて、あとは隣接面だけ50%で割ってくれれば十分なんですよね。そういうのを作るつもり。これならスキニングすら10分もあれば終わる作業になりそう。

またボクセルは動けば意外と見栄えがいい。アニメーションとライティング次第でどんな場でも使えそう。今回はアニメは凝ってないのですが、次は体制整えてしっかりアニメさせようと思います。絡新婦モデルは、顔はSDモデルと同じで頭身が上がってるものなのですが、これならホラーゲームでも使えるじゃないかなと。

次にゲームデザイン面の話ですが、ランダムなマップ生成は作業が速い。今回、マップも敵配置もランダムです。マップについては決まったブロック(このゲームの場合「島」)を乱数で選んで並べているわけですが、レベルエディットに時間を割かず、ゲームバランスの調整に傾注できるので、短期間開発にはもってこいですねこれ。Unity入門本にローグライクが多い理由が分かりました。今後も乱数要素はうまく取り入れていくつもり。

コードの反省点としては、シングルトンばかりになりコンポーネントの参照の持ち合いが複雑化しがちなので、最初に統一した戦略を立てるべきだなと。多分全体のマネージャクラスを作る。また、シーンをまたいで使うプレファブがリンク切れしたらかなりめんどくさいことになるのでプレファブの安全な使い方も考えておきたい。また、カットシーンの動画収録や宣伝画像用のイメージを作成できる環境を整えておきたい。Unityにもそういう機能追加が出来てきてるみたいなんでこちらは簡単なコードなら書いて用意しておきたい。

今後の方針ですが、ボクセルによる開発を続ける予定です。次はスキニングをツール整備によってもっと簡便にやれるようにします。
また、イラストレーターで作った物をSVGで吐いてBlenderで押し出し立体化することによる2.5D表現もやろうかなと思っています。斜めの線や曲線が多いものについてはボクセルよりこっちが速そう。また、ボクセルキャラの表情にこの方法で作ったものを使おうと思っています。その辺のものはコンテンツパイプラインが出来上がってきたら都度紹介していくつもり。
次に作りたいと思っているジャンルは、作ってる間に思いついた「ファンタジーゾーンっぽい横シュー」(それこそイラレ押し出し式の2.5D表現が映えそう)か、今回の絡新婦みたいなキャラやアニメを生かして「SIREN的なJホラー系サバイバルホラーゲーム」か、「逆転裁判的なミステリアドベンチャーゲーム」、あるいは「ロックマン系ジャンプアクションゲーム」ですね。いずれにしても、ゲームとは別にボイロキャラ等を使って寸劇みたいな動画コンテンツを作ってこつこつ連載していきたいという夢は昔からあるので、近況報告その他の動画コンテンツとしてそちらを先に公開する形にはなると思います。

総じて、やりゃあ出来るというのが分かったのは大きい。収益目的ではないので(技術的蓄積とアピールは考えているので実利がないわけではないですが)、気長にやってくつもりですが、これはやってて楽しい、あと20年はやれる趣味を見つけた感じです。仕事の合間にやって、仕事にも生かす技術を身につけつつ、自由な発想で作っていくぞ。 1000.jpg
posted by NTak_Indies at 05:53| Comment(0) | TrackBack(0) | 日記