Home > Mobile >  Getting a script from a gameobject using a string Unity
Getting a script from a gameobject using a string Unity

Time:10-25

I am working on a simple weapons controller for my FPS game and have come across an issue while trying to make it dynamic. What I want to happen when the player picks up a weapon is for the weapons stats and effects to be set as default. To do this each weapon has a script which is

weapon.name "Stats"

But I'm having issues referencing said script. Right now, this is what my code looks like:

string weaponScriptName = weapon.name   "Stats";
weapon.GetComponent<weaponScriptName>().UseWeapon();

where weapon represents the currently equipped weapon's gameobject. Obviously, this doesn't work and various implementations that I've found on the Unity help pages only cause more errors. What can I do to solve this issue?

Thank you.

CodePudding user response:

If i got it correctly, you want to do something like GetComponent<"Transform">() ? If so, you should do GetComponent("Transform"); instead

CodePudding user response:

GetComponent has multiple overloads.

  • There is the generic version you refer to - the most commonly used one

    T GetComponent<T>()
    

    which you can only use with a compile time constant type parameter such as

    var renderer = GetComponent<Renderer>();
    
  • There is one using a dynamic Type

     Component GetComponent (Type type)
    

    like

     // Just an example, there are many ways of getting a type
     var type = typeof(Renderer);
     var renderer = (Renderer) GetComponent(type);
    
  • And finally there is one taking a string

    Component GetComponent (string typeName);
    

    like

    // Again just an example, there are many ways of getting type names
    // Especially when dealing with multiple assemblies you might even have to use the AssemblyQualifiedName
    var renderer = (Renderer) GetComponent("Renderer");
    

Note that for any of the dynamic versions you either have to type cast or if it is enough to have only a generic Component reference you can use it of course.


However, as said if anyhow possible don't use string versions at all!

It is always slow and error prone. Rather use e.g. some common base class or interface, or use an enum or Dictionary to decide what to do for which state.

So I would rather have e.g.

public interface IWeapon
{
    void UseWeapon();
}

and then every of your different weapons can implement this interface

public class WeaponA : MonoBehaviour, IWeapon
{
    public void UseWeapon ()
    {
        Debug.Log("Used Weapon A");
    }
}

public class WeaponB : MonoBehaviour, IWeapon
{
    public void UseWeapon ()
    {
        Debug.Log("Used Weapon B");
    }
}

and your code would simply be

var weapon = someObject.GetComponent<IWeapon>(). UseWeapon();

Or if your weapons all share some common implementation such as pickup etc rather have a common base class

public abstract class BaseWeapon : MonoBehaviour
{
    // Everything that all weapons share as behavior and properties

    // every subclass HAS TO implement and override this method
    public abstract void UseWeapon ();

    // Alternatively if there even is some common behavior
    // subclasses CAN but don't have to override this
    //public virtual void UseWeapon ()
    //{
    //    // Implementation that is the default behavior
    //}
}

And then

public class WeaponA : BaseWeapon
{
    public override void UseWeapon ()
    {
        Debug.Log("Used Weapon A");

        // If using virtual before then this class IGNORES and fully overwrites the default implementation
    }
}

public class WeaponB : BaseWeapon
{
    public override void UseWeapon ()
    {
        // If using virtual and you WANT the default behavior then add
        //base.UseWeapon();

        Debug.Log("Used Weapon B");       
    }
}

and your code would simply be

var weapon = someObject.GetComponent<BaseWeapon>(). UseWeapon();
  • Related