Unity is saying Audioclip is null - c#

I am using this script to try and pull random noises to play during gameplay
public class Sons : MonoBehaviour
{
public static AudioClip al1, al2, al3, al4, al5, al6, al7, al8, al9, al10, al11, al12, al13;
static AudioSource Audio;
int randomizer;
// Start is called before the first frame update
void Start()
{
randomizer = (Random.Range(1, 13));
//sons aleatorios=============================================================
al1 = Resources.Load<AudioClip>("ran1");
al2 = Resources.Load<AudioClip>("ran2");
al3 = Resources.Load<AudioClip>("ran3");
al4 = Resources.Load<AudioClip>("ran4");
al5 = Resources.Load<AudioClip>("ran5");
al6 = Resources.Load<AudioClip>("ran6");
al7 = Resources.Load<AudioClip>("ran7");
al8 = Resources.Load<AudioClip>("ran8");
al9 = Resources.Load<AudioClip>("ran9");
al10 = Resources.Load<AudioClip>("ran10");
al11 = Resources.Load<AudioClip>("ran11");
al12 = Resources.Load<AudioClip>("ran12");
al13 = Resources.Load<AudioClip>("ran13");
InvokeRepeating("RNDSND", 1f, 20f);
//sons ventilação============================================================
//sons corredor==============================================================
//sons salas=================================================================
Audio = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
}
void RNDSND()
{
switch (randomizer)
{
case 1:
Audio.PlayOneShot(al1);
break;
case 2:
Audio.PlayOneShot(al2);
break;
case 3:
Audio.PlayOneShot(al3);
break;
case 4:
Audio.PlayOneShot(al4);
break;
case 5:
Audio.PlayOneShot(al5);
break;
case 6:
Audio.PlayOneShot(al6);
break;
case 7:
Audio.PlayOneShot(al7);
break;
case 8:
Audio.PlayOneShot(al8);
break;
case 9:
Audio.PlayOneShot(al9);
break;
case 10:
Audio.PlayOneShot(al10);
break;
case 11:
Audio.PlayOneShot(al11);
break;
case 12:
Audio.PlayOneShot(al12);
break;
case 13:
Audio.PlayOneShot(al13);
break;
}
}
}
...but unity sends the message "PlayOneShot Was Called With Null AudioClip"
Can anyone point out what I am doing wrong and any possible solutions?

I would recommend doing something more like this:
public class Sons : MonoBehaviour
{
public AudioClip[] randSounds;
static AudioSource Audio;
int randomizer;
// Start is called before the first frame update
void Start()
{
for(int i = 0; i < randSounds.Length; i++)
{
randSounds[i] = Resources.Load<AudioClip>("ran" + i);
}
Audio = GetComponent<AudioSource>();
InvokeRepeating("RNDSND", 1f, 20f);
}
void RNDSND()
{
randomizer = (Random.Range(0, randSounds.Length));
Audio.PlayOneShot(randSounds[randomizer]);
}
}
Untested. I would probably also just delete the Resources.Load call since it seems expensive memory wise to do that on load for all your objects, you probably want to assign those clips into the inspector if possible, or load them on Awake() and before you need to use them.

Related

How can I instantiate a prefab in a panel like slots and detect when it's full and make a scroll option?

