Unity NullReferenceException after accessing a variable of another script - unity3d

after trying to acces a variable in another Script of another GameObject out of a List, I get every time an Exception. The Main code looks like this:
private var BombList = new List.<GameObject>();
private var BombTemp : GameObject;
private var BombTempScript : Bomb;
function Start () {
BombTemp = null;
BombTempScript = null;
BombList.Clear();
}
function Update () {
if(BombList.Count > 0){
for(var i : int = 0; i<BombList.Count;i++){
BombTemp = BombList[i];
BombTempScript = BombTemp.GetComponent.<Bomb>();
if(BombTempScript.bombCountdown <= 0){
BombTempScript.explode();
BombList.Remove(BombTemp);
addHealth(-1);
}
}
}
}
function OnTriggerEnter (other : Collider) {
if(other.gameObject.CompareTag("Bomb")){
BombList.Add(other.gameObject);
other.gameObject.GetComponent.<Bomb>().notListed = false;
}
}
function OnTriggerExit(other : Collider){
if(other.gameObject.CompareTag("Bomb")){
if(BombList.Contains(other.gameObject)){
BombList.Remove(other.gameObject);
other.gameObject.GetComponent.<Bomb>().notListed = true;
}
}
}
If there isn't an object in the List the Code in the Update function does not work as intended. But when there is an object inside it produces a NullReferenceException in the if Line:
if(BombTempScript.bombCountdown <= 0)
The variable which is pointed at named bombCountdown, is continuously changing.
Here is the intended code:
#pragma strict
public var bombCountdown : float;
public var notListed : System.Boolean;
function Start () {
bombCountdown = 10.0;
notListed = true;
}
function Update () {
bombCountdown -= Time.deltaTime;
if(bombCountdown <= 0 && notListed)
explode();
}
function explode(){
Destroy(myText);
Destroy(this.gameObject);
}
I hope you could help us.
Thanks in advance, the Silly Scientists

I think there's a small bug in the code, which is making it happen.
In the Bomb script, in the following portion, you are destroying the bomb object, without removing it from the BombList of the first script.
As a result, BombList[i] may become null, as it may already have been destroyed.
If you make sure that you update the BombList when the Bomb is destroyed, I guess the code will work.

You remove gameobject from list in the for loop, so all indexes in the list shift to left from removed object. And the count is not the same as for loop started. At first you must complete your for loop, then remove objects after that.

Related

Unity3D call function from another script (Unityscript)

I've looked up similar questions and responses and still have not been able to get this to work.
LessonRightButton.js
//#pragma strict
public var audio1 : AudioPlayback;
function OnClick(){
var findAudioSource = GameObject.Find("AudioPlaybackButton");
var audio1:AudioPlayback = findAudioSource.GetComponent(AudioPlayback);
audio1.woo(); // THIS IS LINE 50 IN THE ERROR
}
AudioPlayback.js
//#pragma strict
function woo(){
Debug.Log("wooooooooooooooo");
}
I get this error:
NullReferenceException: Object reference not set to an instance of an
object LessonRightButton.OnClick () (at
Assets/Scripts/LessonRightButton.js:50)
I'm trying to call the woo function from a different script.
These scripts are shortened for the purpose of ease of reading. Please advise.
you have no AudioPlayback attached on that AudioPlaybackButton object.
Either add one manually or by code:
function OnClick(){
var findAudioSource = GameObject.Find("AudioPlaybackButton");
var audio1:AudioPlayback = findAudioSource.GetComponent(AudioPlayback);
if(audio1 == null){
audio1 = findAudioSource.AddComponent(AudioPlayback);
}
audio1.woo();
}

Access non static function from static function

