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

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

【進捗報告】底意地が悪いSTG

治らない、治る気配がない

先々週ぐらいから続いていた腰の痛みは徐々に解消されてきたのですが、鼻風邪の方はなぜか継続中で、くしゃみが全然止まらない。

熱があったりだとか寒気がしたりだとかは全くないのですが、花粉症のような症状がずっと続いています。秋でもブタクサとかヨモギの花粉症ってあると聞いたので、もしかすると其れかもしれない。やだなぁ・・・

 

障害物

さて、毎度ブログを更新するたびに進捗が進まない言い訳を書いている気がする次回先の2.5DSTGなんですが、これでも匍匐前進ぐらいの勢いで少しづつ前へ進んでいます。

 

前回の進捗報告では自機が弾を撃った!とか弾道のパータンが揃った!とか、STGとしての基礎中の基礎が実装された事を報告していましたが、果たしてそれからどれぐらい進んだのか・・・ご覧ください。

 

f:id:Karvan:20191027102358g:plain

 

障害物のようなオブジェクトが出てくるようになりました!!

しかも壊れる!!パチパチ。

 

まぁ、巷のSTGでも自機の進攻を阻むような障害物が出てくることはお馴染みなんですが、これまでは平らな壁が延々と続いていく世界だったので、障害物を置くことで2.5Dらしく立体感が出てきた気がします。どうもありがとう。自画自賛。

 

ちなみに壊れた障害物は当然ながらそれに当たったらダメージになります。

なので敵機の弾丸をかわしている最中にウッカリ壊してしまったら更に難しいことになります。こんな感じで

 

f:id:Karvan:20191027102527g:plain

 

ようは障害物を壊さないように注意して進むSTGってことです、底意地が悪いです。

はてさて、いつになったらボス戦の開発に手を出せるのか・・・

 

【Unity】範囲内の時間を制御・・・してるっぽく見せる(Rigidbody編)

Unity1Week

先週はunityroomの方でUnity1Weekが開催されていました。

unityroom.com

当初は私も微力ながら参加する予定だったのですが、前日からくしゃみが止まらくなる症状が出始め、かつ何故か腰が痛くなるという風邪なのか何なのかよく分からない体調不良に悩まされていた為、断腸の思いで断念させていただきました。


まぁ、unityroomに投稿される作品はUnity1Weekに限らず年々とレベルが高くなっていて、Tweeterなどで上げられている進捗報告の動画を観るたびにビックリしたり落ち込んだりすることも多く、仮に参加出来ていたとしても途中で挫折したかも、、、とか思ったり。参加された皆さん、お疲れ様でした。

 

時間を制御・・・してるっぽく見せる

さて、以前の記事で一定範囲内にあるオブジェクトに対して、あたかも時間を制御しているかのようにゆっくり動作させる、みたいなことをしたのですが、その時はDoTweenとAnimationのTimescale、Speedを変更する手法で実現していました。

www.karvan1230.com

しかし、オブジェクトを動かす手段はDoTweenやAnimation以外でも様々な手法があります。


特に最近では『Human Fall Flat』などが人気になったように物理演算によるオブジェクトの挙動を楽しむゲームも増えてきているので、オブジェクトの位置を直接制御するのではなく、オブジェクトに力を加えることで動かしていく方法も注目されてきています。


Unityで物理演算とえばRigidbody。
なので今回はRigidbodyでも同じようなことができないか探っていきたいと思います。

 

Rigidbodyを使って動かす

Rigidbodyを使ってオブジェクトを動かす場合はAddForceでオブジェクトに力を加えて動かします。AddForceでは力の大きさと、継続的な力、瞬間的な力、みたいな力の種類を選んで指定します。


今回は下図のようなモデルを用意しました。

f:id:Karvan:20191022165035p:plain

 

赤い弾にAddForceで横方向に瞬間的な力を加えます。
そして横に移動した赤い弾が球体内にいる間だけゆっくりと移動する処理を作ります。

 

弾が球体内にいるかどうかの判定は前回と同様にTriggerEnterとTriggerExitで判定するのですが、今回の場合はDoTweenの時のように赤い弾だけのTimescaleは変更できません。

