前提・実現したいこと
メインのソースコードにおいて、Attack関数を呼び出して、その中で他のクラスの変数を用いながら、体力計算をしたいです。
発生している問題・エラーメッセージ
275行目でエラーが出てしまいます。
エラーメッセージ NullReferenceException: Object reference not set to an instance of an object FirstCommand.Attack () (at Assets/Cscript/Battle/FirstCommand.cs:275)
###メインのソースコード
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class FirstCommand : MonoBehaviour { [System.NonSerialized] public float action; [System.NonSerialized] public float Const=19/20f; private Mystatus me; private Dragonstatus dragon; public GameObject canvas;//キャンバス public GameObject FightButton; public GameObject ConversationButton; public GameObject FeedButton; public GameObject EscapeButton; public GameObject AttackButton; public GameObject WeaponButton; public GameObject BackButton; public GameObject DefenceButton; public GameObject MessageUI; Slider EneHP; Slider MyHP; // MessageUIに設定されているMessageスクリプトを設定 [SerializeField] private Message messageScript; // 表示させるメッセージ private string Attackmessage = "あなたの攻撃"; private string Attackedmessage = "相手の攻撃"; // Start is called before the first frame update void Start() { ProduceAll(); VanishSecond(); ProduceMessage(); //AttackMessage(); me = GetComponent<Mystatus>(); Debug.Log("my ATK ="+me.ATK); dragon = GetComponent<Dragonstatus>(); Debug.Log("dragon hp =" + dragon.HP); } public void OnClick() { Debug.Log("first click"); int eneselection = Random.Range(1, 4); switch (transform.name) { //first case "Fight": Debug.Log("tatakau"); VanishFirst(); ProduceSecond(); break; case "Conversation": Debug.Log("kaiwa"); VanishFirst(); ProduceSecond(); break; case "Feed": VanishFirst(); ProduceSecond(); Debug.Log("esa"); break; case "Escape": Debug.Log("逃げる"); int nige = Random.Range(1, 101); //Destroy(this.gameObject); if (nige <= 50) { SceneManager.LoadScene("EscapeScene"); } break; //second case "Attack": Debug.Log("attack"); VanishSecond(); Debug.Log("second finish"); //AttackMessage(); Attack(); //DestroyAttackMessage(); if (eneselection == 1 || eneselection == 3) { //AttackedMessage(); Attacked(); } else if (eneselection == 2) { //AttackedMessage(); me.DFC *= 2; Attacked(); me.DFC /= 2; } ProduceFirst(); break; case "Weapon": Debug.Log("weapon"); if (eneselection == 1 || eneselection == 3) { Attacked(); } else if (eneselection == 2) { me.DFC *= 2; Attacked(); me.DFC /= 2; } VanishSecond(); ProduceFirst(); break; case "Defence": Debug.Log("defence"); me.ATK *= 2; Attack(); me.ATK /= 2; if (eneselection == 1 || eneselection == 3) { me.ATK *= 2; Attacked(); me.ATK /= 2; } else if (eneselection == 2) { me.DFC *= 2; Attacked(); me.DFC /= 2; } VanishSecond(); ProduceFirst(); break; case "Back": Debug.Log("modoru"); VanishSecond(); ProduceFirst(); break; default: break; } } void VanishFirst() { GameObject[] Firsts = GameObject.FindGameObjectsWithTag("First"); foreach (GameObject First in Firsts) { First.SetActive(false); //Destroy(First); } } void VanishSecond() { GameObject[] Seconds = GameObject.FindGameObjectsWithTag("Second"); foreach (GameObject Second in Seconds) { Second.SetActive(false); //Destroy(First); } } void ProduceFirst() { GameObject.Find("Canvas").transform.Find("Fight").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Conversation").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Feed").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Escape").gameObject.SetActive(true); } void ProduceSecond() { GameObject.Find("Canvas").transform.Find("Attack").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Weapon").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Defence").gameObject.SetActive(true); GameObject.Find("Canvas").transform.Find("Back").gameObject.SetActive(true); } void ProduceAll() { GameObject prefab1 = (GameObject)Instantiate(FightButton); prefab1.name = "Fight"; prefab1.transform.SetParent(canvas.transform, false); GameObject prefab2 = (GameObject)Instantiate(ConversationButton); prefab2.name = "Conversation"; prefab2.transform.SetParent(canvas.transform, false); GameObject prefab3 = (GameObject)Instantiate(FeedButton); prefab3.name = "Feed"; prefab3.transform.SetParent(canvas.transform, false); GameObject prefab4 = (GameObject)Instantiate(EscapeButton); prefab4.name = "Escape"; prefab4.transform.SetParent(canvas.transform, false); GameObject prefab5 = (GameObject)Instantiate(AttackButton); prefab5.name = "Attack"; prefab5.transform.SetParent(canvas.transform, false); GameObject prefab6 = (GameObject)Instantiate(WeaponButton); prefab6.name = "Weapon"; prefab6.transform.SetParent(canvas.transform, false); GameObject prefab7 = (GameObject)Instantiate(DefenceButton); prefab7.name = "Defence"; prefab7.transform.SetParent(canvas.transform, false); GameObject prefab8 = (GameObject)Instantiate(BackButton); prefab8.name = "Back"; prefab8.transform.SetParent(canvas.transform, false); } void ProduceMessage() { GameObject prefab = (GameObject)Instantiate(MessageUI); prefab.name = "MessageUI"; // Debug.Log("sssssss"); } IEnumerator Wait() { // 3秒待つ Debug.Log("waiting"); yield return new WaitForSeconds(3f); Debug.Log("finished waiting"); } void Attack() { //相手の体力計算 me = GetComponent<Mystatus>(); dragon = GetComponent<Dragonstatus>(); EneHP = GameObject.Find("EnemyHp").GetComponent<Slider>(); Debug.Log("enehp=" + EneHP.value); ↓↓↓この文にエラーー Debug.Log("dragon hp before="+dragon.HP); dragon.HP = EneHP.value; dragon.HP -= me.ATK * (Mathf.Pow(Const, dragon.DFC)); EneHP.value = dragon.HP; Debug.Log("dragon HP after:" + dragon.HP + " me.ATK:" + me.ATK + " pow:" + Mathf.Pow(Const, dragon.DFC) + " powre:" + " const:" + Const + "dragon.DFC:" + dragon.DFC); } void Attacked() { me = GetComponent<Mystatus>(); dragon = GetComponent<Dragonstatus>(); MyHP = GameObject.Find("YourHp").GetComponent<Slider>(); //自分の体力計算 me.HP = MyHP.value; //Debug.Log("me.HP" +me.HP); me.HP -= dragon.ATK * Mathf.Pow(Const, me.DFC); MyHP.value = me.HP; //Destroy(this.gameObject); } void AttackMessage() { GameObject.Find("MessageUI").GetComponent<Message>().SetMessagePanel(Attackmessage);//あなたの攻撃 } void DestroyAttackMessage() { GameObject.Find("MessageUI").GetComponent<Message>().DestroyMessage(); } void AttackedMessage() { GameObject.Find("MessageUI").GetComponent<Message>().SetMessagePanel(Attackedmessage);//相手の攻撃 } }
###ステータスのソースコード
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Dragonstatus : MonoBehaviour { public int ID = 1; public float MAXHP = 1000f; public float HP = 1000f; public float ATK = 550f; public float DFC = 10f; public string NAME = "ドラゴン"; }
試したこと
スタートのなかで他のスクリプトからの変数の呼び出しはできていることを確認しました。しかし、Attack関数になると同じようなプログラムを書いても動作してくれません。
お分かりの方ご教授お願い致します。
275行目ってどこでしょうか
申し訳ありません。
メインのコードのAttack関数内になります。
//を用いて示しております。
<---- ここ みたく どこでエラーに
なっているか示してくれますか?
修正させていただきました。
よろしくお願いします。
エラーってどんなエラーでしょうか。メッセージは出ていますか?
私の予想では、「ヌルポ系例外」なんじゃないかなと。
(理由: GetComponentとやらで取得しているため)
発生している問題・エラーメッセージの欄に記入してありますが、不完全だったでしょうか。
console画面のメッセージを写したのですが、この方法以外わからないもので、、、
例外が発生しているので、Attack関数の呼び出し時にGetComponentで正しく参照出来ていないみたいですね。
Attack関数を呼び込み時にFirstCommandとDragonstatusが同じオブジェクトにアタッチされているか確認してみてください。
また、StartでDragonstatusを参照しているので外部からコンポーネントを操作していなければ、Attack関数内でGetComponentせずとも取得出来るかと思います。(何か理由があって操作している場合は別ですが)
↓参考に
https://tech.pjin.jp/blog/2017/05/29/unity_error_null-reference-exception/
同様のエラーは 過去のログにもあります。
https://teratail.com/questions/33595
FirstCommandがヌル参照となってそうです。
Attack関数を呼び込み時にはFirstCommandとDragonstatusが同じオブジェクトにアタッチされており、両方とも有効になっています。
Attack関数で再度取得する必要はないんですね。ありがとうございます。
>> 発生している問題・エラーメッセージの欄に記入してありますが、
あ、ほんとですね。見落とし...かな?
ですがやはり例外でしたね。simapikoさんがおっしゃるように、私が先ほど述べたように、
「存在しないオブジェクトを使おうとしている」のが原因です。(それかすでに取得しているのに...とか?)
なるほど。
再取得が問題かと思ったのでAttack関数での取得をせずに実行してみましたが同じエラーが出てしまいました…。
デバックしてStart関数のときは成功していることが確認しているので、Attack関数のとき急にできなくなるのが謎なんです。
同じオブジェクトかつStart関数で取得出来ているのでしたら、現状提示されているコードではそれっぽい原因は見つけられないですね…。Start関数とAttack関数が呼ばれる間に原因があるのは確かなので、変数dragonがnullになっていないかどうかや、Dragonstatus.HPに何か手を加えている部分があればその辺りをDebug.Log等使って追ってみてください。
Startでは大丈夫なのですが、Attack関数でdragonがnullになっていることが確認されました。
直前で
dragon = GetComponent<Dragonstatus>();
を行ってもNULLになっているようです。
インスペクター画面Dragonstatusが有効になっていることが確認されており、このスクリプトは同じオブジェクトにアタッチされています。
解決方法をご存じないでしょうか。
考えられる事としては、FirstCommandのAttack関数以外でもGetComponentしているので、その時にnullになってしまっている可能性と、Dragonstatusを途中で無効にしている場合に参照が外れている(その方法でnullになるかは試していないので定かではありませんが…。)等、自分が考えられるのはこれくらいでしょうか…。
一度新しいプロジェクトで他のスクリプトを使わずにFirstCommand.cs関係のスクリプトのみを使って、同様の結果になるかどうかを試してみてはいかがでしょうか。
現状ですと、提示していただいている物にはエラーの原因が見当たらないので、もしかすると他のスクリプトが影響しているかもしれません...。
あと考えにくいことですが、Start時には取得できてAttack実行時に取得できないという事は、エディタ再生後にDragonstatus.csが消えている、もしくは無効になっている可能性も一応あるのかなと思います。一度確認されてみてはいかがでしょうか。