前提・実現したいこと
unityの勉強も兼ねて、格闘ゲームを製作しています。
5人の登場人物1人1人に別のステータスを設定(ジャンプ特化のキャラ、攻撃力特化のキャラのようなイメージ)したく、ScriptableObjectを使用しました。
具体的な実装方法として、
1:キャラクター選択した際、キャラクター1=number(1)のような感じで、変数numberが保存される。
2:変数numberの値によって、取得するScriptableObject(データ)が変わる
という方法です。
しかし、タイトルの通りすぐにNullのエラーが発生してしまいます。
そこで、ScriptableObjectからのデータの取得方法が間違っているのではと考えました。
正しい取得方法やもっと良い実装方法があれば教えていただきたいです。
以下、ソースコードです。明らかに質問と関係のない部分は省いています。
拙いコードですがご教授いただければ幸いです。
発生している問題・エラーメッセージ
NullReferenceException: Object reference not set to an instance of an object PlayerController.Movement () (at Assets/Scripts/PlayerController.cs:42) PlayerManager.Update () (at Assets/Scripts/PlayerManager.cs:55)
該当のソースコード
###ScriptableObject
C#
1public class FighterModel 2{ 3 public float at; 4 public float df; 5 public float moveJump; 6 public float moveSpeed; 7 8 public FighterModel(int fighterID) 9 { 10 FighterEntity fighterEntity = Resources.Load<FighterEntity>("FighterEntity" + fighterID); 11 12 at = fighterEntity.Attack; 13 df = fighterEntity.Defence; 14 moveJump = fighterEntity.MoveJump; 15 moveSpeed = fighterEntity.MoveSpeed; 16 } 17} 18
###エラーが出たソースコード
C#
1public class PlayerManager : MonoBehaviour 2{ 3 //動きに関する処理 4 PlayerController pc; 5 6 //Playerのデータ 7 public FighterModel model; 8 GameManager gameManager; 9 10 private void Awake() 11 { 12 pc = GetComponent<PlayerController>(); 13 } 14 // Start is called before the first frame update 15 void Start() 16 { 17 SetUp(); 18 } 19 //キャラクターのステータス取得 20 void SetUp() 21 { 22 switch (PlayerPrefs.GetInt("Data")) 23 { 24 case 0: 25 model = new FighterModel(0); 26 Debug.Log(model.moveJump); 27 Debug.Log(model.moveSpeed); 28 break; 29 case 1: 30 model = new FighterModel(1); 31 break; 32 case 2: 33 model = new FighterModel(2); 34 break; 35 case 3: 36 model = new FighterModel(3); 37 break; 38 } 39 } 40 // Update is called once per frame 41 void Update() 42 { 43 pc.Movement(); //エラー箇所 44 } 45} 46
C#
1public class PlayerController : MonoBehaviour 2{ 3 //data 4 public FighterModel model; 5 PlayerManager playerManager; 6 7 CharacterController characterController; 8 Vector3 moveDirection; 9 10 private void Awake() 11 { 12 characterController = GetComponent<CharacterController>(); 13 capsuleCollider = GetComponent<CapsuleCollider>(); 14 playerManager = GetComponent<PlayerManager>(); 15 } 16 //jump,横移動 17 public void Movement() 18 { 19 float z = Input.GetAxis("Horizontal"); 20 21 if (characterController.isGrounded) 22 { 23 //横方向の移動 24 moveDirection = new Vector3(0, 0, -z * model.moveSpeed); //エラー箇所 25 animator.SetFloat("speed", Mathf.Abs(z)); 26 27 //jump 28 if (Input.GetKeyDown(KeyCode.Space)) 29 { 30 //animator.SetTrigger("jump"); 31 moveDirection.y = model.moveJump; 32 } 33 } 34 moveDirection.y -= 10 * Time.deltaTime; 35 36 characterController.Move(moveDirection * Time.deltaTime); 37 } 38} 39
###キャラクター選択時のスクリプト
C#
1public class CharaSelect : MonoBehaviour 2{ 3 public int N; 4 5 public void SelectImage(int number) 6 { 7 N = number; 8 switch(N) 9 { 10 case 0 : 11 PlayerPrefs.SetInt("Data",N); //どのキャラクターを選択したか別のスクリプトでもつかえるようにする 12 selectText.text = "1人目"; 13 Debug.Log(N); 14 break; 15 16 case 1: 17 PlayerPrefs.SetInt("Data", N); 18 selectText.text = "2人目"; 19 break; 20 case 2: 21 PlayerPrefs.SetInt("Data", N); 22 selectText.text = "3人目"; 23 break; 24 case 3: 25 PlayerPrefs.SetInt("Data", N); 26 selectText.text = "4人目"; 27 break; 28 } 29 } 30} 31
試したこと
Debug.Logを使用し、データを取得できているか確認したところ初めの数秒は取得できていることが確認できた。
Update()でSetUp()を呼び出してみたところ変わらず、Start()で呼び出した場合と同様の結果が得られた。
補足情報(FW/ツールのバージョンなど)
unityバージョンは2020.2.7f1 を使用しております。
Udemyの講座を受講していたところ、ScriptableObjectを拝見し、実際に使用してみようと思い、使用しました。
以下、unity入門の森では、Inspector上に直接ScriptableObjectを設定していました。できるだけ、スクリプト上で完結させたかったので、こちらの方法は使用しておりません。
###主に参考にしたサイト
unty入門の森
https://3dunity.org/game-create-lesson/clicker-game/adding-clicker-items/
【Unity】今更ScriptableObject入門
https://qiita.com/4_mio_11/items/a7d8967b853cef4385cd
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/12/23 09:37