また、継続的に力を加えるわけではないのでAddForceのパラメータを変更するわけにもいきません。では、どうするか・・・

赤い弾の速度を直接変更します。

 Rigidbodyではオブジェクトのmass(質量)とvelocity(速度)、angularVelocity(回転角速度)を参照&更新できるので、TriggerEnterでvelocity(速度)を遅くして、TriggerExitで元に戻してあげれば良いはずです。なんて単純な手法。

 

Rigidbody myBody;

void Start()
{
    // Rigidbodyの取得
    myBody = this.GetComponent<Rigidbody>();
}

private void OnTriggerEnter(Collider other)
{
    // 速度を遅くする
    myBody.velocity *= 0.2f;
}

private void OnTriggerExit(Collider other)
{
    // 速度を元に戻す
    myBody.velocity /= 0.2f;
}

 

オブジェクトが回転している場合はangularVelocityに対しても同じような処理を行います。また、OnTriggerExitで速度を元に戻したのに極端に速度が落ちている場合は、OnTriggerEnterでmass(質量)を軽く(=小さく)してOnTriggerExitで元に戻してあげればよい感じなります。

 では、実際の動作を見てください

f:id:Karvan:20191022165447g:plain

 

折角だから別の方法も考える

先程は速度を直接変更しましたが、折角Rigidbodyを使っているので別の手法も考えてみました。

次はこんなモデルを使います。

f:id:Karvan:20191022165733p:plain

 

上空にいるウサギはRigidbodyによって自由落下します。

このウサギに対して球体内にいる間だけ逆方向(=上方向)にAddForceで瞬間的な力を繰り返し加えます。要は抵抗を受けてゆっくり落ちるようにします。

Rigidbody myBody;

void Start()
{
    // Rigidbodyの取得
    myBody = this.GetComponent<Rigidbody>();
}

private void OnTriggerStay(Collider other)
{
    // 上方向に力を加える
    myBody.AddForce(0.7f * Vector3.up, ForceMode.Impulse);
}

 

OnTriggerStayはCollider内にいる間、絶えず呼ばれるのでその中でAddForceを行います。ただ、これだけだと球体から出た時に速度が元に戻らないので、先ほどと同じようにOnTriggerExitでRigidbodyの速度を早くします。

 

private void OnTriggerExit(Collider other)
{
    myBody.velocity /= 0.15f;
}

 

で、実際の動作はこんな感じになります。

f:id:Karvan:20191022170115g:plain

想定通り、落下するウサギにブレーキが掛ったような動作になりました。

これはこれで面白い動きかな、とは思うのですが、速度を直接変更する手法と比べた場合、逆方向の力の大きさとか、速度を戻す係数等はオブジェクトの質量や落下する距離によるので、本当にゲーム内で使う場合は繰り返し実行して調整する必要があります。ちょっと面倒ですね。


 

【Unity】DotweenのToを使ったオブジェクトの伸縮

衣替え

曇り続きならがらも蒸し暑かった夏も終わって朝夕は肌寒いほどとなってきました。衣替えの季節と言えますが、タンスにしまっていた秋冬用のズボンを取り出したら何故か縮んでいてウエストが閉まらない、という経験をした皆さんこんにちは。

私はカッターシャツのボタンが閉まりませんでした。縮んですねカッターシャツって。

 

DotweenのToってやつ

さて、DotweenにはDOMoveやDOJump、SequenceなどObjectのtransformに関しては様々なTweenメソッドが用意されていますが、任意のプロパティとかクラス変数などをTweenしようと思うとToメソッドを使うことになります。

 

iTweenのValueToと同じような機能なんですが、Hashtableを使うiTweenとは異なりDotweenではラムダ式での指定となるので慣れないとちょっと分かりづらいです。
「Number」というクラス変数を1秒で0~100に変化させたい場合の指定は以下のようになります。

 

float Number = 0.0f;
float TargeValue = 100.0f;
float TweenTime = 1.0f;

