problem calling method from another script, Unity [duplicate] - c#

This question already has answers here:
Member '<method>' cannot be accessed with an instance reference error in Singleton Unity
(2 answers)
Closed 4 months ago.
I have a method ListItems() witch i want to be updated whenever I open the Inventory for my game in Unity. Whenever I try this I get the error: member InventoryManager.ListItems() cannot be accessed with an instance reference; qualify it with a type name instead
None of these methods are static, so I'm a bit confused here...
ListItems() :
public void ListItems()
{
foreach(var item in Items)
{
GameObject obj = Instantiate(InventoryItem, ItemContent);
var itemName = obj.transform.Find("Item/ItemName").GetComponent<Text>();
var itemIcon = obj.transform.Find("Item/ItemIcon").GetComponent<Image>();
itemName.text = item.itemName;
itemIcon.sprite = item.icon;
}
}
Update() from a different class:
public GameObject inventory;
public InventoryManager i;
public void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
InventoryManager.GetComponent<InventoryManager>().ListItems();
inventory.gameObject.SetActive(!inventory.gameObject.activeSelf);
}
}

Your InventoryManager is a reference to your script so you don't actually need to call the GetComponent<InventoryManager>().
You just simply call it like this:
i.ListItems();
Or, if you want to use the GetComponent<InventoryManager>() you use it on the gameObject that your script is attached to, for example if public GameObject inventory; has attached to it the InventoryManager script then you can use the following code:
inventory.GetComponent<InventoryManager>().ListItems();
Using the GetComponent method is performance heavy, and it's not required to call it everytime, you can call it only once at the Awake() or Start() method to get the reference that you want and then just simply use the cached reference.

Related

An object reference is required for the non-static field, method or property (Unity C#) [duplicate]

This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 1 year ago.
public class BoardLocations : MonoBehaviour
{
public GameObject A1;
public class Coords
{
public Vector3 aOne = A1.transform.position;
}
}
This is all in one script, attached to an empty game object. The error I get is "An object reference is required for the non-static field, method or property 'BoardLocations.A1'". The only way to make the error go away is to make the GameObject and Vector3 static, but doing that means I can't see the GameObject in the inspector, which I need to assign the GameObject. Placing the GameObject in the same class as the Vector3 yields the same results. How can I reference the GameObject in the class so the Vector3 can see it?
your class coords is not having 'BoardLocations' reference. your code should be like
`public class Coords
{
public Vector3 aOne;
void Start()
{
stackof se = new stackof();
GameObject e = se.A1;
aOne = e.transform.position;
}
}`

How do I make a variable non-static without getting object reference error? (Beginner coder)

The update method in enemyHealth wants me to make targetHealth a static but if I do that then I won't be able to make unique enemies.
{
public Text enemyHealth;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
enemyHealth.text = EnemyVitals.targetHealth.ToString();
}
}
{
public double targetHealth = 100;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (targetHealth <= 1)
{
Destroy(gameObject);
}
}
}
as far as I understand, this: enemyHealth.text = EnemyVitals.targetHealth.ToString();
tries to access targetHealth like you would access static classes for example Vector3.up. These static classes/methods allow you to use their methods without making an instance of that class. So in your case, you would need a reference to an EnemyVitals instance and call .targetHealth on that instance. You can for example instantiate one via EnemyVitals enemyVit = new EnemyVitals(); or declare a public field in your first class like so: public EnemyVitals enemyVit;, then in the editor drag and drop the EnemyVitals reference to that field. I think you might rather want to get the reference somehow otherwise in-game, for example with raycasting to possible enemy objects etc..
From what you posted it seems to me that the latter is more what you would want to go for.

How to access string in one script from another? [duplicate]

