- 投稿日:2020-11-23T20:17:23+09:00
【Unity】打ち上げ攻撃→空中コンボ攻撃を実装
はじめに
初めてQiitaに記事を投稿します。
現在Unityで個人開発している2.5Dのアクションゲームで打ち上げ攻撃からの空中コンボという
ハイスピードなアクションゲームによくみられる挙動を実装したのですが、
実装するにあたって海外の記事や動画でもそれらしい情報がほとんど見つけられず
苦戦したのでこの度自分なりの実装方法を記事として残すことにしました。本記事ではRigidBodyを用いてキャラクターを操作する方法を用いています。
CharacterControllerを使った場合でも応用は効くかと思います。
アニメーションの再生やアニメーターを使ったアニメーションの繋ぎ方等は省略しておりますので
下記のサイトを参考にしていただければと思います。
[Unityのアクションゲームで連続攻撃を実現する方法](https://gametukurikata.com/program/continuityattack)それでは早速本題に入っていきましょう!
目次
・打ち上げ攻撃の実装
・空中コンボの制御
・最後に打ち上げ攻撃の実装
まずは一連の動作の起点となる打ち上げ攻撃の実装になります。
これがなきゃ始まりません。と言ってもこの時点では複雑なことはなく、打ち上げ攻撃のアニメ―ションイベントで
操作キャラと敵を打ち上げる関数を呼び出すだけです。
打ち上げ動作に移るイイ感じのフレームで呼び出してあげましょう。
(アニメーションイベントに関してはこちらを)
(https://docs.unity3d.com/ja/2018.4/Manual/animeditor-AnimationEvents.html)以下、打ち上げ用の関数です。Dotweenを用いています。
打ち上げる高さや速度に関してはゲームバランスにうまくハマるように各々調整していただければと思います。using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class MeleeAttackManager : MonoBehaviour { Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Launch() //打ち上げ用の関数 { rb.DOMoveY(7f, 0.5f); //Y方向に0.5秒かけて上昇 Collider[] hitEnemies = Physics.OverlapSphere(AttackPoint.position, AttackRange, enemyLayers); //コライダー出現 foreach (Collider enemy in hitEnemies) { enemy.GetComponent<EnemyScript>().Launch(); //攻撃を受けた敵を打ち上げます。 } }同様に敵キャラにも打ち上げ用の関数の書かれたスクリプトをアタッチしましょう。
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class EnemyScript : MonoBehaviour { Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } // Update is called once per frame void Update() { } public void Launch() { rb.DOMoveY(7f, 0.5f); //攻撃を受けた敵を打ち上げます。 } }打ちあがる高さと時間に関してはプレイヤー側と同じ数値に揃えましょう。
これで打ち上げ処理は実装できました!
ところがこのままでは。。。
空中でコンボを決めようにも落下してしまっています。
カッコよさもへったくれもありません。
なので次は空中コンボの制御をしていきましょう。空中コンボの制御
打ち上げ攻撃を実装できましたがこのままでは空中コンボに落下してしまいみっともないです。
ケレン味のあるアクションを実現するためにも重力に逆らってもらいましょう。方法としては
打ち上げ→RigidBodyのUseGravityをオフにしたり同じくRigidBodyのDragの数値を弄ることで一定時間空中に留まる→空中コンボが敵に当たれば滞空時間を延長→攻撃が当たらなかったりコンボが途切れると落下を始めるという実装方法に落ち着きました。
今回はDragの値を弄ることにします。
早速詳しくやっていきましょう。まずは滞空するためにDragの値を弄る関数を用意してこの関数を打ち上げ用の関数実行時に呼び出します。
public void OffGrvity() { rb.drag = 40; //RigidBodyのDragの数値を弄る } void Launch() { OffGrvity(); //OffGrvityを実行 rb.DOMoveY(7f, 0.5f); Collider[] hitEnemies = Physics.OverlapSphere(AttackPoint.position, AttackRange, enemyLayers); //コライダー出現 foreach (Collider enemy in hitEnemies) { enemy.GetComponent<EnemyScript>().Launch(); //敵を打ち上げる enemy.GetComponent<EnemyScript>().OffGrvity(); //敵側のOffGravityを実行 } }Dragの値は40にして殆ど落下しないようになっています。
同様に敵側にもusing System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class EnemyScript : MonoBehaviour { Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } // Update is called once per frame void Update() { } public void OffGrvity() { rb.drag = 40; //RigidBodyのDragの数値を弄る } public void Launch() { rb.DOMoveY(7f, 0.5f); //攻撃を受けた敵を打ち上げます。 } }Dragの値を弄る関数を追加して攻撃を受けた際に実行されるようにします。
これで落下せずに空中コンボを決められますがこのままでは宙に浮いたまま降りてこないのでusing System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class MeleeAttackManager : MonoBehaviour { Rigidbody rb; private float airStayTime = 1; //滞空可能時間 void Start() { rb = GetComponent<Rigidbody>(); } void Update() { if (rb.drag != 0) { airStayTime -= Time.deltaTime; //Dragの値が0でなければairStayTimeの値を減らしていく } if (airStayTime < 0) { OnGrvity(); //落下 airStayTime = 1; //airStayTimeの値をリセット } } public void OnGrvity() { if(rb.drag != 0) { rb.drag = 0; //Dragの値を0に戻して落下 } } public void OffGrvity() { rb.drag = 40; //RigidBodyのDragの数値を弄る } void Launch() //打ち上げ用の関数 { rb.DOMoveY(7f, 0.5f); //Y方向に0.5秒かけて上昇 Collider[] hitEnemies = Physics.OverlapSphere(AttackPoint.position, AttackRange, enemyLayers); //コライダー出現 foreach (Collider enemy in hitEnemies) { enemy.GetComponent<EnemyScript>().Launch(); //攻撃を受けた敵を打ち上げます。 } } public void airStayExtend() //滞空時間を延長 { Collider[] hitEnemies = Physics.OverlapSphere(AttackPoint.position, AttackRange, enemyLayers); //コライダー出現 foreach (Collider enemy in hitEnemies) { enemy.GetComponent<EnemyScript>().airStay(); //敵のairStayTimeの値を更新して滞空時間を延長 } airStayTime= 0.7f; //airStayTimeの値を更新して滞空時間を延長 } }変数airStayTimeを新たに用意します。
Dragの値が0でなかった場合Update内でairStayTimeの値を減らし、
airStayTimeの値が0を下回った時点でOnGravity関数を実行して落下しています。
さらに、空中で攻撃を当てるたびにairStayTimeの値を増やしていかないと
コンボ中にやっぱり落下してしまうので
airStayExtendという関数を用意しています。
このairStayExtendを空中コンボのアニメーションイベントで実行することで
敵に攻撃を当てた際に滞空時間を延長しています。例によって例の如く敵のスクリプトにも同じ処理を
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class EnemyScript : MonoBehaviour { Rigidbody rb; private float airStayTime = 1; void Start() { rb = GetComponent<Rigidbody>(); } // Update is called once per frame void Update() { if(rb.drag != 0) { airStayTime -= Time.deltaTime; } if(airStayTime < 0) { OnGrvity(); airStayTime = 1; } } public void OnGrvity() { if(rb.drag != 0) { rb.drag = 0; //Dragの値を0に戻して落下 } } public void OffGrvity() { rb.drag = 40; //RigidBodyのDragの数値を弄る } public void Launch() { rb.DOMoveY(7f, 0.5f); //攻撃を受けた敵を打ち上げます。 } public void airStayExtend() { airStayTime = 0.7f; //滞空時間を延長 } }これで空中コンボは完成です!
最後に
突貫工事で実装をしたので粗がある気はしますが、また改善され次第更新していこうと思います。
Qiita初投稿で読みづらい部分等あったかもしれませんが最後まで読んでいただきありがとうございました!
- 投稿日:2020-11-23T17:43:32+09:00
UniRxの「Debug」オペレータが便利
「Debug」オペレータ
UniRxには「
Debug
」という便利なオペレータが存在します。
これは「Observable上で起きたすべてのイベントをログに出力する」というオペレータです。
- どの値が発行されたか
- 何の例外が起きたか
- どのタイミングで
Subscribe()
されたか- どのタイミングで購読が中断されたか
などをこのオペレータ1つですべて知ることができます。
定義
定義としてはこうなってます。
// copy from https://github.com/neuecc/UniRx/blob/master/Assets/Plugins/UniRx/Scripts/UnityEngineBridge/Diagnostics/ObservableDebugExtensions.cs public static IObservable<T> Debug<T>(this IObservable<T> source, string label = null) { #if DEBUG var l = (label == null) ? "" : "[" + label + "]"; return source.Materialize() .Do(x => UnityEngine.Debug.Log(l + x.ToString())) .Dematerialize() .DoOnCancel(() => UnityEngine.Debug.Log(l + "OnCancel")) .DoOnSubscribe(() => UnityEngine.Debug.Log(l + "OnSubscribe")); #else return source; #endif } public static IObservable<T> Debug<T>(this IObservable<T> source, UniRx.Diagnostics.Logger logger) { #if DEBUG return source.Materialize() .Do(x => logger.Debug(x.ToString())) .Dematerialize() .DoOnCancel(() => logger.Debug("OnCancel")) .DoOnSubscribe(() => logger.Debug("OnSubscribe")); #else return source; #endif }
Do()
+DoOnCancel()
+DoOnSubscribe()
ということで、Observable上で起きたすべてのイベントをログへ出力できるようになっています。
しかもラベルを付与したり、UniRx.Diagnostics.Logger
を利用することもできます。ちなみに
UniRx.Diagnostics
名前空間に定義されているのでこちらへのusingを忘れずに。使い方
Observable
の途中にDebug()
を挟むだけです。using UniRx; using UniRx.Diagnostics; using UnityEngine; public sealed class DebugSample : MonoBehaviour { private readonly Subject<int> _subject = new Subject<int>(); private void Start() { _subject .Debug("Debugサンプル") // Debugオペレータ .Subscribe() .AddTo(this); _subject.OnNext(1); _subject.OnNext(2); _subject.OnNext(3); Destroy(gameObject); } private void OnDestroy() { _subject.Dispose(); } }実行結果[Debugサンプル]OnSubscribe [Debugサンプル]OnNext(1) [Debugサンプル]OnNext(2) [Debugサンプル]OnNext(3) [Debugサンプル]OnCancelログの読み方
メッセージ 意味 OnSubscribe Observable
がSubscribe()
されたOnNext(Value) Value
という値のOnNext
メッセージが発行されたOnCompleted OnCompleted
メッセージが発行されたOnError(ex) ex
という型のOnError
メッセージが発行されたOnCancel Subscribe()
のDispose()
が実行された最後に
UniRxについて学べる技術書が出版されました。
(ちなみにこの
Debug
オペレータについて、本の中で解説するのを忘れています。本当にすいません…。)
- 投稿日:2020-11-23T17:19:33+09:00
Unity PlayGround Referenceガイド③
Unity Playgroundリファレンスガイド日本語訳版の内容をもとに、スクリプトの内容を一つずつ確認していきます。
ConditionスクリプトとActionスクリプト
ConditionスクリプトはActionスクリプトとセットで使用します。これにより、さまざまな条件分岐が作れるようになります。事前に用意されているActionスクリプトだけでなく、自作のスクリプトを実行させることもできます。すべてのConditionスクリプトにはActionスクリプトを設定するプロパティが存在します。
プラスアイコンを押すと、追加可能なアクションのリストが表示されます。ドロップダウンの最後に、空のスロット(Empty slot)を追加することもできます。
Custom Actionsをオンにすると、PlayGroundに登録されている以外のさまざまなスクリプトを実行させられます。特定の条件化(敵を破壊したときなど)で音を鳴らすなどは、その一つです。
Condition AreaとCreate Object Action
Condition Areaは何か特別なオブジェクトが重なった状態を検出したい時に使用するスクリプトです。オブジェクトがゴールに到達した時の状態を検出する際などに使われます。この時オブジェクトは何らかのCollider 2Dがアタッチされており、かつIs Trigerがオンになっている必要があります。この点がCondition Conditionとの違いです。また、Condition Areaを使うと、オブジェクトが「重なった瞬間」「重なり続けている間ずっと」「一度重なって、離れた瞬間」をそれぞれ検出することもできます。
Happen Only Once:オンにすると一度重なりを検出したら、以後は検出しなくなります。
Filter by Tag:オンにすると特定のタグがついたオブジェクトのみ重なりを検出させられます。
Event Type:検出するタイミングを「重なった瞬間」「重なり続けている間ずっと」「一度重なって、離れた瞬間」のいずれかから選択できます。
Create Object Actionは指定したプレハブから新しいインスタンスを作り出すスクリプトです。
Prefab To Create:生成するプレファブを指定します。
New Position:プレファブが生成されるワールド座標を指定します。
Relative To This Object:オンにするとプレファブの生成位置をワールド座標ではなく、本スクリプトがアタッチされたオブジェクトのローカル座標にできます。ここでは、この2つのスクリプトを組み合わせて、Zombieeがゴールに到達したらメッセージが表示される仕組みを作ってみましょう。
Zombieeがゴールに到達したらメッセージを表示する
1:プロジェクトエリアからFlagRedプレハブを選択し、InspectorでOpen Prefabをクリックする。
2:FlagRedプレハブのInspectorでAdd Componentから「Condition Area」を絞り込み検索し、アタッチする。Condition collisionと間違えないように注意。
3:Condition Areaコンポーネントで「Happen Only Once」と「Filter by Tag」をオンにする。続いて「Tag to check for」で「Player」、「Event Type」で「Enter]を選択する。最後に「Gameplay Actions」エリアの「+」ボタンをクリックする。
4:Actionsメニューから「Create Object Action」を選択する。
5:プロジェクトエリアからgoalプレファブをCreate Objectコンポーネントの「Prefab To Create」スロットにドラッグ&ドロップする。
6:FlagRedプレハブをHierarchyにドラッグ&ドロップし、インスタンスの位置を調整する。
7:再生ボタンをクリックして、Zombieeをシーン上でFlagRedインスタンスの位置に移動させ、「CONGRATULATIONS」が画面中央に表示されれば成功だ。展開課題 ゴールに到達したら音を鳴らす
1:プロジェクトエリアのFlagRedプレハブを選択し、先ほどと同じように「Open Prefab」をクリックする。
2:FlagRedプレハブのAdd Componentから「Audio Source」を絞り込み検索し、アタッチする。
3:Condition Areaコンポーネントの「Use Custom Actions」チェックボックスをオンにする。
4:Condition AreaコンポーネントのCustom Actions()プロパティの〇ボタンをクリックし、Select Objectウィンドウの「セルフ」タブから「FlagRed」をクリックする。
5:No Functionメニューを開き、「Audio Source」→「PlayOneShot(AudioClip)」を選択する。
6:プロジェクトエリアのツリーからAssets>UnityPlayGround_Reference>Audioと進み、goal.mp3をFlagRedプレファブのCustom Actions()にある図のスロットにドラッグ&ドロップする。
7:再び再生ボタンをクリックして、ZombieeがFlagRedインスタンスに触れたら効果音が鳴るか確認しよう。Condition CollisionとDestroy Action
Condition Areaスクリプトと似たような機能をもつものにCondition Collisionスクリプトがあります。Condition Areaスクリプトがオブジェクト同士の重複を判定するのに対して、Condition collisionスクリプトはオブジェクト同士の接触を判定する点が異なります。そのためCollider 2DのIs Trigerをオフのまま使用できる点が魅力です。
Happen Only Once:オンにすると一度接触を検出したら、以後は検出しなくなります。
Filter by Tag:オンにすると特定のタグがついたオブジェクトのみ接触を検出させられます。
Destroy Actionスクリプトは指定したオブジェクトを削除するスクリプトです。OnOffActionスクリプトと異なり、オブジェクト自体を削除してしまいます。またDestroy Actionスクリプトには、削除しつつ別のオブジェクトを表示することもできます。そのため、ミサイルに当たった敵が消滅する際、同時に爆発エフェクトを表示するなどの演出を加えられます。
Target:衝突した側と衝突された側のどちらを消滅させるか選択できます。
Death Effect:オブジェクトを消滅させる際に表示するエフェクトなどを設定できます。ここでは、この2つのスクリプトを組み合わせて、BeeがZombieに触れたら爆発する仕組みを作ってみましょう。
BeeがZombieに触れたら爆発する
1:はじめにHierarchyからFlagRedを選択し、Inspectorでチェックボックスをオフにして、ゴールフラグをシーンビュー上で非表示にしておこう。
2:続いてHierarchyからEventSpawnを選択し、Inspectorでチェックボックスをオンにする。これでBeeがランダムに出現するようになる。
3:プロジェクトエリアでBeeプレファブを選択し、InspectorでOpen Prefabをクリックする。
4:BeeプレファブでTagメニューを開き、Enemyタグを選択する。これでシーンビュー上に生成されるBeeの全インスタンスにEnemyタグが付与される。
6:プロジェクトエリアでZombieプレファブを選択し、「Open Prefab」をクリックする。
7:ZombieプレファブのInspectorでAdd Componentから「Condition collision」を絞り込み検索し、アタッチする。
8:Condition collisionコンポーネントでFilter by Tagのチェックボックスをオンにし、Tag to check forメニューから「Enemy」を選ぶ。
9:Gameplay Actionsの+ボタンをクリックし、リストから「Destroy Action」を選ぶ。
10:Destroy Actionコンポーネントで、Targetを「Object That COllided(衝突した相手)」を選ぶ。その後、Death Effectのスロット右にある〇ボタンをクリックし、Select GameObjectウィンドウからAssets>P_Explosionを選ぶ。
11:無事アタッチされたら、「<」ボタンをクリックしてシーンビューに戻る。
12:再生ボタンをクリックして、ZombieがBeeに触れたら爆発エフェクトが表示されるか確認しよう。展開課題 爆発音を再生する
ConditionAreaスクリプトとCreateObjectActionスクリプトの組み合わせの時と同じように、Condition collisionスクリプトとDestroyActionスクリプトの組み合わせでも効果音を鳴らしてみよう。基本的なやり方は同じだが、ポイントはゲームオーバー時にZombieeが削除されてしまう点にある。インスタンスが削除されるので、AudioSourceをZobieeにアタッチすることが出来ないのだ。
そこでシーン上にGameManagerという空のオブジェクトを作成し、そこにAudioSourceをアタッチして、そこから音を鳴らすようにする。また、Zombieeプレファブではなく、シーン上にあるインスタンスから音を鳴らすアクションを設定するようにすればいい。
1:Hierarchyから右クリックしてメニューを開き、Create Emptyを選ぶ。
2:Hierarchyに新しく作られたGameObjectをクリックし、Inspectorで名称をGameManagerに変更する。
3:GameManagerのInspectorでAdd Componentから「Audio Source」を絞り込み検索して、アタッチする。
4:HierarchyからZombieを選択し、InspectorのCondition collisionコンポーネントからUse custom actionsのチェックボックスをオンにする。
5:Custom Actions()のRuntime Onlyメニューの下にある〇ボタンをクリックし、Select ObjectウィンドウからSceneタブをクリックし、GameManagerを選ぶ。
6:Custom Actions()のNo FunctionメニューからAudioSource>PlayOneShot(AuduoClip)を選択する。
7:Assets>UnityPlayGround_Reference>AudioからExplosion.mp3をCustom Actions()の図のスロットにドラッグ&ドロップする。
8:再生ボタンをクリックして、ZombieがBeeに触れたら爆発エフェクトと共に爆発音が再生されるか確認しよう。展開課題2 BGMを再生する
GameManagerのInspectorにアタッチしたAudio SourceのAudio Clipスロットに、Assets>UnityPlayGround_Reference>AudioフォルダにあるBGM.mp3をドラッグ&ドロップしてアタッチすると、BGMを再生させられる。このときPlay On Awakeにチェックすると再生ボタンをクリックした直後からBGMが再生される。オフの場合は別途BGMを再生させるスクリプトが必要になる。また、Loopsにチェックすると自動的に繰り返し再生される。なお、ゲームオーバー時に別のジングルを再生するなどの高度な演出を行う場合も、別途スクリプトを作成する必要がある。ワンポイントアドバイス
Unityで音を鳴らすにはAudio SourceスクリプトとAudio Listenerスクリプトという二種類のスクリプトが必要になる。Audio Sourceスクリプトは音が発せられるオブジェクトにアタッチし、そこから発せられる音がAudio Listerスクリプトに集約されて、実際に音が鳴る仕組みだ。
そのためAudio Sourceスクリプトは同じシーン上で複数のオブジェクトにアタッチされることも少なくない。これに対してAudio Listenrスクリプトは1シーンにつき1つしかアタッチされず、通常はMainCameraコンポーネントにアタッチされている。
また、3Dゲームと違って2Dゲームでは音の立体感が求められないため、作例のように空のオブジェクト(ここではGameManager)に1つだけアタッチされ、外部のオブジェクトから関数として呼び出されて使用されることも多い。ConditionKeyPressとLoadLevelAction
ConditionKeyPressはキーボードの特定のキーの状態を検出するスクリプトです。「キーを押した時」「キーを離した時」「キーを押している間中、ずっと」という3つの状態を検出できます。
Happen Only Once:オンにすると1度だけキーの状態を検出します。
Key To Press:検出するキーを選択できます。
Event Type:「キーを押した時」「キーを離した時」「キーを押している間中、ずっと」を切り替えられます。
LoadLevelActionスクリプトはUnityのシーンファイルを呼び出すスクリプトです。通常Unityではシーンファイルごとにステージを分けて作りますので、あるステージの終了条件を達成したら、次のステージに移行する、といった処理が可能です。また、ゲームの途中からゲームを初期状態に戻したりすることもできます。ただし、このスクリプトを使用するには事前にFile>Build Settingsでシーンファイルを登録しておく必要があります。
Scene to load:呼び出すシーンファイルを選ぶ。RELOAD LEVELの場合は現在のシーンを最初からやり直す。それでは、この2つのスクリプトを組み合わせて、ゲームの途中から初期状態に戻す仕組みを作ってみましょう。
BSキーを押すとゲームの途中から初期状態に戻る
2:Build Settingsウィンドウが開くので、プロジェクトエリアからCondition.unityファイルをドラッグ&ドロップするか、Add Open Sceneをクリックして、現在のシーンファイルを登録する。その後、「✕」ボタンをクリックしてウィンドウを閉じる。
3:HierarchyからGameManagerを選択し、InspectorでAdd Componentから「Condition Key Press」を絞り込み検索してアタッチする。
4:アタッチされたCondition Key PressコンポーネントのKey To Pressメニューをクリックして開く。
- 投稿日:2020-11-23T12:05:43+09:00
Unity PlayGround Referenceガイド②
Unity Playgroundリファレンスガイド日本語訳版の内容をもとに、スクリプトの内容を一つずつ確認していきます。
Gameplay scripts(ゲームプレイスクリプト)
ゲームプレイスクリプトは、ゲームプレイ効果を生み出すための様々な種類のスクリプトです。これらはゲーム内の条件に左右されることなく、単独で動作します。
ObjectCreatorArea
ObjectCreatorAreaスクリプトは、長方形の領域にプレハブから新しいオブジェクトを生成するスクリプトです。このスクリプトが機能するには、インスタンスが表示される領域を定義するBoxCollider2Dコンポーネントが必要です。
Prefab To Spawn:発生させるプレファブをドラッグ&ドロップで登録します。
Spawn Interval:オブジェクトの生成間隔を秒単位で指定できます。エネミーを自動的に創り出す
1:プロジェクトエリアのツリーからAssets>UnityPlayGround_Reference>Conditionと進み、Condition.unityをクリックします。HierarchyのルートにConditionが表示されます。
2:Hierarchyで右クリックし、メニューからCreate Emptyを選択します。
3:HierarchyでCreate Emptyを選択し、名前をEnemySpawnに変更します。その後、Transformで座標をX=7.5、Y=0とします。
4:EnemySpawnのInspectorでAdd Componentをクリックし、「ObjectCreateArea」を絞り込み検索してアタッチします。
5:EnemySpawnにObjectCreateAreaコンポーネントと同時に、Box Collider 2Dコンポーネントもアタッチされます。Box Collider 2DコンポーネントのSize欄でX=1、Y=10と入力します。シーンビュー上で緑色のコライダーの枠が上下方向に拡張されます。このエリアからプレファブがランダムに生成されます。最後にIs Trigerをオンにしましょう。
6:続いて生成されるプレファブを確認しましょう。プロジェクトエリアでBeeプレファブを選択します。すでにRigidbody 2Dコンポーネント、AutoMoveコンポーネント、Circle Collider 2Dコンポーネントがアタッチされて、必要な設定も終了した状態になっています。
7:プロジェクトエリアからBeeプレファブをEnemySpawnのObjectCreateAreaコンポーネントにあるPrefab To Spawnスロットにドラッグ&ドロップします。
8:再生ボタンをクリックして、Beeがランダムに生成されて左に移動することを確認しましょう。Object Shooter
ObjectShooterスクリプトは、キー(デフォルトではSpace)を押したときにプレハブを生成して打ち出せるスクリプトです。このスクリプトを使用して、さまざまな攻撃を繰り出せます(もっと平和にテニスボールを打ち出しても良いです)。BulletAttributeスクリプトと併用すると手軽にスコアシステムを作ることができます。
多くの場合、このスクリプトを空のオブジェクトに割り当て、それを何らかのグラフィックスを持つ別のオブジェクトにペアレント化して使用します。このようにすることで、発射体の発射位置を正確に制御できます。
Prefab To Spawn:スロットに指定したプレファブを発射する。
Key To Press:プレファブを発射するキーを指定する。
Creation Rate:キーが押しっぱなしの場合、何秒おきに新しいプレファブを打ち出すか指定できる。
Shoot Speed:打ち出されたプレファブの初速を設定できる。
Shoot Direction:プレファブを打ち出す方向を指定できる。
Relative To Rotaion:オンにすると打ち出された方向に応じてプレファブの向きを変えられる。爆弾を投射する
キャラクターの足場を作る
1:はじめに地面を作ろう。Hierarchyで右クリックし、Create Emptyを選択する。
2:新しく作られたGameObjectを選択し、Inspectorで名称をGroundに変更する。その後、タグをメニューからGroundに変更する。このタグ設定を忘れるとZombieeのジャンプがおかしくなるので注意。
3:GroundのInspectorでTransformコンポーネントのPositionをX=0、Y=-5.5に変更する。次にAdd ComponentでBox Collider 2Dコンポーネントを絞り込み検索し、アタッチする。
最後にBox Collider 2DのサイズをX=40、Y=1とする。これで地面の下に長方形の緑色のコライダーの枠が表示される。これが見えない当たり判定となり、地面の役割をはたす。キャラクターの配置
1:プロジェクトエリアからZombieeプレファブをHierarchyにドラッグ&ドロップする。その後、シーンビュー上で位置を調整する。すでにRigidbody 2DやBox Collider 2Dなど、最低限のスクリプトはアタッチされている。
2:再生ボタンをクリックして、Zombieeを移動したり、ジャンプしたりできるか確認しよう。なお、本バージョンでは矢印キーの上キーがジャンプに割り当てられているので注意してほしい。爆弾アイテムの投射
1:続いてスペースキーを押すと爆弾が右方向に射出されるようにスクリプトを組んでいこう。まずプロジェクトエリアからZombieeを選択し、Inspectorで「Open Prefab」をクリックする。
2:HierarchyのZombieeオブジェクトで右クリックし、Create Emptyを選択する。
3:Zombieeオブジェクトの子としてGameObjectが設定されたことを確認しよう。次にGameObjectを選択し、Inspectorで「Add Component」をクリックする。その後、Object Shooterを絞り込み検索してアタッチする。
4:GameObjectのInspectorでTransformコンポーネントから、PositionをX=1.2、Y=1.2、SizeをX=0.1、Y=0.1に設定する。これでZombieeの右上からアイテムが射出されるようになる。
5:プロジェクトエリアのBombプレファブをObject ShooterコンポーネントのPrefab To Spawnスロットにドラッグ&ドロップする。その後、「<」ボタンでシーンビューに戻る。
7:再生ボタンをクリック後、スペースキーを押したら爆弾が投射されるのを確認しよう。Pick Up And Hold
PickUpAndHoldスクリプトは何かを拾ったり、落としたりする能力をキャラクターに与えるために使用されます。 ConditionAreaスクリプトと連携させて、オブジェクトを拾って特定の場所まで持っていくようなゲームプレイを作ることができます。
オブジェクトを「ピックアップ可能」にするには、そのオブジェクトにPickupタグを割り当て、任意のCollider2Dを指定する必要があります。Pickup Key:アイテムを拾うためのキーを指定する。
Drop Keyは:アイテムを落とすためのキーを指定する。
Pick Up Distance:オブジェクトがプレイヤーから拾い上げられるまでの最大距離を指定する。サッカーボールを持ち運ぶ
1:はじめにHierarchyでEnemySpawnを選択し、Inspectorでチェックボックスをオフにしておこう。これでBeeが一時的に出現しなくなる。
2:プロジェクトエリアからFootballを選び、Hierarchyにドラッグ&ドロップする。InspectorでタグがPickupになっているか確認しよう。これが別のタグになっていたり、タグがついていなかったりしたら、アイテムを拾うことはできない。
3:プロジェクトエリアのZombieeプレファブをクリックし、Inspectorで「Open Prefab」をクリックする。
4:ZombieeプレファブのInspectorから「Add Component」をクリックし、「Pick Up And Hold」スクリプトを絞り込み検索してアタッチする。
5:Pick Up And HoldコンポーネントでPick Up Distanceを3に設定し、「<」ボタンでシーンビューに戻る。
6:再生ボタンをクリックして、ゾンビーを動かしてサッカーボールに当たると、サッカーボールが転がっていくか確認しよう。
7:続いてサッカーボールの近くでBキーを押すと、ゾンビーとサッカーボールがバインドされ、一緒に移動できるか確認しよう。最後にBキーを押してサッカーボールが離れれば成功だ。また、Bキーを押しながら、HierarchyでZombieeとFootballの親子関係が切り替わる様を確認しよう。Timed Self Destruct
TimedSelfDestructスクリプトは、時間経過にともなってオブジェクトを自動的に削除するためのスクリプトです。武器から発射されたアイテムや、ランダムに生成された敵キャラクターで、シーンが乱雑になったり、メモリ不足でエラーが発生したりすることを防ぐために使用します。
Time to Destruction:オブジェクトが生成後、消滅するまでの秒数爆弾とエネミーを自動的に削除する
1:はじめにHierarchyからFootballインスタンスを選択し、Inspectorでチェックボックスをオフにしておこう。これで一時的にサッカーボールが表示されなくなる。
2:プロジェクトエリアからBeeプレファブを選択し、Inspectorで「Open Prefab」をクリックする。
3:BeeプレファブのInspectorから「Add Component」をクリックし、「Timed Self Destruct」スクリプトを絞り込み検索してアタッチする。
4:InspectorのTimed Self DestructコンポーネントでTime to Destructionの値を3にしよう。その後「<」ボタンでシーンビューに戻ろう。
5:これと同じことをBombプレファブにも行う。まずプロジェクトエリアでBombプレファブを選択し、Inspectorで「Open Prefab」をクリックし・・・
6:BombプレファブのInspectorで「Add Component」をクリック後、「Timed Self Destruct」スクリプトを絞り込み検索して・・・
7:最後にInspectorのTimed Self DestructコンポーネントでTime to Destructionの値を3にしよう。その後「<」ボタンでシーンビューに戻る。
8:その後、HierarchyでEnemySpawnを選択し、Inspectorでチェックボックスをオンんする。
9:再生ボタンをクリックして、BeeやBombが一定時間で消失することを確認しよう。生成されたオブジェクトはHierarchyに表示されるが、一定数以上は増えない(自動的に消える)ことがわかる。Attributes(アトリビュート)
Attributesはオブジェクトが持つ性質を定義するスクリプトです。タグに似た役割を持っていますが、タグとは異なり、追加データを含めることができます。
Bullet Attribute
BulletAttrbuteがアタッチされたオブジェクトが、DestroyForPointsAttributeがアタッチされたオブジェクトに接触すると、BulletAttrbuteがアタッチされたオブジェクトを発射したプレイヤーはポイントを獲得できます。獲得したポイントはUserinterfaceプレファブで画面上に表示させられます。
爆弾で攻撃するための準備
1:プロジェクトエリアのBombプレファブを選択し、Inspectorで「Open Prefab」をクリックしよう。
2:BombプレファブのInspectorで「Add Component」から「Bullet」を絞り込み検索し、アタッチします。
3:アタッチできたら「<」ボタンでシーンビューに戻りましょう。
4:プロジェクトエリアのツリーからAssets>Prefabs>Userinterfaceを選択し、Hierarchynドラッグ&ドロップします。
5:再生ボタンをクリックし、画面にUIが表示されることを確認します。なお、この時点では表示内容は変化しません。Destroy For Points Attribute
DestroyForPointsAttributeスクリプトはBulletAttributeスクリプトとセットで使います。BulletAttributeスクリプトが付いているオブジェクトが、DestroyForPointsAttributeに接触した場合、オブジェクトが破壊され、BulletAttributeスクリプトがついたオブジェクトを発射したプレイヤーにポイントを与えます。
爆弾でエネミーを倒してポイントを稼ぐ
1:プロジェクトエリアからZombieeプレファブを選択し、Inspectorから「Open Prefab」をクリックする。
2:HierarchyからGameObjectを選択し、タグを「Player」に変更する。これでZombieeとGameObjectの両方にPlayerタグが設定されたことになる。タグを設定し終わったら「<」ボタンでシーンビューに戻る。
3:プロジェクトエリアからBeeプレファブを選択し、Inspectorから「Open Prefab」をクリックする。
4:InspectorのAdd Componentから「Destroy For points」を絞り込み検索し、アタッチする。
5:Destroy for pointsコンポーネントが表示されたら、「<」ボタンでシーンビューに戻る。なお、この時「Points Worth」の値を変えると、プレファブが破壊された時に得られるポイントを変更できる。
7:Bombを発射して、Beeに当ててみよう。Bombが当たればBeeが消失し、スコアが1増えれば成功だ。その後、Beeを5匹撃破したら「Player 1 wins!」と表示されるか確認しよう。ワンポイントアドバイス
UserinterfaceプレファブのUI ScriptコンポーネントにあるScre To Winの値を変えると「Player 1 wins!」を表示するために必要な獲得ポイントが変化する。Collectable Attribute
Player(またはPlayer 2)タグがついたオブジェクトが、CollectableAttributeスクリプトがついたオブジェクトと接触すると、プレイヤーにポイントが付与される。
Points Worth:アイテムに触れたときに得られるポイントアイテムを回収する
1:はじめにHierarchyでEnemySpawnを選択し、Inspectorでチェックボックスをオフにしておこう。これで一時的にBeeが出現しなくなる。
2:プロジェクトエリアでStarプレファブを選択し、InspectorでOpen Prefabをクリックする。
3:Star PrefabのInspectorでAdd Componentから「Collectable」を絞り込み検索し、アタッチする。
4:Collectableコンポーネントがついたら、「<」ボタンをクリックしてシーンビューに戻る。このとき、Points Worthの値を変えると得られるポイントを変更できる。
5:StarプレファブをHierarchyにドラッグ&ドロップし、インスタンスの場所をシーンビュー上で調整する。これを5回繰り返す。
※:再生ボタンをクリックし、Zombieeを操作して、Starに触れたらStarが消えてポイントが増えるか確認しよう。5つStarをとった時、「Player 1 wins!」が表示されたら成功だ。Health System Attribute
HealthSystemAttributeスクリプトはModifyHealthAttributeスクリプトと連携して機能し、体力システムとして機能します。体力を持つオブジェクトはプレイヤーキャラクターだけに留まらず、敵キャラクターや、一定ダメージを与えると破壊される壁など、オブジェクト全般にわたります。Player(またはPlayer 2)タグのついたオブジェクトに本スクリプを付与し、Userinterfaceプレファブと連携させると、体力が0になった時点でゲームオーバーのメッセージを表示させられます。なお、本スクリプトはModifyHealthAttributeスクリプトと連携して使用します。ModifyHealthAttributeを持つオブジェクトは、HealthSystemAttributeを持たないオブジェクトには影響しません。
Health:オブジェクトに付与される体力アバターに体力システムをつける
Starを階層構造で整理して非表示にする
1:はじめにシーンビュー上のStarをすべて非表示にしよう。一つずつチェックボックスをオフにしてもいいが、GameObjectにまとめることで効率的に管理できる。はじめにHierarchy上で右クリックし、Create Emptyを選択する。
2:作成したGameObjectをクリックし、Inspectorで名前をStarに変更する。
3:Hierarchy上のStarオブジェクトを先ほど作成した空のStarオブジェクトにまとめて移動させる。
4:親のStarオブジェクトを選択し、Inspectorでチェックボックスをオフにする。Zombieeの体力システムを作る
1:プロジェクトエリアでZombieeを選択し、InspectorでOpen Prefabをクリックしよう。
2:ZombieeのプレファブにあるInspectorのAdd Componentで「Health System」を絞り込み検索し、アタッチする。
3:「<」ボタンをクリックしてシーンビューに戻る。なお、このときHealth SystemコンポーネントのHealthの値を変えると、デフォルトの体力値を変更できる。Modify Health Attribute
Modify Health AttributeスクリプトはHealthSystemAttributeスクリプトとセットで使用し、オブジェクトの体力を増減させられます。これにより敵キャラクターを作ることも、ポーションなどを作ることもできます。
Destroy When Activated:オンにすると効果が発生したときにオブジェクトが削除される。
Health Change:体力の変化値を調整できる。マイナスにすると体力が減り、プラスにすると体力が増える。エネミーにぶつかったら体力を減らす
1:はじめにHierarchyでEnemySpawnを選択し、Inspectorでチェックボックスをオンにしよう。
2:プロジェクトエリアのBeeプレファブを選択し、Open Prefabをクリックする。
3:BeeプレファブのInspectorからAdd Componentで「Mdify Health」を絞り込み検索し、アタッチする。
4:Modify HealthコンポーネントでDestroy When Activeをオンにして、「<」ボタンをクリックし、シーンビューに戻る。このときHealth Changeの値を変えると、ダメージ値を変更できる。
5:シーンビューに戻ったら、さっそく再生ボタンをクリックしよう。
6:ZombieeがBeeに当たったらHealthが1ずつ減り、Healthが0になった時にGameoverと表示されれば成功だ。一方でBombを投げてBeeを破壊し、5匹倒したらゲームクリアとなる。これでシンプルなアクションシューティングゲームが完成した。Resource
Resourceスクリプトはプレイヤーが一時的に蓄え、消費するアイテムを管理できるスクリプトです。Player(またはPlayer 2)タグのついたオブジェクトが、Resourceスクリプトがついたオブジェクトに触れると、Resourceスクリプトがついたオブジェクトが非表示になり、インベントリの数字が増加します。他のスクリプトと組み合わせて、クラフトシステムを作ったり、鍵のかかった扉や宝箱を作ったりすることができます。
Type of Resorce:リソースの種類を変更できます。
Ammount:アイテムを取った時のリソースの増加量を設定できます。マイナスにするとリソースが減少します。
Add/Remove types:リソースの種類を増やしたり、減らしたりできます。
+を押して新しいリソースを設定でき、-を押して既存のリソースを減らせます。アイテムを回収してインベントリに表示させる
1:はじめにHierarchyでEnemySpawnを選択し、Inspectorでチェックボックスをオフにする。これで一時的にBeeが発生しなくなる。
2:プロジェクトエリアのCoinプレファブを選択し、InspectorのOpen Prefabをクリックする。
3:Coinプレファブを開き、InspectorのAdd Componentで「Resource」と入力し、絞り込み検索を行ってアタッチする。
4:ResourceコンポーネントのType of Resorceで「Coin」を選び、「<」ボタンでシーンビューに戻る。このときAmmountの値を変更すれば、アイテム入手時に得られる値を変えられる。
5:続いてCoinのインスタンスを作るわけだが、今回は最初から階層構造を設定しておこう。まずHierarchy上で右クリックし、「Create Empty」を選択する。
6:作成されたGameObjectを選択し、Inspectorで名前を「Coin」とする。
7:プロジェクトエリアのCoinプレファブをHierarchyのCoinオブジェクトの子供になるようにドラッグ&ドロップする。これを3回繰り返す。
8:作成されたCoinのインスタンスをシーンビュー上で適性に配置する。
- 投稿日:2020-11-23T01:44:30+09:00
[Unity]ヒットストップを作ってみる
ヒットストップとは
ゲームで、攻撃がヒットした時に一瞬ゲームの流れが止まるようなあれです。スマブラのファルコンの膝や、モンハンの大剣などがイメージしやすいかなと。大技に多い印象です。
やってみる
前提
- 敵と、プレイヤーに
Box Collider
が付与されている- 敵に
Enemy
というタグを設定する- プレイヤーの右足に
RightFoot
というタグを設定する- プレイヤーの攻撃モーションで、右足が敵に当たる
今回使ったもの
* プレイヤーのAsset : https://assetstore.unity.com/packages/3d/animations/hq-fighting-animation-free-33478
* エネミーのAsset : https://assetstore.unity.com/packages/3d/characters/animated-witch-and-dragon-monster-49955スクリプト
プレイヤーのスクリプトを作成し、以下の記述を付け加えます。
敵と接触した時に発火されるOnCollisionEnter
を使います。Animator animator; private string enemyTag = "Enemy"; private int count = 0; private bool isHitStop = false; void Start() { animator = GetComponent<Animator>(); } void Update() { // ヒットストップ中ならば if (isHitStop) { count += 1; // カウントが20いったなら、ヒットストップを元に戻す if (count > 20) { isHitStop = false; animator.speed = 1; } } } void OnCollisionEnter(Collision collision) { // 敵と接触したならば if (collision.collider.tag == enemyTag) { Debug.Log("敵と接触した!"); animator.speed = 0.01f; // アニメーション速度を遅くし、ヒットストップを演出する isHitStop = true; count = 0; } }これで、プレイヤーが敵と当たった時にヒットストップするようになります。
敵にも同じように判定を付けてあげれば、敵側も止まるようになります。こんな感じ
- 投稿日:2020-11-23T00:28:54+09:00
「Unity と iPad で作る AR VFX の世界」のRCam2を使用する方法
はじめに
この記事では、高橋啓治郎さんが開発したRCam2を使用する手順を紹介します。
RCam2を使用した動画を掲載します。
「Unity と iPad で作る AR VFX の世界」のRCam2を使用テストRCam2のGitHubリポジトリです。
https://github.com/keijiro/Rcam2
ReadmeにRCam2を使用する手順が記載されていますが、私が分からなかった部分を含めて説明します。こちらにRCam2がどのようなものであるかYouTubeにて紹介してくださっています。
https://www.youtube.com/watch?v=IqE14T3hf7Y&list=LL&index=8目次
必要な機材
- LiDARを搭載したiPad Pro
- iPhone 12 Proで動作するかは未検証です。
- Macのパソコン
- XCodeを使用してiOS向けにビルドするために必要です。
- Windowsのパソコン
- iOSのアプリから動画などのデータを取得してエフェクトを表示する際に必要です。
- Wi-Fi
- 同じWi-Fiに接続してデータを送るために必要です。
- 動画をリアルタイムで送受信できる程度の通信速度が必要です。(遅いと画面がカクカクになります。)
- 公共のWi-FiではパソコンとiPad Proの間でデータを送信することができない問題がありました。
RCam2の環境構築方法
- Macのパソコンで準備すること
- iPad Proアプリの「RcamController」を用意する手順です。
- https://github.com/keijiro/Rcam2/tree/master/RcamController このURLから「RcamController」のUnityプロジェクトをダウンロードします。
- UnityでiOS向けにXCodeプロジェクトをビルド
- XCodeでiPad Proにアプリをビルド
- ※そのままだとビルド時にエラーが発生してしまうので、https://www.ndi.tv/sdk/#download からNDI SDK Software Develop Kitをインストールしてください。
- iPad Proで準備すること
- Windowsのパソコンと同じWi-Fiに繋ぎ、ビルドした「RcamController」のアプリを開いてください。
- Windowsのパソコンで準備すること
- https://www.ndi.tv/sdk/#download からNDI SDK Software Develop Kitをインストールしてください。
- https://github.com/keijiro/Rcam2/releases/tag/v1.0.0 このURLからRcam2-1.0.0.zip をダウンロードし、「RcamVisualizer.exe」を開く。
- 画面左上のドロップダウンに、自身のiPad Proの名前が表示されるので、それを選択してください。
- iPad Proの「RcamController」アプリとWindowsの「RcamVisualizer.exe」がインターネット接続で繋がらないとき
- https://pc-karuma.net/windows-10-firewall-enable-disable/ このURLを参考に、ファイアウォールを無効にするとうまく繋がる場合があります。
- 公共のWi-Fiではないものに変更する。(とあるゲーム会社オフィスのゲスト用のWi-Fiで試そうとしましたが、セキュリティの設定が厳しいことが原因(?)で繋がらないことがありました。)
- イーサネット(有線のインターネットのようなもの)を使用する。(私は検証できていません。)
感想など
- RCam2は様々な設定や他のデバイスが必要となるので使用までに負担がかかってしまいますね…。iPad Pro単体で実行できる同様のアプリが開発できればいいですね。
- iPad ProのLiDARの有用性が見えてきましたね。乗るしかない。このビッグウェーブに…!!
- なにか追記すべきことなどありましたら教えて下さい。m(_ _)m