Unity2DのゲームアプリでBGMと複数SEを併用した際に起こるバグについてのご相談
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 224
前提・実現したいこと
UnityでC#を使用し、参考書を見ながらゲームアプリを作成しています。
発生している問題・エラーメッセージ
GameSceneのなかでBGMと3つのSE(スクリプトから操作しようと考えています)をゲーム中に鳴らそうとしたところ、BGMはなるのですが、SEの部分がプログラムの中でバグとして扱われ、ゲームの進行が中断されてしまいます。
AudioClip getScoreSEを鳴らす際のバグは、タッチしてもアプリが反応せず、アイテムが取れなくなります。
if文の中にAudioClip getScoreSEの文を移しても、音はならず、アイテムのカウントがされません。
AudioClip levelUpSEの時点で煙のエフェクトが出ている段階でエラーで画面が停止してしまいます。
大変お手数ですがご教示いただければ幸いです。
エラーメッセージ
NullReferenceException:Object reference not set to an instance of an object
該当のソースコード
下記該当コードをソースコードから抜粋します
public AudioClip getScoreSE;
public AudioClip levelUpSE;
public AudioClip clearSE;
private AudioSource audioSource;
//こちらのAudioSourceにはUnityの方で別途BGMをクリップを設定しています。
void Start()
{
audioSource = this.gameObject.GetComponent<AudioSource>();
currentOrb = 10;
public void GetOrb(int getScore)
{
audioSource.PlayOneShot(getScoreSE);
if (score < nextScore)
{
score += getScore;
void TempleLevelUpEffect()
{
GameObject smoke = (GameObject)Instantiate(smokePrefab);
smoke.transform.SetParent(canvasGame.transform, false);
smoke.transform.SetSiblingIndex(2);
audioSource.PlayOneShot(levelUpSE);
void ClearEffect()
{
GameObject kusudama = (GameObject)Instantiate(kusudamaPrefab);
kusudama.transform.SetParent(canvasGame.transform, false);
audioSource.PlayOneShot(clearSE);
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
public class GameManager : MonoBehaviour
{
private const int MAX_ORB = 10;
private const int RESPAWN_TIME = 1;
private const int MAX_LEVEL = 2;
public GameObject orbPrefab;
public GameObject smokePrefab;
public GameObject kusudamaPrefab;
public GameObject canvasGame;
public GameObject textScore;
public GameObject imageTemple;
public AudioClip getScoreSE;
public AudioClip levelUpSE;
public AudioClip clearSE;
private int score = 0;
private int nextScore = 10;
private int currentOrb = 0;
private int templeLevel = 0;
private DateTime lastDateTime;
private int[] nextScoreTable = new int[] { 10, 100, 1000 };
private AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
audioSource = this.gameObject.GetComponent<AudioSource>();
currentOrb = 10;
for(int i = 0; i < currentOrb; i++)
{
CreateOrb();
}
lastDateTime = DateTime.UtcNow;
nextScore = nextScoreTable[templeLevel];
imageTemple.GetComponent<TempleManager>().SetTemplePicture(templeLevel);
imageTemple.GetComponent<TempleManager>().SetTempleScale(score, nextScore);
RefreshScoreText();
}
// Update is called once per frame
void Update()
{
if(currentOrb < MAX_ORB)
{
TimeSpan timeSpan = DateTime.UtcNow - lastDateTime;
if(timeSpan >= TimeSpan.FromSeconds(RESPAWN_TIME))
{
while(timeSpan >= TimeSpan.FromSeconds(RESPAWN_TIME))
{
CreateNewOrb();
timeSpan -= TimeSpan.FromSeconds(RESPAWN_TIME);
}
}
}
}
public void CreateNewOrb()
{
lastDateTime = DateTime.UtcNow;
if(currentOrb >= MAX_ORB)
{
return;
}
CreateOrb();
currentOrb++;
}
public void CreateOrb()
{
GameObject orb = (GameObject)Instantiate(orbPrefab);
orb.transform.SetParent(canvasGame.transform, false);
orb.transform.localPosition = new Vector3(UnityEngine.Random.Range(-300.0f, 300.0f), UnityEngine.Random.Range(-140.0f, -500.0f));
int kind = UnityEngine.Random.Range(0, templeLevel + 1);
switch (kind)
{
case 0:
orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.BLUE);
break;
case 1:
orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.GREEN);
break;
case 2:
orb.GetComponent<OrbManager>().SetKind(OrbManager.ORB_KIND.PURPLE);
break;
}
}
public void GetOrb(int getScore)
{
audioSource.PlayOneShot(getScoreSE);
if (score < nextScore)
{
score += getScore;
if (score > nextScore)
{
score = nextScore;
}
TempleLevelUp();
RefreshScoreText();
imageTemple.GetComponent<TempleManager>().SetTempleScale(score, nextScore);
if ((score == nextScore) && (templeLevel == MAX_LEVEL))
{
ClearEffect();
}
}
currentOrb--;
}
void RefreshScoreText()
{
textScore.GetComponent<Text>().text = "徳:" + score + "/" + nextScore;
}
void TempleLevelUp()
{
if(score >= nextScore)
{
if(templeLevel < MAX_LEVEL)
{
templeLevel++;
score = 0;
TempleLevelUpEffect();
nextScore = nextScoreTable[templeLevel];
imageTemple.GetComponent<TempleManager>().SetTemplePicture(templeLevel);
}
}
}
void TempleLevelUpEffect()
{
GameObject smoke = (GameObject)Instantiate(smokePrefab);
smoke.transform.SetParent(canvasGame.transform, false);
smoke.transform.SetSiblingIndex(2);
audioSource.PlayOneShot(levelUpSE);
Destroy(smoke, 0.5f);
}
void ClearEffect()
{
GameObject kusudama = (GameObject)Instantiate(kusudamaPrefab);
kusudama.transform.SetParent(canvasGame.transform, false);
audioSource.PlayOneShot(clearSE);
}
}
試したこと
対応策1
AudioclipはGameManagerに紐づいているので
AudioClip getScoreSE = this.GetComponent<GameManager>().getScoreSE;
this.GetComponent<GameManager>().PlayOneShot(getScoreSE);
とコードを変更しましたが変化はありませんでした。
対応策2
Audioclipは最初から音楽生成機能を持つAudiosourceに紐づけられるものとして
AudioClip getScoreSE = this.GetComponent<AudioSource>().getScoreSE;
this.GetComponent<AudioSource>().PlayOneShot(getScoreSE);
としましたが変化はありませんでした。
対応策3
空のAudiosource2を作成し、SE分だけそちらに付け替えましたが、Audiosourceの方に判定がいき、効果ありませんでした。
対応策4
audioSource.PlayOneShot(getScoreSE);にボリュームの値を追加しましたが変化ありませんでした。
補足情報(FW/ツールのバージョンなど)
Unity 2019 4.1f
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
(質問への追記・修正の依頼より)
AudioSourceが付いているのが「GameManagerの子」なら
audioSource = this.gameObject.GetComponent<AudioSource>();
では取得出来ない(=nullになる)のでそれが原因です。
(このコードでは「GameManagerと同じGameObjectに付いているAudioSource」を取得しようとします)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
sakura_hana
2020/07/10 12:04
エラー文の中にエラーが発生している箇所が書かれているのでそこを確認してください。(「〜.cs:数字」となっていて数字は行数を指す)
NullReferenceExceptionについては以下を確認してください。
https://docs.unity3d.com/ja/current/Manual/NullReferenceException.html
teratail内を検索するだけでも同じ質問が沢山出て来るはずなのでそれを参考にnullの箇所を調べてください。
naki888
2020/07/13 09:22
承知いたしました。確認します。ご回答ありがとうございます。
naki888
2020/07/14 10:41
確認した結果、audioSource.PlayOneShot(getScoreSE);
audioSource.PlayOneShot(levelUpSE);
audioSource.PlayOneShot(getScoreSE);
でエラーが発生しています。
これらはGameManagerスクリプトprivateでAudioClip型として定義しています。
GameManagerの子にAudioSource(BGM付き)をつけていてもNULLが出るということはもう一つAudioSourceを作らなければいけないということなのでしょうか。
naki888
2020/07/14 10:44
もう1度記載しますがBGMの方はなります。BGMと一緒に鳴らそうとしているSEがならないので、AudioSourceにBGMをアタッチして、SEを流そうとするのが間違っているのかなどをお教えいただきたいのです。
sakura_hana
2020/07/14 11:19
AudioSourceが付いているのが「GameManagerの子」なら、
audioSource = this.gameObject.GetComponent<AudioSource>();
では取得出来ない(nullになる)のでそれが原因だと思います。
(これだと「GameManagerと同じGameObjectに付いているAudioSource」を取得しようとします)
BGMが元々セットされているClipをPlayOnAwakeで流しているなら、スクリプトとは無関係に動作するのでBGMは正常に流れるのは自然な動きです。
naki888
2020/07/14 11:52
承知いたしました。ありがとうございます。
オブジェクト2つとaudioSourceを2個使用してアタッチしたBGM用とインスペクターは空のSE用に分けたら解決しました。SE用のものは空のため3種類のSEを流すことができました。