ふりかえり
前回は設定画面を実装しました!
プレイヤーの詳細なステータス確認や、BGM・SEの音量調整ができるようになり、ゲームがより快適に遊べるようになりました。
ガチャを実装!
いよいよ、RPGの醍醐味でもある「ガチャ」を実装します!
使うのは、今まで用途がなかったダイヤ。
ガチャで排出されるのは「アーティファクト」という装備のような存在です。
- アーティファクトとは? 攻撃力やHP、会心率など、ステータスを強化してくれる特殊な装備のようなものです。 さらに、強化することで効果量がアップします!
スクリプトの変更
ArtifactManager.cs
アーティファクトの管理・表示・ガチャ機能を統括するクラスです。主な機能は以下の通り:
- ガチャでランダムにアーティファクトを排出
- プレイヤーの所持ダイヤを消費して実行
- 未所持のアーティファクトを優先して排出
- 所持しているアーティファクトはリスト表示
- アーティファクトごとに強化ボタンがあり、ダイヤでレベルアップ可能
- アーティファクトの効果は攻撃力、HP、会心率などに反映
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections.Generic;
public class ArtifactManager : MonoBehaviour
{
[Header("UI References")]
public GameObject artifactPanel; // アーティファクトパネル
public Button artifactButton; // アーティファクトボタン(開閉用)
[Header("ガチャUI")]
public Button gachaButton; // ガチャボタン
public TextMeshProUGUI gachaCostText; // ガチャコスト表示
public TextMeshProUGUI gachaResultText; // ガチャ結果表示
[Header("アーティファクトリストUI")]
public GameObject artifactListContent; // アーティファクトリストのコンテンツ
public GameObject artifactItemPrefab; // アーティファクトアイテムのプレハブ
public ScrollRect artifactScrollRect; // スクロールエリア
[Header("参照")]
public PlayerManager playerManager;
public AudioManager audioManager;
[Header("ガチャ設定")]
public int gachaCost = 10; // ガチャコスト(ダイヤ)
public int upgradeCost = 5; // 強化コスト(ダイヤ)
[Header("アーティファクトデータ")]
public List<ArtifactData> availableArtifacts = new List<ArtifactData>();
private bool isPanelOpen = false;
private List<ArtifactData> ownedArtifacts = new List<ArtifactData>(); // 所持アーティファクトリスト
private List<GameObject> artifactItemObjects = new List<GameObject>(); // アーティファクトアイテムのGameObjectリスト
void Start()
{
// アーティファクトボタンのイベントリスナーを設定
if (artifactButton != null)
{
artifactButton.onClick.AddListener(ToggleArtifactPanel);
}
// ガチャボタンのイベントリスナーを設定
if (gachaButton != null)
{
gachaButton.onClick.AddListener(PerformGacha);
}
// 初期設定:アーティファクトパネルは閉じた状態
if (artifactPanel != null)
{
artifactPanel.SetActive(false);
}
isPanelOpen = false;
// アーティファクトデータを初期化
InitializeArtifactData();
// UIを更新
UpdateUI();
}
// アーティファクトパネルの表示/非表示を切り替え
public void ToggleArtifactPanel()
{
isPanelOpen = !isPanelOpen;
if (artifactPanel != null)
{
artifactPanel.SetActive(isPanelOpen);
}
if (isPanelOpen)
{
UpdateArtifactList();
UpdateUI();
}
}
// アーティファクトデータを初期化
private void InitializeArtifactData()
{
availableArtifacts.Clear();
// アーティファクトデータを追加
availableArtifacts.Add(new ArtifactData
{
name = "勇者の剣",
description = "攻撃力を大幅に上昇させる伝説の剣",
artifactType = ArtifactType.Attack,
baseValue = 10,
valuePerLevel = 5,
});
availableArtifacts.Add(new ArtifactData
{
name = "守護者の盾",
description = "防御力を大幅に上昇させる神聖な盾",
artifactType = ArtifactType.Defense,
baseValue = 5,
});
availableArtifacts.Add(new ArtifactData
{
name = "生命の宝石",
description = "HPを大幅に上昇させる神秘的な宝石",
artifactType = ArtifactType.HP,
baseValue = 50,
valuePerLevel = 25,
});
availableArtifacts.Add(new ArtifactData
{
name = "会心の指輪",
description = "会心率を上昇させる魔術的な指輪",
artifactType = ArtifactType.CriticalRate,
baseValue = 0.05f,
valuePerLevel = 0.02f,
});
availableArtifacts.Add(new ArtifactData
{
name = "破壊の斧",
description = "会心ダメージ倍率を上昇させる凶悪な斧",
artifactType = ArtifactType.CriticalDamage,
baseValue = 0.5f,
valuePerLevel = 0.2f,
});
availableArtifacts.Add(new ArtifactData
{
name = "a",
description = "a",
artifactType = ArtifactType.CriticalDamage,
baseValue = 0.5f,
valuePerLevel = 0.2f,
});
}
// ガチャを実行
public void PerformGacha()
{
if (playerManager == null || playerManager.player == null) return;
if (playerManager.player.diamond >= gachaCost)
{
playerManager.player.diamond -= gachaCost;
// 指定されたランクの未所持アーティファクトを取得
List<ArtifactData> unownedArtifacts = GetUnownedArtifacts();
List<ArtifactData> rankArtifacts = new List<ArtifactData>();
foreach (var artifact in unownedArtifacts)
{
if (artifact.rank == randomRank)
{
rankArtifacts.Add(artifact);
}
}
// 指定されたランクのアーティファクトがない場合は、他のランクから選択
if (rankArtifacts.Count == 0)
{
rankArtifacts = unownedArtifacts;
}
if (rankArtifacts.Count > 0)
{
int randomIndex = Random.Range(0, rankArtifacts.Count);
ArtifactData newArtifact = rankArtifacts[randomIndex];
// すでに所持していないか念のためチェック
bool alreadyOwned = false;
foreach (var owned in ownedArtifacts)
{
if (owned.name == newArtifact.name)
{
alreadyOwned = true;
break;
}
}
if (!alreadyOwned)
{
ArtifactData ownedArtifact = new ArtifactData
{
name = newArtifact.name,
description = newArtifact.description,
artifactType = newArtifact.artifactType,
baseValue = newArtifact.baseValue,
valuePerLevel = newArtifact.valuePerLevel,
level = 1,
rank = newArtifact.rank // ランクもコピー
};
ownedArtifacts.Add(ownedArtifact);
}
// アーティファクト効果を適用
ApplyAllArtifactEffects();
// ガチャSEを再生
if (audioManager != null)
{
audioManager.PlayPowerUpSE();
}
if (gachaResultText != null)
{
gachaResultText.text = $"獲得: {newArtifact.name} ({newArtifact.rank}ランク) Lv.1";
}
UpdateArtifactList();
UpdateUI();
Debug.Log($"アーティファクトガチャ成功: {newArtifact.name} ({newArtifact.rank}ランク) Lv.1");
}
else
{
if (gachaResultText != null)
{
gachaResultText.text = "全てのアーティファクトを獲得済みです";
}
Debug.Log("全てのアーティファクトを獲得済みです");
}
}
else
{
if (gachaResultText != null)
{
gachaResultText.text = "ダイヤが足りません";
}
Debug.Log("ダイヤが足りません");
}
}
// 未所持のアーティファクトを取得
private List<ArtifactData> GetUnownedArtifacts()
{
List<ArtifactData> unownedArtifacts = new List<ArtifactData>();
foreach (var artifact in availableArtifacts)
{
bool isOwned = false;
foreach (var ownedArtifact in ownedArtifacts)
{
if (ownedArtifact.name == artifact.name)
{
isOwned = true;
break;
}
}
if (!isOwned)
{
unownedArtifacts.Add(artifact);
}
}
return unownedArtifacts;
}
// 指定されたランクのアーティファクトを取得
private ArtifactData GetRandomArtifactByRank(ArtifactRank rank)
{
List<ArtifactData> rankArtifacts = new List<ArtifactData>();
foreach (var artifact in availableArtifacts)
{
if (artifact.rank == rank)
{
rankArtifacts.Add(artifact);
}
}
if (rankArtifacts.Count > 0)
{
return rankArtifacts[Random.Range(0, rankArtifacts.Count)];
}
return availableArtifacts[0];
}
// アーティファクトを強化(個別)
public void UpgradeArtifact(int artifactIndex)
{
if (playerManager == null || playerManager.player == null) return;
if (artifactIndex < 0 || artifactIndex >= ownedArtifacts.Count) return;
if (playerManager.player.diamond >= upgradeCost)
{
playerManager.player.diamond -= upgradeCost;
// 指定されたアーティファクトを強化
ArtifactData artifactToUpgrade = ownedArtifacts[artifactIndex];
artifactToUpgrade.level++;
// アーティファクト効果を再適用
ApplyAllArtifactEffects();
// 強化SEを再生
if (audioManager != null)
{
audioManager.PlayPowerUpSE();
}
UpdateArtifactList();
UpdateUI();
Debug.Log($"アーティファクト強化成功: {artifactToUpgrade.name} Lv.{artifactToUpgrade.level}");
}
else
{
Debug.Log("ダイヤが足りません");
}
}
// 全てのアーティファクト効果を適用
private void ApplyAllArtifactEffects()
{
if (playerManager == null || playerManager.player == null) return;
// アーティファクトステータスをリセット
ResetArtifactStats();
// 所持している全てのアーティファクトの効果を適用
foreach (var artifact in ownedArtifacts)
{
float effectValue = artifact.baseValue + (artifact.valuePerLevel * (artifact.level - 1));
switch (artifact.artifactType)
{
case ArtifactType.Attack:
playerManager.player.artifactPowerUpAttack += Mathf.RoundToInt(effectValue);
break;
case ArtifactType.Defense:
playerManager.player.artifactPowerUpDefense += Mathf.RoundToInt(effectValue);
break;
case ArtifactType.HP:
playerManager.player.artifactPowerUpHP += Mathf.RoundToInt(effectValue);
break;
case ArtifactType.CriticalRate:
playerManager.player.artifactPowerUpCriticalRate += effectValue;
break;
case ArtifactType.CriticalDamage:
playerManager.player.artifactPowerUpCriticalDamage += effectValue;
break;
}
}
// 最終ステータスを再計算
UpdateFinalStats();
}
// アーティファクトステータスをリセット
private void ResetArtifactStats()
{
if (playerManager == null || playerManager.player == null) return;
playerManager.player.artifactPowerUpHP = 0;
playerManager.player.artifactPowerUpAttack = 0;
playerManager.player.artifactPowerUpDefense = 0;
playerManager.player.artifactPowerUpCriticalRate = 0f;
playerManager.player.artifactPowerUpCriticalDamage = 0f;
}
// 最終ステータスを更新
private void UpdateFinalStats()
{
if (playerManager == null || playerManager.player == null) return;
// 最終ステータスは自動的に計算されるため、特に何もしない
// PlayerDataのプロパティが自動的に計算する
}
// アーティファクトリストを更新
private void UpdateArtifactList()
{
if (artifactListContent == null) return;
// 既存のアイテムを削除
foreach (var item in artifactItemObjects)
{
if (item != null)
{
Destroy(item);
}
}
artifactItemObjects.Clear();
// 所持アーティファクトがない場合
if (ownedArtifacts.Count == 0)
{
// 空のメッセージを表示する処理を追加できます
return;
}
// 所持アーティファクトのアイテムを作成
for (int i = 0; i < ownedArtifacts.Count; i++)
{
CreateArtifactItem(i, ownedArtifacts[i]);
}
}
// アーティファクトアイテムを作成
private void CreateArtifactItem(int index, ArtifactData artifact)
{
if (artifactItemPrefab == null || artifactListContent == null) return;
GameObject itemObject = Instantiate(artifactItemPrefab, artifactListContent.transform);
artifactItemObjects.Add(itemObject);
// アーティファクト情報を設定
ArtifactItemUI itemUI = itemObject.GetComponent<ArtifactItemUI>();
if (itemUI != null)
{
itemUI.Initialize(artifact, index, this);
}
}
// UIを更新
private void UpdateUI()
{
if (playerManager == null || playerManager.player == null) return;
// ガチャコスト表示
if (gachaCostText != null)
{
gachaCostText.text = $"ガチャコスト: {gachaCost}ダイヤ";
}
// ボタンの有効/無効設定
if (gachaButton != null)
{
bool hasUnownedArtifacts = GetUnownedArtifacts().Count > 0;
gachaButton.interactable = playerManager.player.diamond >= gachaCost && hasUnownedArtifacts;
}
}
// アーティファクトパネルが開いているかどうかを取得
public bool IsPanelOpen()
{
return isPanelOpen;
}
}
// アーティファクトデータクラス
[System.Serializable]
public class ArtifactData
{
public string name;
public string description;
public ArtifactType artifactType;
public float baseValue;
public float valuePerLevel;
public int level = 1;
}
// アーティファクトタイプ
public enum ArtifactType
{
Attack,
Defense,
HP,
CriticalRate,
CriticalDamage
}
ArtifactItemUI.cs
- アーティファクト1つ1つを表示するUIコンポーネント
- 名前・効果・説明・レベル・強化ボタンを管理
- ダイヤが足りない場合はボタンを無効にする処理もあり
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class ArtifactItemUI : MonoBehaviour
{
[Header("UI References")]
public TextMeshProUGUI artifactNameText;
public TextMeshProUGUI artifactLevelText;
public TextMeshProUGUI artifactEffectText;
public TextMeshProUGUI artifactDescriptionText;
public Button upgradeButton;
public TextMeshProUGUI upgradeCostText;
private ArtifactData artifactData;
private int artifactIndex;
private ArtifactManager artifactManager;
public void Initialize(ArtifactData artifact, int index, ArtifactManager manager)
{
artifactData = artifact;
artifactIndex = index;
artifactManager = manager;
UpdateDisplay();
SetupUpgradeButton();
}
private void UpdateDisplay()
{
if (artifactNameText != null)
artifactNameText.text = artifactData.name;
if (artifactLevelText != null)
artifactLevelText.text = $"レベル: {artifactData.level}";
if (artifactEffectText != null)
{
float effectValue = artifactData.baseValue + (artifactData.valuePerLevel * (artifactData.level - 1));
string effectDescription = GetEffectDescription(artifactData.artifactType, effectValue);
artifactEffectText.text = effectDescription;
}
if (artifactDescriptionText != null)
artifactDescriptionText.text = artifactData.description;
if (upgradeCostText != null)
upgradeCostText.text = $"強化コスト: {artifactManager.upgradeCost}ダイヤ";
}
private void SetupUpgradeButton()
{
if (upgradeButton != null)
{
upgradeButton.onClick.RemoveAllListeners();
upgradeButton.onClick.AddListener(OnUpgradeButtonClicked);
// ボタンの有効/無効設定
bool canUpgrade = artifactManager.playerManager.player.diamond >= artifactManager.upgradeCost;
upgradeButton.interactable = canUpgrade;
}
}
private void OnUpgradeButtonClicked()
{
artifactManager.UpgradeArtifact(artifactIndex);
UpdateDisplay();
SetupUpgradeButton();
}
private string GetEffectDescription(ArtifactType type, float value)
{
switch (type)
{
case ArtifactType.Attack:
return $"攻撃力 +{value}";
case ArtifactType.Defense:
return $"防御力 +{value}";
case ArtifactType.HP:
return $"HP +{value}";
case ArtifactType.CriticalRate:
return $"会心率 +{value * 100:F1}%";
case ArtifactType.CriticalDamage:
return $"会心倍率 +{value:F1}倍";
default:
return "";
}
}
}
Unityでの設定
ArtifactManagerとArtifactItemUIのUnityでの設定手順を詳細に説明します。
アーティファクトプレハブ(ArtifactItemPrefab)の作成
- Hierarchy で右クリック → UI → Panel を選択
- 作成されたPanelを
ArtifactItemPrefabにリネーム - Project ウィンドウで
Prefabsフォルダを作成(なければ) ArtifactItemPrefabをPrefabsフォルダにドラッグ&ドロップしてプレハブ化
- 名前・効果・レベル・説明のText(TextMeshPro)を追加
- 強化ボタン(Button)とそのコスト表示も設置
- ArtifactItemUI スクリプトをアタッチし、各UI要素を紐付け


アーティファクトパネル
- アーティファクト用のパネルを作成
- ガチャボタンやガチャ結果表示用のTextも配置
- ScrollView を使用して、所持アーティファクトを縦並びに表示

管理オブジェクト ArtifactManager
- パネルやボタン、PrefabなどすべてをInspectorで接続
- PlayerManager と AudioManager もドラッグ&ドロップで設定

動作確認
アーティファクトボタンを押すと専用パネルが開く
ガチャを回すと新しいアーティファクトが表示される

強化ボタンを押すとダイヤが消費され、アーティファクトの効果がアップ

アーティファクトの内容によって、プレイヤーの攻撃力・HP・会心系ステータスに反映!

まとめ
今回はガチャとアーティファクトの実装を行いました!
強化要素が追加されて、育成のやりがいがアップしました!
ガチャがあることで「ゲームらしさ」もグッと引き立ちますね!
次回予告
次回はアーティファクトにランク(レア度)を設定し、ガチャの排出率調整を行います!
お楽しみに!