DOTween.To 
(
	() => Number, 		//何に
	(x) => Number = x,	//何を
	TargeValue,		//どこまで(最終的な値)
	TweenTime		//どれくらいの時間
);

 

変化させたい変数はVector3とかでも可能なのでかなり便利なメソッドなのですが、意外に必要となる場面は少なくてネットを漁ってもImageやMaterialのColorやAlphaを変える使用例ぐらいしか見当たりません。
なので、ちょっと強引ですがtransformにDotweenのToを使った使用例を考えてみました。

 

オブジェクトの伸縮

今回は下の動画のようなJumpするキャラクターに変化を加えます。

f:id:Karvan:20191015211627g:plain

 

キャラクターのJumpはDOJumpを使って動かしているのですが、それに合わせてキャラクターのlocalScaleを変化させます。
ジャンプ中は縦(Y)方向に伸びて横(XZ)方向は縮むように、逆に着地後は横に伸びて縦は縮むようにします。

 

// 縦(Y)方向に伸びて横(XZ)方向は縮む
this.transform.localScale = new Vector3(
    1.0f - 0.40f * Mathf.Sin(amountVal * Mathf.Deg2Rad),
    1.0f + 0.40f * (Mathf.Sin(amountVal * Mathf.Deg2Rad)),
    1.0f - 0.40f * Mathf.Sin(amountVal * Mathf.Deg2Rad));

// 横(XZ)方向に伸びて縦(Y)方向は縮む
this.transform.localScale = new Vector3(
    1.0f + 0.45f * Mathf.Sin(amountVal * Mathf.Deg2Rad),
    1.0f - 0.45f * (Mathf.Sin(amountVal * Mathf.Deg2Rad)),
    1.0f + 0.45f * Mathf.Sin(amountVal * Mathf.Deg2Rad));

 

単純な処理なんですがsin関数を使った単振動なので「amountVal」を0~180に変化させれば、localScaleは最終的に元に戻ってくれます。便利。

 

よって、この処理にDotweenのToを使って「amountVal」を変化させてやることになります。
なお、Dotween.Toでは変化中のコールバック(OnUpdate)が指定できるので、ジャンプ中と着地後それぞれでコールバックを指定して、その中で上の処理を使ってlocalScaleを変更させます。

 

public float amountVal = 0;

public void JumpCharactor()
{
    // ジャンプ処理
    Vector3 dispPos = this.transform.position;
    this.transform.DOJump(dispPos, 1.0f, 1, 1.0f)
                        .OnComplete(OnComplete_Jump);
	
    // amountValの変化
    DOTween.To( () => amountVal, 
                (x) => amountVal = x, 
                180.0f, 
                1.0f)
              .OnUpdate(CallBack_ChangeValues);
}

// コールバック:ジャンプ中のamountValの変化
public void CallBack_ChangeValues()
{
	// 縦(Y)方向に伸びて横(XZ)方向は縮む
	this.transform.localScale = new Vector3(
	    1.0f - 0.40f * Mathf.Sin(amountVal * Mathf.Deg2Rad),
	    1.0f + 0.40f * (Mathf.Sin(amountVal * Mathf.Deg2Rad)),
	    1.0f - 0.40f * Mathf.Sin(amountVal * Mathf.Deg2Rad));
}

// コールバック:Jump完了後
public void OnComplete_Jump()
{
    amountVal = 0.0f;
	
    // amountValの変化
    DOTween.To( () => amountVal, 
                (x) => amountVal = x, 
                targetVal, 
                1.0f)
              .OnUpdate(CallBack_AfterJump);
}

// コールバック:着地後のamountValの変化
public void CallBack_AfterJump()
{
	// 横(XZ)方向に伸びて縦(Y)方向は縮む
	this.transform.localScale = new Vector3(
	    1.0f + 0.45f * Mathf.Sin(amountVal * Mathf.Deg2Rad),
	    1.0f - 0.45f * (Mathf.Sin(amountVal * Mathf.Deg2Rad)),
	    1.0f + 0.45f * Mathf.Sin(amountVal * Mathf.Deg2Rad));
}

