GetComponent() without a certain script name - C#

Hey fellas, I have an array containing different strings. These strings are named exactly after scripts I have put on a GameObject, and I am now trying to access the scripts through the GameObject using GetComponent(). My problem here is that I don’t know the exact scriptname before calling GetComponent(). Btw I’m using C#, that’s why it’s so challenging… Looks something like this

GameObject script_container = null;
string[] Names = new string[5];

void dostuff(name_number){

// The following doesn't work in C#, but it did in Java, I hope you can see where I am goin
script_container.GetComponent(Names[name_number]).use();
}

That was just a very quick example, hope I was clear enough

If you do not know the name of the class / script but you like to call a specific function you can use BroadcastMessage.

1 Like

Alternately, store an array of Types instead of an array of strings.

How do you post a new thread or do you have to just keep rplying to other peoples i have just joined the site?

Agree with KelsoMRK. For example:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public interface MyInterface{
     void use();
}
public class MyClass : MonoBehaviour{
    private List<MyInterface> interfaces = new List<MyInterface>();
   

    public void addMyInterface(MyInterface myInterface){
         interfaces.Add(myInterface);
    }

    public void dostuff(MyInterface myInterface){
        myInterface.use();	
    }
}

You create the class implementing MyInterface and add it in array interfaces.

Well yeah but how would that work if my function is in a different script?

I’ll try and look it up real quick

edit - can’t figure it out really

Ivenu Visuals, you can make a new thread if you want, just go to whatever sub-forum you like (f.x. scripting), scroll to the bottom of the page and select ‘new thread’

The same way it does when you use an array of strings? I’m not really sure what the question is.

I just don’t know what interface and list is, it’s all pretty confusing to me… Can’t find it on the net, do you know where to find documentation on it?

Plus there are a lot of different scripts… Perhaps I should link my source code so you can see what I mean

This is the file called ‘skillsystem_class_database’:

public class skillsystem_class_database {
	public GameObject spell_container;
	
	public string[] classes = new string[5];
	
	public string[] shaman_spells = new string[3];
	
	public void _init(){
		// Define names of classes, create more if you want
		classes[0] = "shaman";
		classes[1] = "brute";
		classes[2] = "archer";
		classes[3] = "assassin";
		classes[4] = "mage";
		
		shaman_spells[0] = "shaman_attack";
	}
}

This is the relevant part of my file called skillsystem_base, which is attached to my player:

void use_skill(int skillnumber){
	GameObject spell_container = class_db.spell_container
	spell_container.GetComponent(class_db.shaman_spells[skillnumber]).use();
}

And this is my spell script, which is attached to a prefab called spell_container:

public class shaman_attack : MonoBehaviour {

	void use(){
		Debug.Log("You Attacked");
	}
}

That’s basically it, I am simply looking for a way that the skillsystem_base script can access all my spell scripts without too much repitition. I can’t really use GetComponent in this case I think, don’t know what to do…

I am not that smart coder but maybe this can give you some hint for your system, this is just a simple example on how you could approach it

first a file that handle some data

// classe type
public enum Guild
{
	Shaman,
	Brute,
	Assassin,
	Archer,
	Mage
}

// action
public enum Action
{
	Attack,
	Defend,
	RunAway,
	DanceSamba
}

public struct CharacterData
{
	public Guild charGuild;
	public Action charAction;
	
	public CharacterData(Guild charGuild, Action charAction)
	{
		this.charGuild = charGuild;
		this.charAction = charAction;
	}
}

then have a base component to handle your characters ( be it one or many )

using UnityEngine;
using System.Collections;

public class CharacterBase : MonoBehaviour
{
	// just for test purpose
	public Guild currentGuild;
	public Action currentAction;
	
	public delegate void UseSkillEventHandler(CharacterData data);
	public event UseSkillEventHandler OnUseSkillEvent;
	
	private CharacterData characterData;
	
