Type of Class/Script get component - need help please C#

Hello everyone/anyone.

I’m looking for a way of assigning a script/class variable.

The scenario I have is that I have an inventory and whatever is in slot one when I press the “1” button I want to call the “Use” function in the script and that will then do the things that item does.

However the problem I have is that I don’t know how to have a variable of a class or script so.

I don’t knnow if this is a good way of doing it, but I’ve assigned the script of the item to a gameObject so that when I go over the game object I essentially pick it up - this then assigns my Pocket1 GameObject variable in my inventory class with whatever I ran over, that all works fine, however I don’t know how to call a function from that assigned GameObject’s class FROM PlayerInventory.

If I need to elaborate further then I can try however I think that’s the long and short of the problem… I could work around thiss issue but that would require 20+ variables of each script all piled in the Player Inventory class and making this dynamic element obsolete, the only thing that I would do instead after that is jusst when I run over an item it allows the use of the corresponding item via a bool or something, however this seems tacky and probably redundant, maybe also unhelpful on the performance side of things…

so any advice or tips on this matter would be super appreciated. Thanks! :slight_smile:

I could be wrong, but are you trying to pull data from another script via another script?

It sounds like you need to use getComponent.

GetComponent allows you to change variabels from other class files. Example, an enemy and player script. When the enemy is hit you want to deal damage, so you control that through the player class, then if you hit it.

You do: enemy.dealDamage(50);

Unity3D reference on GetComponent: Unity - Scripting API: Component.GetComponent

I use GetComponent a lot already. But the problem is I’m trying to design this inventory class to be dynamic so it has a slot which it will try and use (call a use function in whatever class/script occupies a particular slot). My problem is I don’t know how to do this without just having to declare EVERY single possible script as a variable in the inventory.

I wanted to dynamically assign something like a generic variable.

I don’t think it exists but I thought maybe someone has a good idea alternative.

For Example…

	public void UpdatePocket1(GameObject NewPocket1)
	{
		Pocket1 = NewPocket1;
		
		Pocket1.transform.parent = PlayerGameObject.transform;
	}
	
	
	
	public void PlayerUseInventory()
	{
		if(ItemHasCooledDown == true)
		{
			if(Input.GetButtonDown("1 Key"))
			{
				Pocket1.GetComponent<ItemExample>().UseFunction();;
			}

Above is a working example but its all hard coded, and not dynamic, I want the GetComponent() to be whatever the item occupying the first slot is not what I’m telling it to be.

so simply, the above example, how do I do it more dynamically so that

Pocket1.GetComponent().UseFunction();;

that bit would have the script changed when

Pocket1 = NewPocket1;

that happens.

Have you tried using send message?

No, I hadn’t heard of it, just did a search but not found anything useful yet, seems like the kind of thing I should be looking at though, could you elaborate further perhaps with an example ? :slight_smile:

Well if you don’t want to have to get a component… But you know what gameobject has that component on it. You can simply do a

public void UpdatePocket1(GameObject NewPocket1)
{
    Pocket1 = NewPocket1;
    Pocket1.transform.parent = PlayerGameObject.transform;
}

public void PlayerUseInventory()
{
    if(ItemHasCooledDown == true)
    {
        if(Input.GetButtonDown("1 Key"))
        {
        	//You can SendMessage to a Gameobject.. It will call a Method on that gameobject. If it exists.
            Pocket1.gameObject.SendMessage("TheFunctionNameToCall")
        }

Thanks so much Eiznek.

I got a lot of “recoding” to do now.

in terms of performance is using SendMessage (not on an update) going to be expensive on performance, and is it more or less than the whole getcomponent stuff.

Thanks again.

Its a bit more expensive. If you know what component to use just use it. But if you want a more generic solution as your looking for and its not going to be used constantly I’d say its fine.

NGUI uses strictly SendMessage for button click events and many people consider it to be the only solution of GUI in Unity3d.

Yeah, I’ve made a lot of design choices with my GUI which has allowed me so far to not need SendMessage ( as I didn’t know about it). As I now know about it I’m gonna do a little bit of recoding here and then as its a better solution, thanks! :slight_smile:

Built in Unity3d GUI System is terrible on performance. For each element on the GUI it creates another draw call. So you can easily get to hundreds of draw calls from a relatively simple GUI System.

NGUI can condense it to much lower depending on how you create it. I think mine which is fairly complicated is like 50.

Have you scripted a base Item class that has a use function?

Once you do that, you can simply create new classes for each different item if your game with their own custom Use() function.

Then, all you need to know is that the gameobject has any type of Item component.

gameObject.GetComponent<Item>().Use(); //This will then call the correct Use function on whichever type of Item it is

I’d like to try that Mister-E2 as the SendMesssage way is giving me a strange error…

can you tell me what the abstract / base class is and what the class which inherits from it is called based on your example:

gameObject.GetComponent<Item>().Use(); //This will then call the correct Use function on whichever type of Item it is
public abstract class Item : MonoBehaviour 
{
     protected object owner;

    protected abstract void Start()
    {
    }

    protected abstract void Use()
    {
    }

 

}

public class Potion: Item
{

    protected float _strength;
    protected float _amountLeft;
    protected Color _color;

    protected override void Start()  
   { 
      _color = Color.white;
   } 

    protected override void Use()
    {
        if(_amountLeft <= 0)
         {
               Destroy(gameObject);
          }
    }

 

}
public class HealthPotion: Potion
{
     
    protected override void Start()  
   { 
      base.Start(); //Calls Potion.Start() for any initialisation you want
       _amountLeft = 100; //If these are initialised in Potion.Start(), they will now be overwritten by their values here
       _strength = 20;
       _color = Color.red; 
   } 

    protected override void Use()
    {
       (Player)owner.health+=_strength;
       _amountLeft -= _strength;

       base.Use();
    }

 

}