This question already has answers here:
In Unity, how can I pass values from one script to another?
(4 answers)
Closed 1 year ago.
Can you tell me how to access a variable of a script from another script ? I have even read everything in unity website but I still can’t do it. I know how to access another object but not another variable.
This is the situation :
I’m in script B and I want to access the variable X from script A. The variable X is boolean.
Can you help me ?
Btw i need to update X’s value costantly in script B , how do I do that ? Access it in Update function
If you could give me and example with these letters would be great !
Thank you
You first need to get the script component of the variable, and if they're in different game objects, you'll need to pass the Game Object as a reference in the inspector.
For example, I have scriptA.cs in GameObject A and scriptB.cs in GameObject B:
scriptA.cs
// make sure its type is public so you can access it later on
public bool X = false;
scriptB.cs
public GameObject a; // you will need this if scriptB is in another GameObject
// if not, you can omit this
// you'll realize in the inspector a field GameObject will appear
// assign it just by dragging the game object there
public scriptA script; // this will be the container of the script
void Start(){
// first you need to get the script component from game object A
// getComponent can get any components, rigidbody, collider, etc from a game object
// giving it <scriptA> meaning you want to get a component with type scriptA
// note that if your script is not from another game object, you don't need "a."
// script = a.gameObject.getComponent<scriptA>(); <-- this is a bit wrong, thanks to user2320445 for spotting that
// don't need .gameObject because a itself is already a gameObject
script = a.getComponent<scriptA>();
}
void Update(){
// and you can access the variable like this
// even modifying it works
script.X = true;
}
just for completing the first answer
there is no need for
a.gameObject.getComponent<scriptA>();
a is already a GameObject so this will do
a.getComponent<scriptA>();
and if the variable you are trying to access is in children of the GameObject you should use
a.GetComponentInChildren<scriptA>();
and if you need a variable of it or method you can access it like this
a.GetComponentInChildren<scriptA>().nameofyourvar;
a.GetComponentInChildren<scriptA>().nameofyourmethod(Methodparams);
You can use static here.
here is the example:
ScriptA.cs
Class ScriptA : MonoBehaviour{
public static bool X = false;
}
ScriptB.cs
Class ScriptB : MonoBehaviour{
void Update() {
bool AccesingX = ScriptA.X;
// or you can do this also
ScriptA.X = true;
}
}
OR
ScriptA.cs
Class ScriptA : MonoBehaviour{
//you are actually creating instance of this class to access variable.
public static ScriptA instance;
void Awake(){
// give reference to created object.
instance = this;
}
// by this way you can access non-static members also.
public bool X = false;
}
ScriptB.cs
Class ScriptB : MonoBehaviour{
void Update() {
bool AccesingX = ScriptA.instance.X;
// or you can do this also
ScriptA.instance.X = true;
}
}
for more detail, you can refer singleton class.

Passing values from one script to another without a game object in the scene

I’ve found a lot of information on passing parameters from one script to another when a game object is present in the hierarchy. My problem is that my Transform object is created on the fly using Instantiate(myPrefab). Is there any way to access the position of myPrefab game object from another script?
You could store a reference to the instantiated GameObject after it has been instantiated (see example below). If there are more GameObjects, use a list to store them instead.
Call the InstantiateGO() and GetGOPosition() where it makes sense for you.
public class YourClass: MonoBehaviour
{
public GameObject yourPrefab;
public GameObject yourGameObject;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
}
void InstantiateGO()
{
yourGameObject = Instantiate(yourPrefab); // assign the newly instantiated GameObject to yourGameObject
}
void GetGOPosition()
{
var x = yourGameObject.position;
//Do something here
}
}

List.Count Raises Null Reference Exception [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I'm creating a 2D spaceship game in Unity. I have an object titled "Player" with this script attached to it. In the script, I have this class representing the player's ship:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList;
void Start()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
And this class (within the same script) representing a weapon:
public class Weapon
{
//properties here
}
Now, when I try to reference weaponsList to get List.Count using this code (from a different script), it throws a NullReferenceException, saying Object reference not set to an instance of an object:
Ship ship = GameObject.Find("Player").GetComponent<Ship>();
if (ship.weaponsList.Count >=2)
{
//do stuff
}
But any other property of ship i try to access works just fine. Can someone help? If you need additional context or code, please let me know and I'll make the necessary edits.
EDIT: The start method is special to Unity and is always called by default when the script initializes.
To avoid this error Add constructor to your class
public class Ship : MonoBehaviour
{
public Ship()
{
weaponsList = new List<Weapon>();
}
public List<Weapon> weaponsList;
void Start()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
Your weaponsList is null if Start() isn't called ... or it becomes null at some point. Change the public variable to become a public property to deny external callers to change the internal list:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList { get; private set; }
public Ship()
{
weaponsList = new List<Weapon>();
}
...
}
This will likely create compiler errors in other parts of your application. These errors are probably the reason why weaponsList becomes null.
In terms of better coding practice some more suggestions to change the property to this:
public IList<IWeapon> Weapons { get; private set; }
Change the List to an interface.
Change the Weapon to an IWeapon.
Use Pascal notation (Weapons, not weapons).
Avoid types in names: Weapons, not WeaponsList (that it is a list is obvious)
Ship does not contain weapons list.
You can avoid the exception with
Ship ship = GameObject.Find("Player").GetComponent<Ship>();
if (ship != null && ship.weaponsList != null && ship.weaponsList.Count >=2)
{
//do stuff
}
¿Is the method Start() been call?
Instead of putting the initialization of the weapons list in the void Start() put it in the constructor of the object. Then when the ship is created, the weapons list will always be initialized with a zero count. A constructor should always put the object in question into a valid state so it can be used. Sometimes, programmers create Init() or Start() methods to defer expensive logic until a method actually needs it, but in this case I would definitely put that initialization in the constructor.
The list is constructed when Start() is called. If Start() is not called before the list is accessed, your error will appear. My guess is that you are trying to access the list before Start() is called.
You should consider building a constructor for the Ship class and placing the initialization code there:
public class Ship : MonoBehaviour
{
public List<Weapon> weaponsList;
public Ship()
{
weaponsList = new List<Weapon>();
weaponsList.Add(new Weapon());
weaponsList.Add(new Weapon());
}
}
This constructor will be called as soon as objects of the class are created, and you won't have to call a method explicitly to get the object's properties constructed.

Categories