Define namespace with variable

I am trying to make a script in which I assign a component to my object and get a reference to it in my main script but the component is not always the same each time I use the main script.

public string abilityName;
public abilityName ability = GetComponent<abilityName>();

My scene:
Object: Ship1
Components: ShipScript, AbilityScript1

Object: Ship2
Components: ShipScript, AbilityScript5

ShipScript
-abilityName: ( )

GetComponent does not work that way. It expects a type of Type, not of string which you are passing into it.

Also in general this is not the way to do this. You should read up on using interfaces :
https://www.w3schools.com/cs/cs_interface.asp

Using an interface that represents ability in place of this would be the way to do this.

1 Like

I dont think this is quite what I am trying to achieve. The methods I use are defined in the ability component. In the interface example the name of the interface is static.
I want to give the name of the ability component in unity to the public abilityName string so that my main component knows which ability to access with GetComponent.

Another way would be to list all components of the object and select the second component somehow.

No it is exactly what you are trying to achieve, its just you are thinking about the problem and how to use interfaces to solve it in the wrong way. You dont want to specify types using strings and try and “find” that type, even if you could get that working it would be crazy ineffecient. You want to make this generically handled. The interfaces will facilitate that.

Here is an off the top of my head example:

public interface IAbility
{
   void SomeFunction();

    int SomeOtherFunction;
}

You then have any Ability specific code exist inside these functions. An interface is just a signature. You can then make each abilty component implement this interface:

public class SomeAbility : Monobehaviour, IAbility
{
      public void SomeFunction()
{
   // specifics to this ability here
}


}
public class SomeOtherAbility : Monobehaviour, IAbility
{
      public void SomeFunction()
{
   // specifics to this ability here
}


}

Then in your ability manager or whatever script actually uses the ability, you can get it like this:

IAbility ability = GetComponent<IAbility>();

You can then use the methods on that ability without caring what it is or what it does.

ability.SomeFunction();

And then you can do stuff with the ability without the manager having to care about or know what the ability does. This is the proper way to do this sort of generic programming, and is scalable and requires very little code duplication / boiletplate.

So I recommend looking into interfaces properly, your understanding of them is incorrect based on what you said in your last comment.

https://learn.unity.com/tutorial/interfaces#5c893ef9edbc2a141035529f

Good Luck! :slight_smile:

1 Like

Ok thanks I think I got it now! I kind of skipped the intermediate tutorials, I guess I should take a look at them.

1 Like

Yes for sure, its always best to get a comprehensive view of as much of the engine as you can :slight_smile:

I hope this proves helpful, you can achieve some really cool things using interfaces whilst keeping code nice and readable :slight_smile:

1 Like

I have one more question though, what if I have multiple abilities on my object? I can only reference to all of them with

IAbility ability = GetComponent<IAbility>()

How do I get an array of abilities?

Lots of ways to do that. I guess easist for you will be: just have one of the scripts on the object have a List of all IAbility on the object. And have a function return that list.

So you could have a component called CharacterControl.cs for example:

public class CharacterControl: Monobehaviour
{

   [SerializeField] List<IAbility> _characterAbilityList;


   public List<IAbility>  GetCharacterAbilityList()
{
   return _characterAbilityList;
}

}

And then you get that component first, then use its function to get all the ability components out as a list. Then you can just go through each one and use as needed.

Thx but I think I found a good way :wink:IAbility[] ability = GetComponents<IAbility>()

Does that actually work? As far as I was aware GetComponents did not work on interfaces while GetComponent did, hence why I suggested a more round-about approach. We have a bunch of interface helper scripts that we use to get things so I havent actually had to use either getcomponent or getcomponents on an interface in quite some time!

If GetComponents does indeed work with interfaces now, then that is actually news to me! Make sure to run it at runtime to ensure it actually is working as you expect :slight_smile: If so then fantastic! If it can be done in 1 line then always try to do so if it is readable :slight_smile: