0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UnityでScriptableObjectを使ったらバグ地獄に…? -複数の敵が勝手に弾を撃つようになった原因と対策-

Last updated at Posted at 2025-04-19

この投稿で得られること

  • ScriptableObjectを使う際の意外な落とし穴
  • 「Healのはずが弾が出る」ようなバグの本質
  • Unityで状態管理する際の安全な設計パターン

開発背景

敵キャラの行動管理に ScriptableObject(以下SO)を使っていました。
EnemyData というSOにこんな感じのパラメータを持たせています:

[CreateAssetMenu(fileName = "EnemyData", menuName = "Game/EnemyData")]
public class EnemyData : ScriptableObject
{
    public string enemyName = "Enemy";
    public int maxHP = 100;
    public float attackInterval = 10f;
    public int attackPower = 10;
    public int defense = 5;

    // 実はここが落とし穴
    public EnemyActionType actionType = EnemyActionType.Attack;
}

発生した問題

敵Aが Heal を選んだ

敵Bが Attack を選んだ

→ なぜか 敵Aまで弾を撃ち出した!?

見た目は Heal アイコンなのに、弾が出てプレイヤーを攻撃。完全にバグってるように見えました。

原因:SOは「共有される」インスタンスだった

SOは Unity において、アセットベースで共有される参照型です。
そのため、複数の敵が同じSOを参照していると、状態を上書きし合ってしまうのです。

enemyA.stats.actionType = Heal;
enemyB.stats.actionType = Attack;
// enemyA も attack 扱いされる(共有されてるため)

解決策:SOを複製して使う!

[SerializeField] private EnemyData statsTemplate; // SOアセット
private EnemyData stats; // 実行時インスタンス

void Start()
{
    stats = Instantiate(statsTemplate); // ランタイムで複製
}

これにより、各敵が個別の stats を持てるようになり、バグは完全解消しました。

ScriptableObjectに持たせてはいけないもの

OK(共有すべき情報)   名前、HP上限、攻撃力など
NG(実行中に変わる情報) 現在HP、状態、行動タイプなど

教訓とベストプラクティス

SOは「読み取り専用設定データ」と割り切る

状態(行動・HP・ターゲット)は必ずインスタンス側で保持する

複製には Instantiate() を使う

UnityのSOは便利だけど「安全ではない」こともある

再現チェック用ログ例(抜粋)

[Decision] Drone decided to Buff
[Execute] Drone BUFFS Player

→ 弾が飛ぶ

[Decision] Drone decided to Attack
[Execute] Drone ATTACKS EnemyController

→ 弾のログ

まとめ

ScriptableObjectは便利だけど危険な共有変数

状態を扱うには、実行時に複製してインスタンス管理するのがベスト

「バフのはずが攻撃してる…」そんな直感に反する挙動にはSOの共有性を疑うべき

ブログでもUnityや個人開発ネタを発信中です!

開発ノウハウやアプリ制作過程、Unity連携系のハマりポイントなど
より深掘りした内容をブログにまとめています。
https://syunpp.com

公開中のアプリ一覧はこちら!

実際にUnityで開発してリリース済みのアプリ一覧をまとめています。
https://syunpp.com/公開中のアプリ一覧/

コメント・ストック・LGTM大歓迎!

「自分も似た経験ある」「こうやって回避してるよ」などあれば気軽にコメントください!
ストックやLGTMも励みになります!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?