前回は、ダイヤを消費すると、味方の精霊を増やせるように実装しました。
個人ゲーム開発日報|ダイヤ消費で味方の複製
今回はダイヤ消費で味方の複製を実装します。
今回は、コインの獲得アニメーションを実装します。
コインが獲得コイン数の数字の方に飛んでいく処理
今までは、コインを獲得したらそのコインは消滅していました。
ちょっと味気ないので、獲得したコインは右上の獲得コイン数の場所に飛んでいくようにします。
DOTweenを使ったアニメーション
以下のコードで獲得したコインを飛ばします。
void FlyToCoinCount(GameObject coin)
{
Vector3 targetPosition = coinCountText.transform.position; // コインカウントテキストの位置
coin.transform.DOMove(targetPosition, 0.5f).SetEase(Ease.InOutQuad)
.OnComplete(() =>
{
Destroy(coin);
AddCoin(); // コインを獲得
});
}
このコードを加えれば完成です。
DOTween便利ですね。
全体コードは以下です。
using UnityEngine;
using DG.Tweening;
using TMPro;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public class ClickDamageHandler : MonoBehaviour
{
public GameObject coinPrefab; // コインのプレハブ
public GameObject diamondPrefab; // ダイヤのプレハブ
public GameObject spiritPrefab; // 精霊のプレハブ
public Transform coinSpawnPoint; // コインが飛び出す位置
public Transform spiritSpawnPoint; // 精霊がスポーンする位置
public TMP_Text coinCountText; // コイン獲得数を表示するTextMeshProUGUI
public TMP_Text diamondCountText; // ダイヤ獲得数を表示するTextMeshProUGUI
public Image damageGaugeBackground; // ダメージゲージの背景
public Image damageGaugeFill; // ダメージゲージのフィル
public TMP_Text enemyLifeText; // 敵のライフを表示するTextMeshProUGUI
public Button increaseTapDamageButton; // タップの威力を上げるボタン
public Button increaseSpiritLevelButton; // 精霊のレベルを上げるボタン
public Button addSpiritButton; // 精霊を追加するボタン
private int coinCount = 0; // 獲得したコインの数
private int diamondCount = 0; // 獲得したダイヤの数
private int damageCount = 0; // ダメージ数のカウント
private int enemyLife = 10; // 敵のライフ
private int maxEnemyLife = 10; // 敵の最大ライフ
private int tapDamage = 1; // タップの威力
private Vector3 originalPosition; // オブジェクトの元の位置
private bool isAnimating = false; // アニメーション中かどうかを示すフラグ
private List<GameObject> spirits = new List<GameObject>(); // 精霊のリスト
private SpriteRenderer spriteRenderer; // スプライトレンダラー
void Start()
{
// オブジェクトの元の位置を保存
originalPosition = transform.localPosition;
spriteRenderer = GetComponent<SpriteRenderer>(); // スプライトレンダラーを取得
UpdateCoinCountText(); // 初期表示の更新
UpdateDiamondCountText(); // 初期表示の更新
UpdateDamageGauge(); // 初期表示の更新
UpdateEnemyLifeText(); // 敵のライフの表示を更新
// ボタンにイベントリスナーを追加
increaseTapDamageButton.onClick.AddListener(IncreaseTapDamage);
increaseSpiritLevelButton.onClick.AddListener(IncreaseSpiritLevel);
addSpiritButton.onClick.AddListener(AddSpirit);
}
void OnMouseDown()
{
if (!isAnimating)
{
ReceiveDamage(tapDamage); // 現在のタップダメージを使用
}
}
public void ReceiveDamage(int amount)
{
damageCount += amount; // ダメージ数を増加
enemyLife -= amount; // 敵のライフを減少
LogDamage(); // ダメージ数をコンソールに表示
ShakeObject(); // オブジェクトを揺らす
SpawnCoin(); // コインを生成して飛ばす
UpdateDamageGauge(); // ダメージゲージを更新
UpdateEnemyLifeText(); // 敵のライフの表示を更新
if (enemyLife <= 0)
{
DropDiamondAndRespawnEnemy(); // ダイヤを生成し、敵をリスポーン
}
}
void LogDamage()
{
Debug.Log("Damage: " + damageCount); // コンソールにダメージ数を表示
}
void ShakeObject()
{
// アニメーション中フラグを設定
isAnimating = true;
// 左にもっと動かしてから元の位置に戻す
transform.DOLocalMoveX(originalPosition.x - 0.2f, 0.05f).SetEase(Ease.OutQuad) // 移動の幅を0.2fに設定
.OnComplete(() =>
{
transform.localPosition = originalPosition;
isAnimating = false; // アニメーションが終了したらフラグをリセット
});
}
void SpawnCoin()
{
// コインを生成
GameObject coin = Instantiate(coinPrefab, coinSpawnPoint.position, Quaternion.identity);
// コインを敵キャラクターより上に表示
coin.GetComponent<SpriteRenderer>().sortingOrder = 10;
// コインに飛び出すアニメーションを適用
float dropHeight = Random.Range(-2.0f, -4.0f); // 落下先を2倍に伸ばす
Vector3 peakPosition = new Vector3(
coinSpawnPoint.position.x,
coinSpawnPoint.position.y + 1.0f, // 一度上に上がる
coinSpawnPoint.position.z
);
Vector3 targetPosition = new Vector3(
coinSpawnPoint.position.x + Random.Range(-1.0f, 1.0f), // 横の範囲を広げる
coinSpawnPoint.position.y + dropHeight,
coinSpawnPoint.position.z
);
Sequence coinSequence = DOTween.Sequence();
coinSequence.Append(coin.transform.DOMove(peakPosition, 0.15f).SetEase(Ease.OutQuad)) // 上に上がる動きを2倍速に
.Append(coin.transform.DOMove(targetPosition, 0.25f).SetEase(Ease.InQuad)) // 下に落ちる動きを2倍速に
.OnComplete(() => StartCoroutine(CoinLifetime(coin))); // アニメーション完了時にコインのライフタイムを開始
}
void FlyToCoinCount(GameObject coin)
{
Vector3 targetPosition = coinCountText.transform.position; // コインカウントテキストの位置
coin.transform.DOMove(targetPosition, 0.5f).SetEase(Ease.InOutQuad)
.OnComplete(() =>
{
Destroy(coin);
AddCoin(); // コインを獲得
});
}
public void AddCoin()
{
coinCount++; // 獲得したコイン数を増加
UpdateCoinCountText(); // UIを更新
}
public void AddDiamond()
{
diamondCount++; // 獲得したダイヤ数を増加
UpdateDiamondCountText(); // UIを更新
}
void UpdateCoinCountText()
{
coinCountText.text = "Coins: " + coinCount.ToString(); // コイン数を表示
}
void UpdateDiamondCountText()
{
diamondCountText.text = "Diamonds: " + diamondCount.ToString(); // ダイヤ数を表示
}
void UpdateDamageGauge()
{
float fillAmount = (float)enemyLife / maxEnemyLife;
damageGaugeFill.fillAmount = fillAmount; // ダメージゲージを更新
}
void UpdateEnemyLifeText()
{
enemyLifeText.text = "Life: " + enemyLife.ToString(); // 敵のライフを表示
}
void DropDiamondAndRespawnEnemy()
{
// ダイヤを生成
GameObject diamond = Instantiate(diamondPrefab, coinSpawnPoint.position, Quaternion.identity);
// ダイヤに飛び出すアニメーションを適用
float dropHeight = Random.Range(-2.0f, -4.0f); // 落下先を2倍に伸ばす
Vector3 peakPosition = new Vector3(
coinSpawnPoint.position.x,
coinSpawnPoint.position.y + 1.0f, // 一度上に上がる
coinSpawnPoint.position.z
);
Vector3 targetPosition = new Vector3(
coinSpawnPoint.position.x + Random.Range(-1.0f, 1.0f), // 横の範囲を広げる
coinSpawnPoint.position.y + dropHeight,
coinSpawnPoint.position.z
);
Sequence diamondSequence = DOTween.Sequence();
diamondSequence.Append(diamond.transform.DOMove(peakPosition, 0.15f).SetEase(Ease.OutQuad)) // 上に上がる動きを2倍速に
.Append(diamond.transform.DOMove(targetPosition, 0.25f).SetEase(Ease.InQuad)) // 下に落ちる動きを2倍速に
.OnComplete(() => StartCoroutine(DiamondLifetime(diamond))); // アニメーション完了時にダイヤのライフタイムを開始
// 敵のライフを増加させる
maxEnemyLife += 10; // ライフの増加量を設定
enemyLife = maxEnemyLife;
// 敵を一瞬消して再び現れる演出を追加
StartCoroutine(RespawnEnemy());
}
IEnumerator DiamondLifetime(GameObject diamond)
{
float lifetime = 4.0f; // ダイヤが消えるまでの時間
float timer = 0.0f;
while (timer < lifetime)
{
timer += Time.deltaTime;
yield return null;
if (diamond == null)
yield break; // ダイヤが既に消えている場合はコルーチンを終了
}
if (diamond != null)
{
FlyToCoinCount(diamond); // ダイヤをコインカウントに飛ばす
}
}
IEnumerator CoinLifetime(GameObject coin)
{
float lifetime = 4.0f; // コインが消えるまでの時間
float timer = 0.0f;
while (timer < lifetime)
{
timer += Time.deltaTime;
yield return null;
if (coin == null)
yield break; // コインが既に消えている場合はコルーチンを終了
}
if (coin != null)
{
FlyToCoinCount(coin); // コインをコインカウントに飛ばす
}
}
IEnumerator RespawnEnemy()
{
// 敵を一瞬消す
spriteRenderer.DOFade(0, 0.5f);
yield return new WaitForSeconds(0.5f);
// 敵を再び現す
spriteRenderer.DOFade(1, 0.5f);
UpdateDamageGauge(); // ダメージゲージをリセット
UpdateEnemyLifeText(); // 敵のライフの表示を更新
}
void IncreaseTapDamage()
{
if (coinCount >= 10) // 必要なコイン数を設定
{
coinCount -= 10; // コインを消費
tapDamage += 1; // タップダメージを増加
UpdateCoinCountText(); // UIを更新
Debug.Log("タップダメージが増加しました。現在のタップダメージ: " + tapDamage);
}
}
void IncreaseSpiritLevel()
{
if (coinCount >= 20) // 必要なコイン数を設定
{
coinCount -= 20; // コインを消費
foreach (GameObject spirit in spirits)
{
SpiritController spiritController = spirit.GetComponent<SpiritController>();
if (spiritController != null)
{
spiritController.IncreaseAttackPower(); // 精霊の攻撃力を増加
}
}
UpdateCoinCountText(); // UIを更新
Debug.Log("精霊の攻撃力が増加しました。");
}
}
void AddSpirit()
{
if (diamondCount >= 10) // 必要なダイヤ数を設定
{
diamondCount -= 10; // ダイヤを消費
GameObject newSpirit = Instantiate(spiritPrefab, spiritSpawnPoint.position, Quaternion.identity);
newSpirit.GetComponent<SpiritController>().targetEnemy = this.gameObject; // 追加された部分
spirits.Add(newSpirit);
UpdateDiamondCountText(); // UIを更新
Debug.Log("精霊が追加されました。");
}
}
}
これで、一通りの機能を実装することができました。
クリックゲームの感覚が掴めたので、今回でこのゲームの開発は一旦終わりにします。
<以前の記事>
個人ゲーム開発日報|コインでレベルアップの実装
コインでレベルアップの実装
個人ゲーム開発日報|ダイヤ消費で味方の複製
今回はダイヤ消費で味方の複製を実装します。