で、実際に動作させるとこんな感じ

f:id:Karvan:20191015211954g:plain

 

単純なJumpより楽しい動きになったのではないでしょうか。
あまり使用されないDotween.Toですが、意外と使い勝手は良いですね。

 

【Unity】ゲーム開発で頻繁に使う便利スクリプト

やっぱり休みの日は雨がいい

行楽シーズンで快晴の休日を一日中部屋で過ごし、ふと窓の外が夕焼けに染まっているのに気づいて激しい寂寥感に襲われた皆さんこんにちは。

どこか行こうにもどこにも行くところがないっては辛過ぎなので休みの日はずっと雨でお願いします。

「雨だからなぁー、どこにも行けないなぁー、部屋で過ごすしかないなぁー」って自分に言い聞かせるので

 

言い訳タイム

そういばここ最近は2.5DのSTG開発についてこのブログで触れることがありませんでした。

ありませんでした、というかブログで報告できるような進捗がほとんどないからで、というのも、会社から帰宅⇒PCを起動⇒Unityを立ち上げ⇒プロジェクトを開き⇒寝る、この繰り返しばかりで大事な「開発する」という工程がきれいさっぱり抜けているからです。

 

いや、一応やる気はあるんですよ。

毎日晩飯後には必ずUnityを立ち上げてプロジェクトを開くと何故か急に眠気が襲ってきて「ちょっと10分ぐらい・・・」の気持ちでソファーに寝そべると何故か翌日の午前2時にタイムワープしてしまうという特殊能力を抑えられない自分が憎い。

PS4で遊んでいるときはちっとも眠くないのに何故だろう?

 

便利スクリプト

そんなわけで、ゲーム開発に足を突っ込んでStab of Bee Projectの立ち上げからは2本しからリリースしてないのですが、それ以前からプロトタイプ的なものを作っていたり、UnityRoomへ投稿していたりするので、作成したプロジェクトはそこそこの数になっていたり。


そんな中でも毎度お世話になっている(使用している)便利スクリプトのご紹介

 

BetterDictionary

github.comUnity 向けに高速化されたDictionaryクラス
かつ、ボックス化の発生を防ぐことができます

 

StringOperationUtil

github.comString の連結についてパフォーマンスを改善することができます。
StringBufferを使うより簡便なステップで実装できます

 

PanelSlider

hoge465.seesaa.netuGUIのPanelをスライドイン/アウトさせる
AnimationCurveを使用してイージングを指定できます

 

ErrorReporter

fantom1x.blog130.fc2.comAndroid実機でエラーログをファイルに出力します
実機での動作テスト中には重宝します

 

Unityはコミュニティの層が厚いので、便利なツール(スクリプト)も色々揃っていて有難いですね。

 

 

【Unity】範囲内の時間を制御・・・してるっぽく見せる

消費税増税前に

以前から承知していた事なんですが、いざ直前となると焦る気持ちが湧き上がってきて「折角だから今のうちに買っておこう」と結構値段の張るコートを買った後で「こんなのいつ着るんだ・・・」と我に返って唖然としている皆さんこんにちは。
真冬用のコートなんですが、そもそも真冬は寒くて外に出ないことに気づいた。

 

Chronosというアセット

そんなわけでUnityアセットの購入にも二の足を踏む今日この頃なんですが、以前から気になっていたアセットがありまして「Chronos - Time Control」という時間制御が簡単にできるアセット

 

youtu.be上のプロモーションムービーのようにゲーム時間の制御以外にもグループ単位の速度変更やオブジェクト動作の早送り・逆廻し等々、時間に関する制御が簡便に実装できるアセットで、その中で私の目を引いたのは「Area Clock」という特定の範囲内にだけ時間制御を適用できるという機能、なんかメッチャカッコいい

 

とはいえ税抜きで$40.0程するので増税前だからと言ってホイホイ購入するわけにもいきません。コートは一回払いで買っちゃったからね!
なので「Area Clock」と同じような機能を実現する方法を考えてみました。

 

単純な方法

