0

So basically I want to end with several ingame objects, each having few .cs scripts with monobehaviour. (different set of scripts on each object)

party of characters with their skills

Those scripts on each character can vary over time

characters learning new skills/abandoning old

So when the game starts, I want to attach the scripts to objects dynamically at runtime

based on player decision in skill tree

Is there any way how can I do this without using reflection?

EDIT: It seems I found solution how to make it work without reflection

public class TestSkill : MonoBehaviour {}

public class TestFireball : TestSkill {}
public class TestMeleeAttack : TestSkill {}

public class TestSkillBook : MonoBehaviour {

    public MonoScript script;

    void Start () {

        System.Type t = script.GetClass();

        TestSkill skill = gameObject.AddComponent(t) as TestSkill;

    }

}
7
  • I'm finding it hard to understand your question. Could you please try to rewrite it more clearly? (The bold and italics aren't helping make anything clearer at the moment, either.) Commented Jun 6, 2018 at 20:59
  • The problem is on my side, I am not very good at explaining :) Basically, I want to dynamically attach scripts to object, but I dont know beforehand which scripts I will attach. Commented Jun 6, 2018 at 21:06
  • Do you understand now or should I clarify more? Commented Jun 6, 2018 at 21:08
  • Not really, I'm afraid. Giving a concrete example with code would help a lot. Commented Jun 6, 2018 at 21:14
  • My code have thousands of lines. But I will try from different angle. I know how to create a class with gameobject variable, put it on prefab, fill the variable in unity editor and then pass it to another script runtime. I would like to do the same with script type. Commented Jun 6, 2018 at 21:18

2 Answers 2

2

I want to attach the scripts to objects dynamically at run-time.

he AddComponent function is used to attach scripts to GameObjects.

Your Object

public GameObject yourgameObject;

Attach script to it:

yourgameObject.AddComponent<YourScript>();

EDIT:

The problem is, I dont know if it will be MyScript1 or MyScript2. I dont want it to be hardcoded, but modifiable via editor/ingame UI.

I think that you are looking for AddComponent that can take string as param. There used to be one like this:

public Component AddComponent(string className);

but it was deprecated years ago. I made a new one called AddComponentExt as extension method last year and you can get it here. It can be used like this:

yourgameObject.AddComponentExt<"YourScript">();

You can add script even if it doesn't exist yet. You will get run-time error instead of compile-time error in that case.

Is there any way how can I do this without using reflection?

No, you can't do this without reflection since it doesn't exist yet. That's what reflection is used for.

Sign up to request clarification or add additional context in comments.

19 Comments

Yes, but how do I get reference to MyScript?
Let's say your script is called or named YourScript, you attach it to your GameObject with yourgameObject.AddComponent<YourScript>();. Which part is confusing to you?
The problem is, I dont know if it will be MyScript1 or MyScript2. I dont want it to be hardcoded, but modifiable via editor/ingame UI.
And I havent found a way how to pass it like other variable types
Thank you for extension method. Just tu clarify: Why is it possible to pass a variable from editor through gameobject with some class to runtime, but I cant so the same with script? Like passing it through something like MonobehaviorScript variable?
|
0

Since this doesn't fit into the comments of Programmers answer, some example and to clarify on what you can/must do:

// The component to add
public class B : MonoBehaviour
{
    public void TestCall()
    {
        Debug.Log("Success");
    }
}




public class A : MonoBehaviour
{
    public string ToAddName = "B";

    private void Start()
    {
        System.Type t = System.Type.GetType(ToAddName);
        AddComponent(t);    // This does successfully add the component (assuming it exists)

        Debug.Log(t.GetType());    // This will give out "System.MonoType"

        // This doesn't work since it is not known that this is actually "B", not "MonoScript"
        GetComponent(t).TestCall();

        // What is possible is this, requires hardcoding the method name though:
        System.Reflection.MethodInfo mI = t.GetMethod("TestCall");
        var c = GetComponent(t);
        mI.Invoke(c, null);    // null because "TestCall" doesn't take params
    }
}

This is not meant to be an actual solution, I'd rather say that there is probably a (better) way to set up your whole construct so that you don't have this problem at all.

4 Comments

Works for custom classes but won't work with built-in ones like AudioSource. string ToAddName = "AudioSource"; will fail
@PerformanceFreak This wasn't meant to be an actual answer, but some example code refering to the comments of Programmers answer, should have wrote that. Otherwise OP seemingly only wants to add his custom components (or at least those are the problematic ones).
@GunnarB. It seems I found solution that doesnt need reflection. Check my edit.
@Colp That is a solution I mentioned in the comments of Programmers answer: casting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.