Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9297

【Unity】打ち上げ攻撃→空中コンボ攻撃を実装

$
0
0

はじめに

初めてQiitaに記事を投稿します。

現在Unityで個人開発している2.5Dのアクションゲームで打ち上げ攻撃からの空中コンボという
ハイスピードなアクションゲームによくみられる挙動を実装したのですが、
実装するにあたって海外の記事や動画でもそれらしい情報がほとんど見つけられず
苦戦したのでこの度自分なりの実装方法を記事として残すことにしました。

本記事ではRigidBodyを用いてキャラクターを操作する方法を用いています。
CharacterControllerを使った場合でも応用は効くかと思います。
アニメーションの再生やアニメーターを使ったアニメーションの繋ぎ方等は省略しておりますので
下記のサイトを参考にしていただければと思います。
[Unityのアクションゲームで連続攻撃を実現する方法](https://gametukurikata.com/program/continuityattack)

それでは早速本題に入っていきましょう!

目次

・打ち上げ攻撃の実装
・空中コンボの制御
・最後に

打ち上げ攻撃の実装

まずは一連の動作の起点となる打ち上げ攻撃の実装になります。
これがなきゃ始まりません。

と言ってもこの時点では複雑なことはなく、打ち上げ攻撃のアニメ―ションイベントで
操作キャラと敵を打ち上げる関数を呼び出すだけです。
打ち上げ動作に移るイイ感じのフレームで呼び出してあげましょう。
(アニメーションイベントに関してはこちらを)
https://docs.unity3d.com/ja/2018.4/Manual/animeditor-AnimationEvents.html)

以下、打ち上げ用の関数です。Dotweenを用いています。
打ち上げる高さや速度に関してはゲームバランスにうまくハマるように各々調整していただければと思います。

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingDG.Tweening;publicclassMeleeAttackManager:MonoBehaviour{Rigidbodyrb;voidStart(){rb=GetComponent<Rigidbody>();}voidLaunch() //打ち上げ用の関数{rb.DOMoveY(7f,0.5f); //Y方向に0.5秒かけて上昇Collider[]hitEnemies=Physics.OverlapSphere(AttackPoint.position,AttackRange,enemyLayers);//コライダー出現foreach(ColliderenemyinhitEnemies){enemy.GetComponent<EnemyScript>().Launch(); //攻撃を受けた敵を打ち上げます。}}

同様に敵キャラにも打ち上げ用の関数の書かれたスクリプトをアタッチしましょう。

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingDG.Tweening;publicclassEnemyScript:MonoBehaviour{Rigidbodyrb;voidStart(){rb=GetComponent<Rigidbody>();}// Update is called once per framevoidUpdate(){}publicvoidLaunch(){rb.DOMoveY(7f,0.5f); //攻撃を受けた敵を打ち上げます。}}

打ちあがる高さと時間に関してはプレイヤー側と同じ数値に揃えましょう。

これで打ち上げ処理は実装できました!
ところがこのままでは。。。
ezgif.com-gif-maker.gif
空中でコンボを決めようにも落下してしまっています。
カッコよさもへったくれもありません。
なので次は空中コンボの制御をしていきましょう。

空中コンボの制御

打ち上げ攻撃を実装できましたがこのままでは空中コンボに落下してしまいみっともないです。
ケレン味のあるアクションを実現するためにも重力に逆らってもらいましょう。

方法としては
打ち上げ→RigidBodyのUseGravityをオフにしたり同じくRigidBodyのDragの数値を弄ることで一定時間空中に留まる→空中コンボが敵に当たれば滞空時間を延長→攻撃が当たらなかったりコンボが途切れると落下を始める

という実装方法に落ち着きました。
今回はDragの値を弄ることにします。
早速詳しくやっていきましょう。

まずは滞空するためにDragの値を弄る関数を用意してこの関数を打ち上げ用の関数実行時に呼び出します。

  publicvoidOffGrvity(){rb.drag=40; //RigidBodyのDragの数値を弄る}voidLaunch(){OffGrvity(); //OffGrvityを実行rb.DOMoveY(7f,0.5f);Collider[]hitEnemies=Physics.OverlapSphere(AttackPoint.position,AttackRange,enemyLayers);//コライダー出現foreach(ColliderenemyinhitEnemies){enemy.GetComponent<EnemyScript>().Launch(); //敵を打ち上げるenemy.GetComponent<EnemyScript>().OffGrvity(); //敵側のOffGravityを実行}}

Dragの値は40にして殆ど落下しないようになっています。
同様に敵側にも

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingDG.Tweening;publicclassEnemyScript:MonoBehaviour{Rigidbodyrb;voidStart(){rb=GetComponent<Rigidbody>();}// Update is called once per framevoidUpdate(){}    publicvoidOffGrvity(){rb.drag=40; //RigidBodyのDragの数値を弄る}publicvoidLaunch(){rb.DOMoveY(7f,0.5f); //攻撃を受けた敵を打ち上げます。}}

Dragの値を弄る関数を追加して攻撃を受けた際に実行されるようにします。
これで落下せずに空中コンボを決められますがこのままでは宙に浮いたまま降りてこないので

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingDG.Tweening;publicclassMeleeAttackManager:MonoBehaviour{Rigidbodyrb;privatefloatairStayTime=1; //滞空可能時間voidStart(){rb=GetComponent<Rigidbody>();}    voidUpdate(){if(rb.drag!=0){airStayTime-=Time.deltaTime; //Dragの値が0でなければairStayTimeの値を減らしていく}if(airStayTime<0){OnGrvity();  //落下airStayTime=1; //airStayTimeの値をリセット}}    publicvoidOnGrvity(){if(rb.drag!=0){rb.drag=0; //Dragの値を0に戻して落下}}    publicvoidOffGrvity(){rb.drag=40; //RigidBodyのDragの数値を弄る}voidLaunch() //打ち上げ用の関数{rb.DOMoveY(7f,0.5f); //Y方向に0.5秒かけて上昇Collider[]hitEnemies=Physics.OverlapSphere(AttackPoint.position,AttackRange,enemyLayers);//コライダー出現foreach(ColliderenemyinhitEnemies){enemy.GetComponent<EnemyScript>().Launch(); //攻撃を受けた敵を打ち上げます。}}publicvoidairStayExtend() //滞空時間を延長{Collider[]hitEnemies=Physics.OverlapSphere(AttackPoint.position,AttackRange,enemyLayers);//コライダー出現foreach(ColliderenemyinhitEnemies){enemy.GetComponent<EnemyScript>().airStay(); //敵のairStayTimeの値を更新して滞空時間を延長}airStayTime=0.7f;//airStayTimeの値を更新して滞空時間を延長}}

変数airStayTimeを新たに用意します。
Dragの値が0でなかった場合Update内でairStayTimeの値を減らし、
airStayTimeの値が0を下回った時点でOnGravity関数を実行して落下しています。
さらに、空中で攻撃を当てるたびにairStayTimeの値を増やしていかないと
コンボ中にやっぱり落下してしまうので
airStayExtendという関数を用意しています。
このairStayExtendを空中コンボのアニメーションイベントで実行することで
敵に攻撃を当てた際に滞空時間を延長しています。

例によって例の如く敵のスクリプトにも同じ処理を

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingDG.Tweening;publicclassEnemyScript:MonoBehaviour{Rigidbodyrb;  privatefloatairStayTime=1;voidStart(){rb=GetComponent<Rigidbody>();}// Update is called once per framevoidUpdate(){    if(rb.drag!=0){airStayTime-=Time.deltaTime;}if(airStayTime<0){OnGrvity();airStayTime=1;}}  publicvoidOnGrvity(){if(rb.drag!=0){rb.drag=0; //Dragの値を0に戻して落下}}    publicvoidOffGrvity(){rb.drag=40; //RigidBodyのDragの数値を弄る}publicvoidLaunch(){rb.DOMoveY(7f,0.5f); //攻撃を受けた敵を打ち上げます。}  publicvoidairStayExtend(){airStayTime=0.7f; //滞空時間を延長}}

これで空中コンボは完成です!

ezgif.com-gif-maker (1).gif

最後に

突貫工事で実装をしたので粗がある気はしますが、また改善され次第更新していこうと思います。
Qiita初投稿で読みづらい部分等あったかもしれませんが最後まで読んでいただきありがとうございました!


Viewing all articles
Browse latest Browse all 9297

Trending Articles