- Home /
Integer Getter Method always returns zero
Hello everyone, I am trying to make a system that stores GameObjects in a dictionary that is accessed with their unique ID's (obtained elsewhere from a RaycastHit object). Putting objects in the dictionary and getting them out works fine, I have verified with printing to debug.log.
However my getter method that returns the ID of the currently selected object is only returning 0. I have no idea what the problem is, other than maybe the integer variable gets reset to its default value every time the script stops running.
This is my first time asking a question on here, so I apologize if my formatting was bad or if I wasn't very specific.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class id_table : MonoBehaviour
{
//hash table linking unique ID's to gameobjects
public Dictionary<int,GameObject> idTable = new Dictionary<int,GameObject>();
//this will hold the currently selected object's ID
int selected;
//add a gameobject to our hashtable with ID as the key
public void addObject(int id, GameObject go){
//set ID as the currently selected object
selected = id;
//check that our key does not already exist
if (!(idTable.ContainsKey(id)))
{
//add object to table
idTable.Add(id,go);
//confirm we added item to table
Debug.Log("Item " + id + " added to table");
}
}
//return a gameobject
public GameObject getObject(int id){
//set ID as the currently selected object
selected = id;
return idTable[id];
}
//return the ID of the currently selected gameObject
public int getSelected(){
//THIS IS THE AREA THAT ALWAYS RETURNS AS ZERO
Debug.Log("Selected ID is: " + selected);
return selected;
}
}
Answer by sh_code · Jan 13, 2019 at 10:38 PM
Obviously, your error is in a different script. Probably something that's trying to add object with id 0, or get object with id 0, as you set the selected both when adding and getting objects.
This script you provided is fine (except it's weird to be setting the selected id everywhere, but whatever, your logic might require that), but something outside is calling something in this one and providing id 0.
I'd guess it's the raycast script, which, when it doesn't hit anything, returns id 0, calls into this script with the id, and thus setting the selected to 0 as well.
Unfortunately I don't think that's the case. "Selected" is only written when my RaycastHit is valid (it ignores UI objects) and it always assigns a unique instanceID to the hit object. So selected will only ever be a unique InstanceID.
I also have Debug.Log printouts that tell me every time the "Selected" variable gets changed. These show that "selected" value is correct up until I try to use that return method.
Another piece of the puzzle is that if I return a hard value like, say 5, then run the game, the game will say that "The selected ID is 5".
If I go back and set it to return the "selected" variable, then it will continue returning 5 until I go back and force it to return another hard value.
How do you generate those "unique instanceID". $$anonymous$$eep in $$anonymous$$d that an integer can only represent 4 billion different values. Also where is this script attached to? How many instances of this script exists in your scene / project? When you want to call "addObject" from a seperate script, are you sure you reference the "correct" instance of that script? So yes, the error is most likely in another script or generally a wrong concept. Either way the issue is somewhere that isn't included in the information you provided in your question.
There is one object I have that handles selection events. One script deter$$anonymous$$es what object is selected, assigns an ID using GetInstanceID(), then uses the addObject() method to add that object to the Dictionary.
I think the issue is me not understanding how Unity/C# handles variables and functions. I haven't formally learned how C# handles memory, only C++. Here is an example of anothe problem I encountered.
public class global_selection : $$anonymous$$onoBehaviour
{
//raycast return variable
RaycastHit hit;
//keeping track of current game object
GameObject go = null;
public int getSelected(){
return go.GetInstanceID();
}
//............more code that isn't relevant down here
I decided to get the ID from the gameObject itself in another script. There is always a GameObject selected, so in theory this should return the ID of the GameObject that is currently selected (which I have verified by a Debug.Log print out again).
However I got an error saying that go was still set to null, even after I had spawn multiple objects and selected them, so go had been overwritten several times.
It seems that for whatever reason, my user-defined functions outside of start, update, lateupdate, etc, are accessing the variables as they are declared at the top of the script, rather than their new value after they have been dynamically updated. I'll try to find a book or something that explains C#'s memory rules better. Thank you guys for the help in the meantime!
Answer by pickles976 · Jan 14, 2019 at 02:28 AM
I figured it out. I was calling the getSelected() function from another GameObject and I used "public GameObject eventHandler" to assign my Event Handler to the script in the inspector. I was unknowingly assigning a prefab as the reference instead of the copy of the Event System already present in my world.
I instead used "GameObject.find" to assign the eventHandler at runtime and then call the getSelected() method. I had an inkling that this was the problem earlier, but it didn't work until the second time around when I changed it.
Thank you guys for all the help you were very fast and responsive!
Answer by badadam · Jan 14, 2019 at 09:48 AM
Set tag of all game objects you want to add to idTable Dictionary "tableitem" and add collider to all your these game objects. Add the script below to all game objects you want to add to idTable and set indexItem
public class GameobjectItem : MonoBehaviour {
public int indexItem;
}
change your addObject and getSelected methods with the codes below
public void addObject(GameObject go)
{
//set ID as the currently selected object
int id= go.GetComponent<GameobjectItem>().indexItem;
//check that our key does not already exist
if (!(idTable.ContainsKey(id)))
{
//add object to table
idTable.Add(go.GetComponent<GameobjectItem>().indexItem, go);
}
}
public int getSelected()
{
RaycastHit raycastHit;
if (Physics.Raycast(transform.position,transform.forward,out raycastHit))
{
if (raycastHit.collider.gameObject.tag=="tableitem")
{
return raycastHit.collider.gameObject.GetComponent<GameobjectItem>().indexItem;
}
}
return -1;
}