Here is some insight: I am working with UnityScript in Unity 4.6.3. I have one script called Pause.js and it contains this function:
function fadeMusicOut () {
while (audio.volume >= 0.005) {
yield WaitForSeconds(0.1);
Debug.Log("Loop Entered: " + audio.volume);
audio.volume = (audio.volume - 0.015);
}
Another script GameManager.js has this function:
static function Score (wallName : String) {
if (wallName == "rightWall") {
playerScore01 += 1;
}
else {
playerScore02 += 1;
}
if (playerScore01 == SettingsBack.scoreLimit || playerScore02 == SettingsBack.scoreLimit)
{
startParticles = 1;
SettingsBack.gameOver = 1;
BallControl.fadeSound = 1;
yield WaitForSeconds(4);
Camera.main.SendMessage("fadeOut");
Pause.fadeMusic = 1;
SettingsBack.soundVolume = 0;
yield WaitForSeconds(2);
playerScore01 = 0;
playerScore02 = 0;
SettingsBack.soundVolume = oldSoundVol;
Application.LoadLevel("_Menu");
}
}
So pretty much I want to call the fadeMusicOut() function from static function Score, but it will not let me because it says it needs an instance of that object.
The Pause.js script is not attached to any game objects, but it is attached to 2 buttons that call their specific functions. The GameManager.js script is attached to an object called GM. So how can I go about calling fadeMusicOut() from the Score function?
I have tried setting new vars that import the game object but still no luck. I tried making fadeMusicOut() a static function, but it creates many errors.
Any help at all is appreciated.

unity Destroy instantiated GameObject

i want to destroy a game object that i instantiated and i get a lot of errors when i try to do so like "the name clone does not exist in the current context" , "cannot convert object expression to type UnityEngine.Object". i tried a lot of things i found online but nothing helps. here is my code :
if(distance<renderDistance)
{
if(!temp)
{
GameObject clone = Instantiate(chunk,transform.position,transform.rotation)as GameObject;
temp = true;
}
}
else
{
Destroy(clone);
}
You were getting "the name clone does not exist in the current context" error because you declared this variable ('clone') inside "if(!temp)" brackets and it hasn't existed after closing bracket.
Try this code:
GameObject clone = null;
if (distance < renderDistance)
{
if(!temp)
{
clone = (GameObject)Instantiate(chunk, transform.position, transform.rotation);
//be sure 'chunk' is GameObject type
temp = true;
}
}
else
{
if (clone != null)
Destroy(clone);
}
Let me know if you have any questions or need more help.

Why isn't my score recording on the playerprefs is there GetFloat method?

Why isn't my score recording on the playerprefs ? is there GetFloat method? Can anyone help me to post the least score of my game it just like the most least seconds will get the best time record ever
var myTimer: float = 0;
var GUITimer: GUIText;
function Start() {
}
function Update() {
GUITimer.text = "Time: " + myTimer;
if (myTimer > -1) {
myTimer += Time.deltaTime;
}
}
function OnTriggerEnter(other: Collider) {
if (other.tag == "FinishLine") {
SaveTime();
}
}
function OnGUI() {
GUI.Label(Rect(10, 10, 500, 200), myTimer.ToString());
}
function SaveTime() {
if (myTimer < PlayerPrefs.GetInt("JeepneyScore3")) {
PlayerPrefs.SetInt("JeepneyScore3", myTimer);
}
Application.LoadLevel("Levels");
}
I see three problems:
First, you're tracking a float, but calling GetInt() and SetInt(). Keep your data types consistent. You should either round/floor/etc, or call GetFloat() and SetFloat().
Second, you're not calling Save(), which means your changes will never write to disk. You might consider something like this:
PlayerPrefs.SetFloat("JeepneyScore3", myTimer);
PlayerPrefs.Save();
Third, you're not handling the case where no data exists. You could check for existing data with HasKey(), but in this case it's simpler to rely on the second form of GetFloat(). The default form, which you're calling, returns zero if the requested key isn't set:
//returns value of "foo", or zero if no such value
var prevBest = PlayerPrefs.GetFloat("foo");
If you're looking for a time below the player's previous best, but the default "best" is already 0.0, you're going to have a hard time beating that time.
You can instead provide your own default value:
//returns value of "foo", or ten thousand if no such value
var prevBest = PlayerPrefs.GetFloat("foo", 10000.0);
Finally, you should make sure that SaveTime() is actually being called at the appropriate time. You could add a simple debug line, like this:
Debug.Log("SaveTime was called");
And then make sure that's showing up. If not, you need to fix your collision check.

Unity3D: Automatic target according to price

I've been working on a simulator in Unity3D and i need a customer object to be able to automatically find the shop object with the lowest price.
I've done a little testing on this myself and found it to be rather difficult to achive. So i was hoping someone could help me tweak my code a bit further in the right direction? :)
Here's the code i've got so far:
var cityName : String;
var shopScript : MarketScript;
function FindShopPlace () : GameObject //Make a queueing system
{
var max : float;
var target : GameObject;
var gos : GameObject[];
var goScript : MarketScript;
gos = GameObject.FindGameObjectsWithTag("market");
for (var go : GameObject in gos)
{
goScript = go.GetComponent(MarketScript);
if (goScript.cityName == cityName)
{
if (goScript.resalePrice >= max && goScript.cityName == cityName)
{
max = goScript.resalePrice;
}
if (goScript.resalePrice < max && goScript.cityName == cityName)
{
print ("test");
target = go;
}
}
}
shopScript = target.GetComponent(MarketScript);
return target;
}
Currently with this code, the target is never found and assigned. I get the following NullReferenceException from line number 3 from the bottom:
NullReferenceException: Object reference not set to an instance of an
object ConsumerScript.FindShopPlace () (at
Assets/_MyAssets/_Scripts/ConsumerScript.js:268) ConsumerScript.Update
() (at Assets/_MyAssets/_Scripts/ConsumerScript.js:96)
You get a NullReferenceException because target was never set to any object.
What you are doing in your loop is (1) finding the maximum price and (2) finding the last Object after maximum that is smaller than the maximum.
So if your prices in order are 1, 2, 3 target will never be set because in each step you are setting the maximum to the new value and are never setting target. Even when set its not necessarily the cheapest. Consider the prices 1, 3, 2.
First Step: Set maximum to 1
Second Step: Set maximum to 3
Third Step: Set target to the GameObject with price 2
If you get errors like this try out simple examples like this to get to the bottom of things. Also you are using the variable maximum(comparing the first time) without ever setting it to anything, not sure if this works in Javascript(it might) but its bad practice
What you really want isnt finding the maximum price or minimum price but the GameObject with the lowest resalePrice.
var min : float;
var success : boolean;
var firstHit : boolean;
...
success = false;
firstHit = true;
for (var go : GameObject in gos)
{
goScript = go.GetComponent(MarketScript);
if (goScript.cityName == cityName)
{
success = true;
if(firstHit) // alternatively to this would be to set minimum to a value that is higher than every possible price ( thats also what i meant with you shouldnt use max without setting it to anything)
{
min = goScript.resalePrice;
target = go;
}
else
{
if (goScript.resalePrice < min )
{
min = goScript.resalePrice;
target = go;
}
}
}
}
if(success)
{
shopScript = target.GetComponent(MarketScript);
return target;
}
else
{
// TODO: handle the case that there isnt a shop in the city.
// Maybe give an error Message with Debug.Log if this isnt supposed to happen
return null;
}