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();