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

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

C# JobSystemを使ってみよう2

賢人の言葉

宮沢賢治氏の代表作「雨ニモマケズ」では「雨ニモマケズ風ニモマケズ・・」の次に「雪ニモ夏ノ暑サニモマケヌ・・・」という言葉がありますが、ここ最近はさすがの賢治氏もその節を曲げそうな暑さが続いていおり、私の場合は負けっぱなしでエアコン全開の日々が続いています。もう部屋から出られんし。

 

夏休みシーズンに入ったこともあり私の周りでも、フェスだ!、花火だ!、お祭りだ!、みたいなワードが飛び交っていますが、私としてはこの酷暑の中、一歩も外に出る気はありません。そもそも誘われない、という話は悲しくなるので置いといて、この夏は部屋から出ることなくゲーム制作に専念したいと思っています、うん、だから泣いてません。

 

C# JobSystemの続き

前回の記事でUnityのJobSystemについて取り上げましたが、今回はその続きです。他にネタがなかったとか、そういうわけでは決してありません、うん、たぶん、きっとそう。

 

前回では複数のモデルに公転と自転の運動をさせていましたが、今回は公転運動に収縮の動きを加えてみようと思います。つまり公転半径が周期的に変わるってやつ。

f:id:Karvan:20180724225803p:plain

 

公転運動に収縮運動を加える

公転運動のロジックに収縮分の計算を加えれば出来そうな気もしますが、今回は公転運動を計算した後、収縮運動を計算してオブジェクトのTransformに反映しようと思います。これにより前回作成した公転運動のロジック部分には一切手を入れなくて済みます。

 

f:id:Karvan:20180724225856p:plain

 

収縮運動の移動

収縮運動の移動量にはAnimationCurveを使用しました。Main側でカーブの位置を取得して、変数「SpreadPower」に渡して収縮運動計算で使用しています。

Main側

    // Update is called once per frame
    void Update () {
        // 公転用JOB領域設定
        RevolutionMotionUpdate revolutionJob = new RevolutionMotionUpdate()
        {
            Accessor = this._revolutionStructs,
            DeltaTime = Time.deltaTime,
        };

        // 自転用JOB領域設定
        RotationMotionUpdate rotationJob = new RotationMotionUpdate()
        {
            Accessor = this._rotationStructs,
            DeltaTime = Time.deltaTime,
        };

        //カーブ位置取得
        if (_curveRate == 1f)
        {
            _curveRate = 0;
        }
        else
        {
            _curveRate = Mathf.Clamp(_curveRate + _spreadPower, 0f, 1f);
        }

        // 収縮運動用JOB領域設定
        ContractionMotionUpdate contractionJob = new ContractionMotionUpdate()
        {
            Accessor = this._spreadStructs,
            SpreadPower = contPower * _jumpCurve.Evaluate(_curveRate)
        };

        this._jobRevolutionHandle.Complete();
        this._jobRotatioHandle.Complete();
        this._jobSpreadHandle.Complete();

        this._jobRotatioHandle = rotationJob.Schedule(this._planetTransformAccessArray);
        this._jobRevolutionHandle = revolutionJob.Schedule(this._planetTransformAccessArray);
        this._jobSpreadHandle = contractionJob.Schedule(this._planetTransformAccessArray, _jobRevolutionHandle);
        JobHandle.ScheduleBatchedJobs();
    }

 

収縮運動側

    /// <summary>
    /// 収縮運動のJOB
    /// </summary>
    struct ContractionMotionUpdate : IJobParallelForTransform
    {
        public NativeArray<RotCalStruct> Accessor;
        public float SpreadPower;

        // JobSystem側で実行する処理
        public void Execute(int index, TransformAccess transform)
        {
            RotCalStruct accessor = this.Accessor[index];
            transform.localPosition = Spread(accessor, transform);
            this.Accessor[index] = accessor;
        }

        // 収縮運動
        Vector3 Spread(RotCalStruct data, TransformAccess transform)
        {
            Vector3 nowPos = transform.localPosition;

            Vector3 radiusVec = new Vector3(nowPos.x - data.RevOri_X,
                                            nowPos.y - data.RevOri_Y,
                                            nowPos.z - data.RevOri_Z);

            Vector3 modVec = (SpreadPower + 1.0f) * data.RevRadius * radiusVec.normalized;

            Vector3 retPos = new Vector3(data.RevOri_X + modVec.x,
                                         data.RevOri_Y + modVec.y,
                                         data.RevOri_Z + modVec.z);

            return retPos;
        }
    }

 

公転運動後に収縮運動を行う

並列処理を行うためのJobSystemですが、今回の場合は公転運動⇒収縮運動の順に処理を行わなくてはいけません。これを実現させるためにJobSystemでは各Jobの依存関係を設定することができます。

 

上のソースのMain側で

       this._jobRevolutionHandle = revolutionJob.Schedule(this._planetTransformAccessArray);
        this._jobSpreadHandle = contractionJob.Schedule(this._planetTransformAccessArray, _jobRevolutionHandle);
        JobHandle.ScheduleBatchedJobs();

と記載している箇所があります。

収縮運動側のScheduleの第二引数に公転運動側のジョブハンドルを指定することで、公転運動の処理が完了したら収縮運動の処理が即時に実行させるようになります。

公転運動にも収縮運動にも同じtransformArrayを渡しているので、収縮運動の処理には公転運動分の移動が終ったtransformに収縮運動分の移動を反映させることができます。

 

実際の動作

これらの処理を使って実際に動作させた結果が以下の動画です。

どーん

f:id:Karvan:20180724231410g:plain

 

スクエア上に並んだ球体が自転+公転しながら収縮運動もしていることが分かります。

 

JobSystemは難しくない

前回も述べましたがJobSystemの実装自体は難しくありません。ただ、JobSystemでどのように実装するか、という設計の見極めは十分な考慮が必要かもしれません。今回の場合だと、自転と公転はそれぞれ並列処理でよいけど、収縮は公転⇒収縮の順じゃないと駄目、みたいな。まぁ、色々試してみるのが一番ですね。

 

 

◇プライバシーポリシー

●個人情報の利用目的

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

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

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

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

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

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

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

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

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

●免責事項

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

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

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

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

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

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