今回は下図のようなステージを使い、二匹のキャラクターが中央のドームに入っている間はゆっくり動いてすれ違うような動作を作ってみます。前回、前々回記事からの使い回しとか言わないよ、絶対

 

f:id:Karvan:20191001205937p:plain

 

まぁ方法は単純で、キャラクターの移動にはDoTweenのSequence、アニメーションにはAnimatorを使っているので、特定のCollider内にキャラクターがある場合にSequenceとAnimatorのTimeScale(Animatorはspeed)を変更してあげればよいだけです。

 

    Sequence PathSeq;
    Animator myAnim;

    private void OnCollisionEnter(Collision collision)
    {
       PathSeq.timeScale = 0.3f;
        myAnim.speed = 0.3f;
    }

    private void OnCollisionExit(Collision collision)
    {
        PathSeq.timeScale = 1.0f;
        myAnim.speed = 1.0f;
    }

 

こんな感じ

 二匹のキャラクターにはColliderだけでなくRigidbodyを付けるのを忘れないように。
またキャラクターがドームの中に入る(衝突する)時はRigidbodyの影響をうけるので注意する必要があります。

 

で、実際の動作はこんな感じ

f:id:Karvan:20191001210201g:plain

 

単純な処理ですが、$40.0が浮いたと思えば・・・

 

【Unity】Dotweenの便利なコールバックについて

不正不満を口にする

はてなブログは「画像のアップロードに失敗しました」とかメッセージ出す癖に、ページをリロードするとちゃんと投稿欄にアップロードされているのはやめろ。おかげで同じ動画が投稿欄を埋めて尽くしているんですが。
それからTwitterの「〇〇さんが▲▲さんのツイートにいいねしました」という通知は不要です。私にどうしろというのか。

 

そんな感じで不正不満だけは止まらない屈折した日々を過ごしている所為なのか新作ゲームの進捗はさっぱり進みません。

f:id:Karvan:20190924232422p:plain

この三連休ではアセットストアから敵用のモデルを購入してカスタマイズしたぐらい

 

Dotweenのコールバック

さて、Unityでオブジェクトをアレコレ動かす際にお世話になるDotween
移動(Move)や回転(Rotate)以外にも前回の記事でも使用した経路移動(DoPath)、ジャンプ(DoJump)など、色々便利な関数が用意されているのですが、それと同じようにコールバックも色々なタイミングで使えるように用意されています。

 

  •  OnComplete:Tweener、Sequenceの完了時コールバック
  • OnStart:こちらはTweener、Sequenceの開始時のコールバック

 

おそらく使用頻度が高いのは上記の二つだと思うのですが、これ以外に使い勝手が良いものを上げると

 

・PrependCallback

Tweenerの開始時コールバック
Sequenceの場合は各Tweenerの開始時コールバック
OnStartはSequence全体の開始時ですが、こちらはSequenceの各動作(Tweener)毎の開始前に呼ばれます。

 

・AppendCallback(Sequence用)

Sequenceの各Tweenerの終了時コールバック
OnCompleteと違い各動作(Tweener)毎の完了時に呼ばれます

 

・OnWaypointChange(DOPath、DOLocalPath用)

経路として指定した座標に到達するたびに呼ばれます。
引数としてDOPath,DOLocalPathで指定したVector3配列のIndexが渡されます。

 

 ちょっと使ってみよう

丁度前回の記事でDOLocalPathとDoJumpをSequenceに設定してキャラクターを動かしていたので、それを利用してコールバックの動作を確認しましょう。

 

前回のキャラクター移動

f:id:Karvan:20190917204540g:plain


上の動画では以下の動作をSequenceに設定しています。

  1.  Start~Path3まで:DOLocalPathによる移動
  2. Jump1~Jump3まで:DoJumpを繰り返し
  3. Jump3~Goalまで:DOLocalPathによる移動

f:id:Karvan:20190924233353p:plain

 

ここで、1のDOLocalPathにてOnWaypointChangeを設定しPath1のポイントに達したら、Sequenceを一時停止してキャラクターのAnimationを変更します。

 

