追加された行はこの色です。
削除された行はこの色です。
オリジナル要素の追加を検討し、実装にチャレンジしましょう。
----
*設計
**1.速度アップの効果・終了条件を考える
速度アップの効果・終了条件を設計し、その条件を満たした際に速度を元の速度に戻す処理を実装します。
速度アップの効果を適用するためには、どのようにすればゲーム内で表現できるか、日本語で設計を考えて書き出します。
頭の中でイメージを作り、それを言語化していくことが、プログラムを書いていくための大きなポイントです。
箇条書きでよいので、やりたいことを書き出し、精査して順番を考えていきます。
日本語で書き出すことができたら、つついて、速度の情報を管理しているクラスがあるかを確認する部分からスタートします。
まだ速度の情報を管理していないのであれば、新しく変数を追加する必要がありますし、それをどのクラスに書き足すかも考えていく必要があります。
すでにあるのであれば、そのクラスを利用します。
次に、終了条件を検討します。
一般的には、一定時間経過後、が速度アップの終了条件となるゲームが多いです。
仮にこの条件を終了条件とするならば、この一定時間の経過という部分をどのようにすればプログラムとして表現できるかを考えます。
また、速度アップのアイテムを重複して獲得した場合の処理についても検討しておきます。
すでに速度アップのアイテムを獲得している場合に、さらに速度がアップするのか、あるいは重複はしないのか、という効果部分と、
効果が持続する時間の延長が行われるのか、行われる場合には加算式なのか、初期値に戻す方式なのか、といった細かい部分まで決定しておきます。
このようにして設計部分でしっかりとアイテムの内容を練っておくことで、次のロジックを考えていくことが可能になります。
そして忘れてはならないのが、速度アップの効果が終了したあとの処理です。
速度アップの効果が終わる、ということは、最初の速度に戻ることになりますので、どのようにすれば元の速度に戻せるかを検討します。
----
**2.効果の適用方法と終了条件をロジック化し、必要な情報は何かを考える
効果と終了条件は決まりましたので、続いて、この条件のロジックを組むためには、どんな情報が必要となるかを何かを考えていきます。
「プレイヤーの移動速度が一時的に上がる」ということは「プレイヤーの移動速度を管理している変数を変更する」と考えることが出来ます。
この処理を考えたとき、オブジェクトの情報を管理できていなければ条件や書式として組み立てることが出来ません。
つまり、ゲームシーン内にプレイヤーの移動速度の情報があり(管理しているクラスが存在し)、新しい移動速度を設定しているクラスがなければ書式として構築できないためです。
アイテムの効果として速度アップの効果を考えるのであれば、「速度アップのアイテムを獲得したら」という条件も必要になります。
アイテムの獲得について Item タグを持つオブジェクトを作成した教材を参考にしましょう。獲得処理に関しては、以前に作成した、HPItem スクリプトなどが役に立つでしょう。
この処理内では、アイテムにプレイヤーが侵入したらという処理が記載されていますし、効果を適用する処理も記載されていますので、それを応用してください。
<応用する>
=|PERL|
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
th = GameObject.Find("Tank").GetComponent<TankHealth>();
// TODO ここで効果を書いているので、ここを「速度アップ」に変える
// AddHP()メソッドを呼び出して「引数」にrewardを与えている。
//th.AddHP(reward);
// アイテムを破壊
Destroy(gameObject);
// effectを生成し、指定時間後に破壊するようにセットしておく
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 0.5f);
// SE 再生
AudioSource.PlayClipAtPoint(getSound, transform.position);
}
}
||=
今回は条件を満たしたら(プレイヤーがアイテムを獲得したら)、速度アップの効果を適用することが目的ですので、
上記の HpItem の処理を参考に、速度アップの効果を適用するための変数や、効果を考えてみましょう。
あとは適用した速度アップの効果を「一定時間後に戻す」処理、および、速度アップの効果適用中に同じ速度アップを獲得した場合の処理が必要になります。
これらについても、どのように処理を管理をしていくかを考えていきます。
----
**3.処理を順番に実装する
スクリプトに処理を記述する際には、日本語のコメントを事前に書いておいて、それを元にプログラムを書いていく手法がおすすめです。
ロジックを構築しやすいですし、コメントがそのまま残り、処理の書き洩らしを防ぐことが出来るためです。
----
*実装手順
設計を元に、以下の手順で実装を行います。まずは自分でロジックを考えて実装に挑戦してみてください。
また、ここにある実装例の処理は必要最低限の処理になりますので、自分なりにアレンジを自由に行ってください。
=|PERL|
1.TankMovement スクリプトを修正して、現在の速度、初期速度、持続時間をカウントするための変数、速度をアップさせる処理(BoostMoveSpeed メソッド)、速度を戻す処理(ResetMoveSpeed メソッド)を追加する
2.HpItem を参考に SpeedUpItem スクリプトを作成して、速度アップ用のアイテムを取得した際に TankMovement の BoostMoveSpeed メソッドを呼び出す処理を追加する
3.ゲームを実行して動作を確認する
||=
----
*1.TankMovement スクリプトを修正して、現在の速度、初期速度、持続時間をカウントするための変数、速度をアップさせる処理(BoostMoveSpeed メソッド)、速度を戻す処理(ResetMoveSpeed メソッド)を追加する
速度のロジックを構築するために必要な変数を1つ追加します。
敵の数(残りの数)を管理するために、int 型の enemyCount 変数を用意します。
この値には、Start メソッド内でEnemy タグを持つ敵を配列で取得した後に配列の長さ(最大値)を代入します。
何故ならば、この配列は敵の情報が代入されており、敵の数分だけ要素を持っているからです。
またこの enemyCount 変数は private 修飾子であるため、外部のスクリプトからは直接参照して増減処理を行うことが出来ません。
外部のスクリプトから呼び出してもらうために public の CalculateEnemyCount メソッドを用意して、減算を行う際にはこのメソッドを利用してもらうようにします。
このメソッド内では enemyCount 変数の減算後に、敵の数がクリアの条件を満たしているか = enemyCount 変数の値が 0 かどうかを判定するようにしていますので、
敵の数のカウントダウンとクリアの判定を一緒に行うようにロジックを組んでいます。
''TankMovement.cs''
[+] <= クリックすると開きます。
=|BOX|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class TankMovement : MonoBehaviour
{
public float moveSpeed;
public float turnSpeed;
////* ここから追加 *////
public float currentDuration;
private float defaultMoveSpeed;
////* ここまで *////
private Rigidbody rb;
private float movementInputValue;
private float turnInputValue;
void Start()
{
rb = GetComponent<Rigidbody>();
defaultMoveSpeed = moveSpeed;
}
void Update()
{
TankMove();
TankTurn();
currentDuration -= Time.deltaTime;
if (currentDuration <= 0)
{
currentDuration = 0;
ResetMoveSpeed();
}
}
// 前進・後退
void TankMove()
{
movementInputValue = Input.GetAxis("Vertical");
Vector3 movement = transform.forward * movementInputValue * moveSpeed * Time.deltaTime;
rb.MovePosition(rb.position + movement);
}
// 旋回
void TankTurn()
{
turnInputValue = Input.GetAxis("Horizontal");
float turn = turnInputValue * turnSpeed * Time.deltaTime;
Quaternion turnRptation = Quaternion.Euler(0, turn, 0);
rb.MoveRotation(rb.rotation * turnRptation);
}
////* ここからメソッドを2つ追加 *////
public void BoostMoveSpeed(float speedupRate, float duration)
{
moveSpeed *= speedupRate;
currentDuration += duration;
Debug.Log(moveSpeed);
}
private void ResetMoveSpeed()
{
moveSpeed = defaultMoveSpeed;
}
////* ここまで *////
}
||=
[END]
----
*2.HpItem を参考に SpeedUpItem スクリプトを作成して、速度アップ用のアイテムを取得した際に TankMovement の BoostMoveSpeed メソッドを呼び出す処理を追加する
HpItem を参考に SpeedUpItem スクリプトを作成してみましょう。
どのような処理になっているのか、記述しながらコメントを書いて理解を深めましょう。
''SpeedUpItem.cs''
[+] <= クリックすると開きます。
=|BOX|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpeedUpItem : MonoBehaviour
{
public GameObject effectPrefab;
public AudioClip getSound;
public float speedupRate = 1.2f;
public float duration = 5.0f;
private TankMovement tm;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
tm = GameObject.Find("Tank").GetComponent<TankMovement>();
tm.BoostMoveSpeed(speedupRate, duration);
Destroy(gameObject);
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 0.5f);
AudioSource.PlayClipAtPoint(getSound, transform.position);
}
}
}
||=
[END]
----
*3.ゲームを実行して確認する
以上で実装は終了です。ゲームを実行して、速度アップの効果が正常に制御されているかを確認します。
まずは速度アップのアイテムに侵入してみてください。獲得処理が正常に動作すれば、プレイヤーの速度がアップします。
同時に速度アップのアイテムが破壊され、エフェクトと SE が再生されます。
ほかのアイテムと同様、プレイヤー以外のオブジェクトが侵入した場合には効果が適用されないことも確認します。
プレイヤーの速度アップについては、画面上での確認のみではなく、
インスペクターを確認して変数の値が変更されていることも確認が必要です。
プログラムをしっかりと理解しておくためにも、内部データがどのように動いているかを常に見ておくようにしてください。
また Debug.Log メソッドを活用しておくことで、処理を Console ビューにも表示できます。この方法も大変有効です。
Console ビュー画像
&ref(https://image01.seesaawiki.jp/i/o/i-school-memo/jAC6HcfdBf-s.png)
----
そのままゲームを継続し、一定時間を経過させてください。
速度が元の速度に戻れば、こちらの処理も成功です。インスペクターを確認して変数の値が変更されていることも確認しましょう。
あとは、速度アップ中に、続けて同じ速度アップの獲得したときに想定している挙動になるかもチェックしてください。
自分で作成した処理ですので、作成した自分が一番理解している必要があります。
どのような処理があり、それに対して、どのような挙動が正しいのか、デバッグする内容も含めて書き出しておくとよいでしょう。
----
以上でこの手順は終了です。おつかれさまでした。
----
*設計
**1.速度アップの効果・終了条件を考える
速度アップの効果・終了条件を設計し、その条件を満たした際に速度を元の速度に戻す処理を実装します。
速度アップの効果を適用するためには、どのようにすればゲーム内で表現できるか、日本語で設計を考えて書き出します。
頭の中でイメージを作り、それを言語化していくことが、プログラムを書いていくための大きなポイントです。
箇条書きでよいので、やりたいことを書き出し、精査して順番を考えていきます。
日本語で書き出すことができたら、つついて、速度の情報を管理しているクラスがあるかを確認する部分からスタートします。
まだ速度の情報を管理していないのであれば、新しく変数を追加する必要がありますし、それをどのクラスに書き足すかも考えていく必要があります。
すでにあるのであれば、そのクラスを利用します。
次に、終了条件を検討します。
一般的には、一定時間経過後、が速度アップの終了条件となるゲームが多いです。
仮にこの条件を終了条件とするならば、この一定時間の経過という部分をどのようにすればプログラムとして表現できるかを考えます。
また、速度アップのアイテムを重複して獲得した場合の処理についても検討しておきます。
すでに速度アップのアイテムを獲得している場合に、さらに速度がアップするのか、あるいは重複はしないのか、という効果部分と、
効果が持続する時間の延長が行われるのか、行われる場合には加算式なのか、初期値に戻す方式なのか、といった細かい部分まで決定しておきます。
このようにして設計部分でしっかりとアイテムの内容を練っておくことで、次のロジックを考えていくことが可能になります。
そして忘れてはならないのが、速度アップの効果が終了したあとの処理です。
速度アップの効果が終わる、ということは、最初の速度に戻ることになりますので、どのようにすれば元の速度に戻せるかを検討します。
----
**2.効果の適用方法と終了条件をロジック化し、必要な情報は何かを考える
効果と終了条件は決まりましたので、続いて、この条件のロジックを組むためには、どんな情報が必要となるかを何かを考えていきます。
「プレイヤーの移動速度が一時的に上がる」ということは「プレイヤーの移動速度を管理している変数を変更する」と考えることが出来ます。
この処理を考えたとき、オブジェクトの情報を管理できていなければ条件や書式として組み立てることが出来ません。
つまり、ゲームシーン内にプレイヤーの移動速度の情報があり(管理しているクラスが存在し)、新しい移動速度を設定しているクラスがなければ書式として構築できないためです。
アイテムの効果として速度アップの効果を考えるのであれば、「速度アップのアイテムを獲得したら」という条件も必要になります。
アイテムの獲得について Item タグを持つオブジェクトを作成した教材を参考にしましょう。獲得処理に関しては、以前に作成した、HPItem スクリプトなどが役に立つでしょう。
この処理内では、アイテムにプレイヤーが侵入したらという処理が記載されていますし、効果を適用する処理も記載されていますので、それを応用してください。
<応用する>
=|PERL|
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
th = GameObject.Find("Tank").GetComponent<TankHealth>();
// TODO ここで効果を書いているので、ここを「速度アップ」に変える
// AddHP()メソッドを呼び出して「引数」にrewardを与えている。
//th.AddHP(reward);
// アイテムを破壊
Destroy(gameObject);
// effectを生成し、指定時間後に破壊するようにセットしておく
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 0.5f);
// SE 再生
AudioSource.PlayClipAtPoint(getSound, transform.position);
}
}
||=
今回は条件を満たしたら(プレイヤーがアイテムを獲得したら)、速度アップの効果を適用することが目的ですので、
上記の HpItem の処理を参考に、速度アップの効果を適用するための変数や、効果を考えてみましょう。
あとは適用した速度アップの効果を「一定時間後に戻す」処理、および、速度アップの効果適用中に同じ速度アップを獲得した場合の処理が必要になります。
これらについても、どのように処理を管理をしていくかを考えていきます。
----
**3.処理を順番に実装する
スクリプトに処理を記述する際には、日本語のコメントを事前に書いておいて、それを元にプログラムを書いていく手法がおすすめです。
ロジックを構築しやすいですし、コメントがそのまま残り、処理の書き洩らしを防ぐことが出来るためです。
----
*実装手順
設計を元に、以下の手順で実装を行います。まずは自分でロジックを考えて実装に挑戦してみてください。
また、ここにある実装例の処理は必要最低限の処理になりますので、自分なりにアレンジを自由に行ってください。
=|PERL|
1.TankMovement スクリプトを修正して、現在の速度、初期速度、持続時間をカウントするための変数、速度をアップさせる処理(BoostMoveSpeed メソッド)、速度を戻す処理(ResetMoveSpeed メソッド)を追加する
2.HpItem を参考に SpeedUpItem スクリプトを作成して、速度アップ用のアイテムを取得した際に TankMovement の BoostMoveSpeed メソッドを呼び出す処理を追加する
3.ゲームを実行して動作を確認する
||=
----
*1.TankMovement スクリプトを修正して、現在の速度、初期速度、持続時間をカウントするための変数、速度をアップさせる処理(BoostMoveSpeed メソッド)、速度を戻す処理(ResetMoveSpeed メソッド)を追加する
速度のロジックを構築するために必要な変数を1つ追加します。
敵の数(残りの数)を管理するために、int 型の enemyCount 変数を用意します。
この値には、Start メソッド内でEnemy タグを持つ敵を配列で取得した後に配列の長さ(最大値)を代入します。
何故ならば、この配列は敵の情報が代入されており、敵の数分だけ要素を持っているからです。
またこの enemyCount 変数は private 修飾子であるため、外部のスクリプトからは直接参照して増減処理を行うことが出来ません。
外部のスクリプトから呼び出してもらうために public の CalculateEnemyCount メソッドを用意して、減算を行う際にはこのメソッドを利用してもらうようにします。
このメソッド内では enemyCount 変数の減算後に、敵の数がクリアの条件を満たしているか = enemyCount 変数の値が 0 かどうかを判定するようにしていますので、
敵の数のカウントダウンとクリアの判定を一緒に行うようにロジックを組んでいます。
''TankMovement.cs''
[+] <= クリックすると開きます。
=|BOX|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class TankMovement : MonoBehaviour
{
public float moveSpeed;
public float turnSpeed;
////* ここから追加 *////
public float currentDuration;
private float defaultMoveSpeed;
////* ここまで *////
private Rigidbody rb;
private float movementInputValue;
private float turnInputValue;
void Start()
{
rb = GetComponent<Rigidbody>();
defaultMoveSpeed = moveSpeed;
}
void Update()
{
TankMove();
TankTurn();
currentDuration -= Time.deltaTime;
if (currentDuration <= 0)
{
currentDuration = 0;
ResetMoveSpeed();
}
}
// 前進・後退
void TankMove()
{
movementInputValue = Input.GetAxis("Vertical");
Vector3 movement = transform.forward * movementInputValue * moveSpeed * Time.deltaTime;
rb.MovePosition(rb.position + movement);
}
// 旋回
void TankTurn()
{
turnInputValue = Input.GetAxis("Horizontal");
float turn = turnInputValue * turnSpeed * Time.deltaTime;
Quaternion turnRptation = Quaternion.Euler(0, turn, 0);
rb.MoveRotation(rb.rotation * turnRptation);
}
////* ここからメソッドを2つ追加 *////
public void BoostMoveSpeed(float speedupRate, float duration)
{
moveSpeed *= speedupRate;
currentDuration += duration;
Debug.Log(moveSpeed);
}
private void ResetMoveSpeed()
{
moveSpeed = defaultMoveSpeed;
}
////* ここまで *////
}
||=
[END]
----
*2.HpItem を参考に SpeedUpItem スクリプトを作成して、速度アップ用のアイテムを取得した際に TankMovement の BoostMoveSpeed メソッドを呼び出す処理を追加する
HpItem を参考に SpeedUpItem スクリプトを作成してみましょう。
どのような処理になっているのか、記述しながらコメントを書いて理解を深めましょう。
''SpeedUpItem.cs''
[+] <= クリックすると開きます。
=|BOX|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpeedUpItem : MonoBehaviour
{
public GameObject effectPrefab;
public AudioClip getSound;
public float speedupRate = 1.2f;
public float duration = 5.0f;
private TankMovement tm;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
tm = GameObject.Find("Tank").GetComponent<TankMovement>();
tm.BoostMoveSpeed(speedupRate, duration);
Destroy(gameObject);
GameObject effect = Instantiate(effectPrefab, transform.position, Quaternion.identity);
Destroy(effect, 0.5f);
AudioSource.PlayClipAtPoint(getSound, transform.position);
}
}
}
||=
[END]
----
*3.ゲームを実行して確認する
以上で実装は終了です。ゲームを実行して、速度アップの効果が正常に制御されているかを確認します。
まずは速度アップのアイテムに侵入してみてください。獲得処理が正常に動作すれば、プレイヤーの速度がアップします。
同時に速度アップのアイテムが破壊され、エフェクトと SE が再生されます。
ほかのアイテムと同様、プレイヤー以外のオブジェクトが侵入した場合には効果が適用されないことも確認します。
プレイヤーの速度アップについては、画面上での確認のみではなく、
インスペクターを確認して変数の値が変更されていることも確認が必要です。
プログラムをしっかりと理解しておくためにも、内部データがどのように動いているかを常に見ておくようにしてください。
また Debug.Log メソッドを活用しておくことで、処理を Console ビューにも表示できます。この方法も大変有効です。
Console ビュー画像
&ref(https://image01.seesaawiki.jp/i/o/i-school-memo/jAC6HcfdBf-s.png)
----
そのままゲームを継続し、一定時間を経過させてください。
速度が元の速度に戻れば、こちらの処理も成功です。インスペクターを確認して変数の値が変更されていることも確認しましょう。
あとは、速度アップ中に、続けて同じ速度アップの獲得したときに想定している挙動になるかもチェックしてください。
自分で作成した処理ですので、作成した自分が一番理解している必要があります。
どのような処理があり、それに対して、どのような挙動が正しいのか、デバッグする内容も含めて書き出しておくとよいでしょう。
----
以上でこの手順は終了です。おつかれさまでした。