I try to make an vertical inventory, like i have show in picture.
I want to be able to add slots in number of items available, and and the create a schroolbar to view all slots available.
i will use switch to switch the sprites.
I need to create an instance of the prefab of the slot for each item picked.
I have try my self implement ip but it give me an 2 errors wen i try to instatiate de prefab.
this is the errors:
1 Setting the parent of a transform which resides in a prefab is
disabled to prevent data corruption.
UnityEngine.Transform:SetParent(Transform, Boolean)
additem:CreateA() (at Assets/inventory ultimate pt/additem.cs:49)
additem:Start() (at Assets/inventory ultimate pt/additem.cs:35)
the line in question is
the void createA prefabtoinstatiate.transform.SetParent(panel.transform, false);
2 NullReferenceException: Object reference not set to an instance of an
object
additem.CreateA () (at Assets/inventory ultimate pt/additem.cs:50)
additem.Start () (at Assets/inventory ultimate pt/additem.cs:35)
the line in question is
title_text.text = title_text1.text;
this is my code so far.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class additem : MonoBehaviour {
public static int havepick = 0;
public Transform prefabtoinstatiate;
public GameObject panel;
public static Text title_text;
public static Text description_text;
public static Text amount_text;
public static Sprite image;
public static int amountx = 0;
public Text title_text1;
public Text description_text1;
public Text amount_text1;
public Sprite image_icon_small_healling;
public Sprite image_icon_medium_healling;
public Sprite image_icon_big_healling;
public Sprite image_icon_small_stamina;
public Sprite image_icon_medium_stamina;
public Sprite image_icon_big_stamina;
public Sprite image_icon_small_magic;
public Sprite image_icon_medium_magic;
public Sprite image_icon_big_magic;
public Sprite image_icon_small_defence;
public Sprite image_icon_medium_defence;
public Sprite image_icon_big_defence;
public int image_number_count;
// Use this for initialization
void Start () {
CreateA ();
}
// Update is called once per frame
void Update () {
description_text1.text = "Small healling Potion " +
"Give You 10 Points Of Healling";
amount_text1.text = "Amount: " + amountx;
title_text1.text= "Small Healling Potion";
}
public void CreateA() {
prefabtoinstatiate.transform.SetParent(panel.transform, false);
title_text.text = title_text1.text;
description_text.text= description_text1.text;
amount_text.text =amount_text1.text;
}
public void changeimages()
{
switch (image_number_count)
{
case 0:
GetComponent <Image>().sprite = image_icon_small_healling;
image_number_count++;
break;
case 1:
GetComponent <Image>().sprite = image_icon_medium_healling;
image_number_count++;
break;
case 2:
GetComponent <Image>().sprite = image_icon_big_healling;
image_number_count++;
break;
case 3:
GetComponent <Image>().sprite = image_icon_small_stamina;
image_number_count++;
break;
case 4:
GetComponent <Image>().sprite = image_icon_medium_stamina;
image_number_count++;
break;
case 5:
GetComponent <Image>().sprite = image_icon_big_stamina;
image_number_count++;
break;
case 6:
GetComponent <Image>().sprite = image_icon_small_magic;
image_number_count++;
break;
case 7:
GetComponent <Image>().sprite = image_icon_medium_magic;
image_number_count++;
break;
case 8:
GetComponent <Image>().sprite = image_icon_big_magic;
image_number_count++;
break;
case 9:
GetComponent <Image>().sprite = image_icon_small_defence;
image_number_count++;
break;
case 10:
GetComponent <Image>().sprite = image_icon_medium_defence;
image_number_count++;
break;
case 11:
GetComponent <Image>().sprite = image_icon_big_defence;
image_number_count++;
break;
}
}
}

triggerzone reads the same object every frame