まず、Sequence側にOnWaypointChangeを指定します。

    PathSeq.Append(
            myObj.transform.DOLocalPath(Path1Array, 6.0f, PathType.CatmullRom)
                                .SetLookAt(0.05f, Vector3.forward)
                                .OnWaypointChange(x => CallBack_WaitPoint(x))
                                .OnComplete(() => CallBack_Path1())

        );

コールバック関数側でAnimationの変更とSequenceの一時停止、再開を行うようにします

    public void CallBack_WaitPoint(int index)
    {
        if (index == 1)
        {
            // Sequenceの一時停止
            PathSeq.TogglePause();
            
            // 座るAnimation
            myAnim.SetInteger("Animation", 4);

            StartCoroutine(SequenceRestart());
        }
    }

    private IEnumerator SequenceRestart()
    {
        yield return new WaitForSeconds(3.0f);

        // Sequenceの再開
        PathSeq.TogglePause();
        
        // 歩くAnimation
        myAnim.SetInteger("Animation", 1);
    }

次に、2のDoJumpではPrependCallbackを使用して3回目のジャンプ開始前にSequenceを一時停止してキャラクターのAnimationを変更します。

Sequence側にPrependCallbackを指定

   for(int iCnt = 0; iCnt < Jump1Array.Length; iCnt++)
   {
       PathSeq.Append(
               myObj.transform.DOJump(Jump1Array[iCnt], 0.5f, 1, 1.0f)
                               .PrependCallback(() => CallBack_PreJump())
                               .PrependInterval(0.5f)
                               .OnComplete(() => CallBack_CompJump())
           );
   }

コールバック関数側でAnimationの変更とSequenceの一時停止、再開。ここでは回数を計るためにOnCompleteのコールバックにてジャンプの完了回数をカウントアップしています。

    public void CallBack_PreJump()
    {
        // 3回目のジャンプ開始前の場合
        if (JumpComp == 2)
        {
            // Sequenceの一時停止
            PathSeq.TogglePause();
            
            // 座るAnimation
            myAnim.SetInteger("Animation", 4);
            
            
            StartCoroutine(SequenceStepRestart());
            return;
        }

        // ジャンプAnimation
        myAnim.SetInteger("Animation", 2);
    }

    private IEnumerator SequenceStepRestart()
    {
        yield return new WaitForSeconds(3.0f);

        // Sequenceの再開
        PathSeq.TogglePause();
        
        // ジャンプAnimation
        myAnim.SetInteger("Animation", 2);
    }

    public void CallBack_CompJump()
    {
        // ジャンプの完了回数をカウントアップ
        JumpComp++;
    }

これを実際に動作させるとこんな感じになります。

f:id:Karvan:20190922161358g:plain

コールバックを使うと色々な動きが可能となるので積極的に使ってみましょう。

 

【Unity】DotweenのSequenceでDoLocalJumpを使う時は注意が必要

三連休

「三連休ですね~、何か予定があるんですか?」という質問が世の中で一番嫌いな皆さんこんにちは。オイオイ、いくら行楽の秋だからと言って誰もがドライブしたりBBQしたり観光したりするとは思うなよ、と言うことで、理容師のお姉さんへ、答えに窮する質問を投げかけるのはやめて下さい、それから髪を洗う時に不意に頭のツボを押すのもやめて下さい、変な声出そうになった。

 

この機会に知ってほしい事があるの~!!

というわけで、ダラダラ説明するよりまずは下の動画を見てほしい

f:id:Karvan:20190917202614g:plain

 

まるで某巨大変身ヒーローみたいな仕草でキャラクターが画面外に飛んで行っていますが、別に意図的にそうした訳ではなく、本来は階段をジャンプしながら登って先に進む、という動作をDotweenのSequenceを使って実装した結果です。

 

Dotweenって何?Sequenceって美味しいの?っていう人は下のリンクを参照してください

qiita.com

要はGameObjectの移動を連続させて行う際に使用するAPIで、今回の場合はキャラクターに対して

  1. 階段までの経路を移動する
  2. 一段目の段差をジャンプして移動する
  3. 二段目の段差をジャンプして移動する
  4. 三段目の段差をジャンプして移動する
  5. 階段の端まで移動する