	void Awake()
	{
		ChangeData(currentGuild, currentAction);
	}
	
	//just for test
	void Update()
	{
		if(Input.GetKeyDown(KeyCode.Space))
		{
			ChangeData(currentGuild, currentAction);
			UseSkill();
		}
	}
	
	//call this from some logic script
	public void ChangeData(Guild guild, Action action)
	{
		characterData = new CharacterData(guild, action);
	}
	
	public void UseSkill()
	{
		if(OnUseSkillEvent != null)
			OnUseSkillEvent(characterData);
	}
}

then your skill action , be it all in one script or separate it doesn’t matter

using UnityEngine;
using System.Collections;

public class ShamanAction : MonoBehaviour
{
	private Guild thisGuild = Guild.Shaman;
	
	void Start()
	{
		// considering character base in on the same GameObject
		GetComponent<CharacterBase>().OnUseSkillEvent += UseSkill;
	}
	
	void OnDisable()
	{
		GetComponent<CharacterBase>().OnUseSkillEvent -= UseSkill;
	}
	
	void UseSkill(CharacterData data)
	{		
		if(thisGuild != data.charGuild)
			return;
		
		switch(data.charAction)
		{
			case Action.Attack:
				Attack();
				break;
			case Action.Defend:
				Defend();
				break;
			case Action.RunAway:
				RunAway();
				break;
			case Action.DanceSamba:
				DanceSamba();
				break;
		}
	}
	
	void Attack()
	{
		Debug.Log(GetType().ToString() + " Attack");
	}
	
	void Defend()
	{
		Debug.Log(GetType().ToString() + " Defend");
	}
	
	void RunAway()
	{
		Debug.Log(GetType().ToString() + " RunAway");
	}
	
	void DanceSamba()
	{
		Debug.Log(GetType().ToString() + " DanceSamba");
	}
}

same you can define a class archer too

using UnityEngine;
using System.Collections;

public class ArcherAction : MonoBehaviour
{
	private Guild thisGuild = Guild.Archer;
	
	void Start()
	{
		// considering character base in on the same GameObject
		GetComponent<CharacterBase>().OnUseSkillEvent += UseSkill;
	}
	
	void OnDisable()
	{
		GetComponent<CharacterBase>().OnUseSkillEvent -= UseSkill;
	}
	
	void UseSkill(CharacterData data)
	{		
		if(thisGuild != data.charGuild)
			return;
		
		switch(data.charAction)
		{
			case Action.Attack:
				Attack();
				break;
			case Action.Defend:
				Defend();
				break;
			case Action.RunAway:
				RunAway();
				break;
			case Action.DanceSamba:
				DanceSamba();
				break;
		}
	}
	
	void Attack()
	{
		Debug.Log(GetType().ToString() + " Attack");
	}
	
	void Defend()
	{
		Debug.Log(GetType().ToString() + " Defend");
	}
	
	void RunAway()
	{
		Debug.Log(GetType().ToString() + " RunAway");
	}
	
	void DanceSamba()
	{
		Debug.Log(GetType().ToString() + " DanceSamba");
	}
}

well that just an example how you could go about it using event in C# , that way you don’t care about get listing of your class , but do care about what you send to who

as i say that just something you can tinker with…

hope that help :wink:

try it put the character base and archer , shaman on same GO and test out…

after regarding how you want architecture your stuff and how you want call that well it may be more or less appropriate…

I would do this:

public class Spell : MonoBehaviour
{
    // base spell implementation

    public void Use()
    {
        // whatever your default use logic is
    }
}

public class ShamanAttackOne : Spell
{
    // override specific properties of base Spell

    public override void Use()
    {
        // override default behaviour, or add to it by calling base.Use() first
    }
}

public class SomeOtherClass : MonoBehaviour
{
    // use this instead of your string[] from before
    public Spell[] spellArray = new Spell[5];

    public void Use(int spellNum)
    {
        spellArray[spellNum].Use();
    }
}