Trigger-zone reads the same object every frame, it is not supposed to do that and it is messing up the game. It does not happen all the time and I don't know why
Sorry for the messy code, I am not too organized.
There are not many comments (if any) I always forget to put them in.
I am just typing now to try to get it to let me post
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spacereader : MonoBehaviour
{
public int spacesmoved = 0, jiff;
void Start()
{
}
void Update()
{
sharedscript.nummoved = spacesmoved;
if(sharedscript.reset)
{
spacesmoved = 0;
jiff = 0;
}
}
private void OnTriggerEnter(Collider other)
{
Debug.Log(other.tag);
Debug.Log(other.name);
StartCoroutine(spotchecker(other));
if (jiff != 2)
jiff++;
else if (sharedscript.ismoving)
{
spacesmoved++;
}
}
private IEnumerator spotchecker(Collider other)
{
switch (other.tag)
{
case "GO":
break;
case "MEDAVE":
break;
case "CHEST":
break;
case "BALAVE":
break;
case "INCOME":
break;
case "READING":
break;
case "ORIENTAL AVE":
break;
case "CHANCE":
break;
case "VERMONT":
break;
case "CONNAVE":
break;
case "INJAIL":
break;
case "CHARPLACE":
break;
case "COMPANY":
break;
case "STATESAVE":
break;
case "VIRGAVE":
break;
case "PENNRAIL":
break;
case "JAMESPLACE":
break;
case "TENNAVE":
break;
case "NEWYORKAVE":
break;
case "FREEPARK":
break;
case "KENAVE":
break;
case "INDIAVE":
break;
case "ILLAVE":
break;
case "BORAIL":
break;
case "ATLAAVE":
break;
case "VENTAVE":
break;
case "WATERWORKS":
break;
case "MARVGARD":
break;
case "GOTOJAIL":
break;
case "PACAVE":
break;
case "NORTHAVE":
break;
case "PENNAVE":
break;
case "SHORTLINE":
break;
case "PARKPLACE":
break;
case "BOARDWALK":
break;
case "LUXTAX":
break;
}
yield return other;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playercontroller : MonoBehaviour
{
public List<GameObject> targets;
public float speed, step;
bool canmove = false;
public List<Camera> cameras;
public Camera diecam;
public List<GameObject> players;
public List<GameObject> playerreaders;
public int[] turntarget = new int[] { 0, 0, 0, 0 };
public int turn = 1;
int lastturn = 0;
bool switchit = true;
Coroutine inin;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(canmove)
{
if(!switchit || sharedscript.doubles)
{
foreach(GameObject s in playerreaders)
{
s.SetActive(false);
}
foreach (Camera s in cameras)
{
s.gameObject.SetActive(false);
}
foreach(GameObject s in players)
{
Collider g = s.GetComponent<Collider>();
g.enabled = false;
Rigidbody w = s.GetComponent<Rigidbody>();
w.isKinematic = true;
}
lastturn = turn;
switchit = true;
}
Collider d = players[turn].GetComponent<Collider>();
d.enabled = true;
Rigidbody f = players[turn].GetComponent<Rigidbody>();
f.isKinematic = false;
playerreaders[turn].SetActive(true);
cameras[turn].gameObject.SetActive(true);
diecam.gameObject.SetActive(false);
step = speed * Time.deltaTime;
if (players[turn].transform.position.x <= targets[turntarget[turn]].transform.position.x + .003 && players[turn].transform.position.x >= targets[turntarget[turn]].transform.position.x - .003 && players[turn].transform.position.z <= targets[turntarget[turn]].transform.position.z + .03 && players[turn].transform.position.z >= targets[turntarget[turn]].transform.position.z - .03)
{
if (turntarget[turn] < 3)
{
turntarget[turn] ++;
players[turn].transform.Rotate(0, 90, 0);
}
else
{
turntarget[turn] = 0;
}
}
players[turn].transform.position = Vector3.MoveTowards(players[turn].transform.position, targets[turntarget[turn]].transform.position, speed);
}
if(sharedscript.nummoved >= sharedscript.total)
{
canmove = false;
sharedscript.ismoving = false;
}
else
{
canmove = true;
sharedscript.ismoving = true;
}
if(sharedscript.nummoved >= sharedscript.total && sharedscript.total != 0 && sharedscript.nummoved != 0 && !sharedscript.doubles && switchit)
{
if (turn < 3)
turn++;
else
turn = 0;
sharedscript.reset = true;
switchit = false;
Debug.Log("playedturn");
sharedscript.canroll = true;
}
}
}
You are starting your coroutine whenever something enters the trigger collider. Try checking if the object that entered is the object you are looking for. If it is your player and the object is tagged "Player" you could check for that:
private void OnTriggerEnter(Collider other)
{
if(other.CompareTag("Player"))
{
StartCoroutine(YourCoroutine());
}
}
Another reason could be Unity collision detection. It can be wonky at times so most of the time you are better off checking if the objects collided already.
One way to solve this issue using coroutines in particular would be to store the coroutine in a variable in your script and check if it already ran. Something like this:
private Coroutine coroutine;
private void OnTriggerEnter(Collider other)
{
if(coroutine == null)
{
coroutine = StartCoroutine(YourCoroutine());
}
}
Then set the value to null in OnTriggerExit or something:
private void OnTriggerExit(Collider other)
{
coroutine = null;
}
I would recommend to also check for the tag in this implementation:
private Coroutine coroutine;
private void OnTriggerEnter(Collider other)
{
if(coroutine == null && other.CompareTag("Player"))
{
coroutine = StartCoroutine(YourCoroutine());
}
}

coroutine calls following method too many times

I'm trying out some code for an idea I had recently. But right now I'm stuck on trying to find a good way to add a delay. I've been trying to use coroutine, and I get a delay, but the method called after that gets called way too many times (I only want it to be called once)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System;
using Random = UnityEngine.Random;
public class YourHealth : MonoBehaviour
{
bool yourTurn = true;
public Button button1;
public Button button2;
public Text YH;
public Text EH;
private int yourHealth = 100;
private int enemyHealth = 100;
// Use this for initialization
void Start()
{
button1.onClick.AddListener(Heal20);
button2.onClick.AddListener(Damage40);
YH.text = Convert.ToString(yourHealth);
EH.text = Convert.ToString(enemyHealth);
}
public void Heal20()
{
yourHealth += 20;
yourTurn = false;
}
public void Damage40()
{
enemyHealth -= 40;
yourHealth -= 5;
yourTurn = false;
}
public void Update()
{
YH.text = Convert.ToString(yourHealth);
EH.text = Convert.ToString(enemyHealth);
if (yourTurn == false)
{
button1.interactable = false;
StartCoroutine(Wait(2));
}
else
{
button1.interactable = true;
}
}
public void EnemyTurn()
{
int roll = Random.Range(1 , 7);
switch (roll)
{
case 1:
yourHealth -= 10;
break;
case 2:
enemyHealth -= 10;
break;
case 3:
yourHealth -= 30;
break;
case 4:
yourHealth += 5;
break;
case 5:
break;
case 6:
enemyHealth += 10;
break;
}
yourTurn = true;
}
IEnumerator Wait(float time)
{
yield return new WaitForSecondsRealtime(time);
EnemyTurn();
}
}
I want EnemyTurn to be called only once after the delay. But instead it runs a bunch of times. I hope I can get a solution to this quickly because it has just brought a halt to my project and I can't figure it out myself.
That's because you're creating a Wait Coroutine on every Update call between the player's end and the enemy's turn. You need a way to only create it once per player turn end.
One way is adding a flag that you set when you create the Wait Coroutine and then unset it when the enemy's turn is done:
// If this is true, we are already waiting
// and don't want more Wait coroutines (yet)
private bool waiting;
void Start()
{
button1.onClick.AddListener(Heal20);
button2.onClick.AddListener(Damage40);
YH.text = Convert.ToString(yourHealth);
EH.text = Convert.ToString(enemyHealth);
waiting = false;
}
// ...
if (yourTurn == false)
{
if (!waiting)
{
// we only want to do this stuff the first frame we start waiting
button1.interactable = false;
waiting = true;
StartCoroutine(Wait(2));
}
}
else
{
button1.interactable = true;
}
// ...
IEnumerator Wait(float time)
{
yield return new WaitForSecondsRealtime(time);
EnemyTurn();
waiting = false;
}

My Unity Script Wont work?

Hi I have a script attached to the main camera, and in this script I want to choose a number between 0 to 5 . And depending on what number I get, I want a script to run. Hers my script that is attached to the main camera. I keep getting this error
NullReferenceException: Object reference not set to an instance of an object RandomFunction.Start () (at Assets/Resources/Scripts/RandomFunction.cs:22)
using UnityEngine;
using System.Collections;
public class RandomFunction : MonoBehaviour {
int n;
void Awake()
{
GetComponent<RandomFunction> ().enabled = true;
}
void Start ()
{
n=Random.Range(0,5);
if(n==0)
{
GetComponent<BlueGoUp> ().enabled = true;
}
else if(n==1)
{
GetComponent<RedGoUp> ().enabled = true;
}
else if(n==2)
{
GetComponent<GreenGoUp> ().enabled = true;
}
else if(n==3)
{
GetComponent<OrangeGoUp> ().enabled = true;
}
else if(n==4)
{
GetComponent<YellowGoUp> ().enabled = true;
}
else if(n==5)
{
GetComponent<PurpleGoUp> ().enabled = true;
}
}
}
Remove Awake() method because it is really unnecessary to active RandomFunction script from here. Active that in inspector.
I'm not sure if use component like this was correct. I always use gameObject.GetComponent
if(n==5) will never be true because Random.Range(0,5) return 0,1,2,3 or 4 .
from the document:
Range(int min, int max), Returns a random integer number between min [inclusive] and max [exclusive] (Read Only).
Use switch case statement instead of If else
Your final code should look like this:
using UnityEngine;
using System.Collections;
public class RandomFunction : MonoBehaviour {
int n;
void Start ()
{
n=Random.Range(0,6);
switch (n)
{
case 0:
gameobject.GetComponent<BlueGoUp> ().enabled = true;
break;
case 1:
gameObject.GetComponent<RedGoUp> ().enabled = true;
break;
case 2:
gameObject.GetComponent<GreenGoUp> ().enabled = true;
break;
case 3:
gameObject.GetComponent<OrangeGoUp> ().enabled = true;
break;
case 4:
gameObject.GetComponent<YellowGoUp> ().enabled = true;
break;
case 5:
gameObject.GetComponent<PurpleGoUp> ().enabled = true;
break;
default:
break;
}
}
}
So first of all, you don't need to do what you're doing in the Awake function because:
The MonoBehaviour object being used is the one attached to the GameObject. If you don't get what I mean, supposed you attached RandomFunction to a CameraObj. Now, that instance of RandomFunction (this pointer in script) is equal to or is same as CameraObj.GetComponent<RandomFunction>(), since you can't add more than one of the same component to a GameObject.
The Awake() method won't be executed till the object is actually enabled. Thus you won't need to re-enable the object in the script, because if it is executing, the object is enabled already.
Remove the Awake method and it should also remove the NullReferenceException. If it still doesn't, make sure that the same object (which has the RandomFunction component) also has the components BlueGoUp, RedGoUp, YellowGoUp, GreenGoUp, OrangeGoUp and PurpleGoUp.
Oh, and your if (n==5) condition will never be true, since 5 will never be returned by Random.Range(). The max parameter is always exclusive for integers in the Random.Range() function, thus the value returned will always be min <= value < max.
Most probably and I am hoping that all the GoUp scripts are not attached to the Camera. So find script in another way. Try to replace your code by this,
using UnityEngine;
using System.Collections;
public class RandomFunction : MonoBehaviour {
int n;
void Awake()
{
GetComponent<RandomFunction> ().enabled = true;
}
void Start ()
{
n=Random.Range(0,6);
switch(n){
case 0:
FindObjectOfType<BlueGoUp>().enabled = true;
break;
case 1:
FindObjectOfType<RedGoUp>().enabled = true;
break;
case 2:
FindObjectOfType<GreenGoUp>().enabled = true;
break;
case 3:
FindObjectOfType<OrangeGoUp>().enabled = true;
break;
case 4:
FindObjectOfType<YellowGoUp>().enabled = true;
break;
case 5:
FindObjectOfType<PurpleGoUp>().enabled = true;
break;
}
}
}
If this code will not work then there is no way other than that your scripts are not dropped on any gameObjects.

Program skipping stages

So I have a Unity program, where it switches screens if the user presses ENTER.
However, whenever the user presses enter, instead of just going one screen forward, it skips all the way to the last screen.
Here is my OnGUI():
if (showScreen == true)
{
//this allows the screens to toggle
switch (pageNum)
{
case 1:
rectangle = GUI.Window(1,rectangle, Page1, "Computer");
break;
case 2:
rectangle = GUI.Window(1,rectangle, Page2, "Computer");
break;
case 3:
rectangle = GUI.Window(1,rectangle, Page3, "Computer");
break;
case 4:
rectangle = GUI.Window(1,rectangle, Page4, "Computer");
break;
case 5:
rectangle = GUI.Window(1,rectangle, Page5, "Computer");
GUILayout.Window (2,rect2, popUp, "Warning!");
break;
case 6:
rectangle = GUI.Window(1,rectangle, Page6, "Computer");
break;
case 7:
rectangle = GUILayout.Window(1,rectangle, Page7, "Computer");
break;
default:
break;
}
}
And here is where the GUIs are actually set up, and made to change:
void Page1(int windowID)
{ if (Input.GetKeyDown(KeyCode.Return))
{
GUI.FocusControl(null);
pageNum = 2;
}
}
void Page2(int windowID)
{
if (Input.GetKeyDown(KeyCode.Return))
{
pageNum = 3;
GUI.FocusControl(null);
}
}
//continue like this for 5 more Page#(int windowID)
So what can I insert into these classes to make my program stop skipping? should I put a pause into these if statements too?
So it looks like the easiest way to solve this problem is by changing how the program changes the stages. All you need to do is a boolean that changes to true once the return key has been pressed.
so just declare the boolean:
public class ClassName : MonoBehaviour
{
bool wasClicked = false;
Then to change the states just do this:
if (Input.GetKey(KeyCode.Return))
{
wasClicked = true;
}
if (wasClicked)
{
if (!Input.GetKey(KeyCode.Return))
{
GUI.FocusControl(null);
pageNum = next page number;
wasClicked = false;
}
}

Categories