という動作を連続で行うように設定しています。

この時、1.と5.の移動にはDoPathによる経路移動を、2.3.4.のジャンプにはDoLocalJumpを使用します。

 

DoPathによる経路移動については下記参照

www.karvan1230.com

ソース的にはこんな感じです。

 

   PathSeq = DOTween.Sequence();

   // 階段までの経路移動
   PathSeq.Append(
           myObj.transform.DOLocalPath(Path1Array, 6.0f, PathType.CatmullRom)
                               .SetLookAt(0.05f, Vector3.forward)

       );

   // 各段差をジャンプして移動
   for(int iCnt = 0; iCnt < Jump1Array.Length; iCnt++)
   {
       PathSeq.Append(
               myObj.transform.DOLocalJump(Jump1Array[iCnt], 0.5f, 1, 1.0f)
           );
   }

   // 階段の端まで移動する
   PathSeq.Append(
       myObj.transform.DOLocalPath(Path2Array, 4.0f, PathType.CatmullRom)
                           .SetLookAt(0.05f, Vector3.forward)

   );
 

何故飛んで行ってしまうのか?

ソースだけを眺めていると特におかしな処理はしていないので、移動先の座標さえ間違っていなければ意図通りの動作をすると思うのですが、結果としては大ジャンプを繰り返して画面外へ消える動作となっています。

 

これはきっとDotweenのバグに違いない、ということで、下のモデルを使って検証してみることにしました。

f:id:Karvan:20190917203415p:plain


赤いCubeをSequenceを使って移動させるのですが、図の通りに同じ高さの場所をDOLocalJumpで移動させる場合と、異なる高さをDOLocalJumpで移動させる場合について比較してみます。

まずは同じ高さを移動する場合

f:id:Karvan:20190917203511g:plain

 

特に問題なく移動できます。
次は違う高さを移動する場合

f:id:Karvan:20190917203606g:plain

 想定以上に飛び上がって移動し、最終位置もずいぶん高い位置になっています。


これをSequenceを使用せずにDOLocalJumpを連続で使用した場合は

f:id:Karvan:20190917203706g:plain

きちんと指定先にジャンプ移動します。


これは垂直方向へ飛びあがる場合も同じで、Sequenceを使った場合とDOLocalJumpを連続で使用した場合では動作が全く異なります。

 

Sequenceを使った場合

f:id:Karvan:20190917203853g:plain

 

DOLocalJumpを連続で使用した場合

f:id:Karvan:20190917203947g:plain

 

Sequenceを使った場合は指定した位置以上へ飛び上がる結果となります。

また、これは飛び上がる場合だけでなく下へ飛び降りる場合も同じで、ジャンプを繰り返すほど下へ落ち込む軌道になります。

 

想定するに最終的な高さ(Y座標)の差異が、次のジャンプの計算に影響していると思われ、ジャンプを繰り返すほど大きなジャンプ軌道を描くようになり、最終的な位置も異なるようになります。


まぁこれらの挙動(不具合)について言及しているサイトを見つけることが出来なかったので想像の範囲なのですが、これまでの事象をまとめると

SequenceでDOLocalJumpを使用する場合は同じ高さ(Y座標)を移動する場合に限る

ということになります。

 

対処法

まぁ、Sequenceを使用せずにその都度DOLocalJumpを使用すればいいことなんですが、どうしてもSequenceを使いたい、ジャンプの時だけ別口で処理をするのは面倒くさい、という場合は

SequenceではDOLocalJumpではなくDOJumpを使用してください

移動先の座標をローカル座標ではなくワールド座標に変更するもの忘れずに。

 

先程のソースでDOLocalJumpとなっている箇所をDOJumpに変更した結果が以下の動画になります。

 

f:id:Karvan:20190917204540g:plain

きちんと想定通りに動作してくれました。めでたしめでたし。
 

 

◇プライバシーポリシー

●個人情報の利用目的

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

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

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

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

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

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

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

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

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

●免責事項

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

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

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

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

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

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