简体   繁体   English

Unity-通过编辑器的引用传递脚本,在运行时在对象上实例化它

[英]Unity - passing script by reference from editor, instantiating it on object at runtime

So basically I want to end with several ingame objects, each having few .cs scripts with monobehaviour. 因此,基本上我想以几个游戏内对象结束,每个对象都具有很少的具有单一行为的.cs脚本。 (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;

    }

}

I want to attach the scripts to objects dynamically at run-time. 我想在运行时将脚本动态附加到对象。

he AddComponent function is used to attach scripts to GameObjects. AddComponent函数用于将脚本附加到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. 问题是,我不知道它是MyScript1还是MyScript2。 I dont want it to be hardcoded, but modifiable via editor/ingame UI. 我不希望它被硬编码,但可以通过编辑器/ ingame UI进行修改。

I think that you are looking for AddComponent that can take string as param. 我认为您正在寻找可以将string作为参数的AddComponent 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 . 去年,我做了一个新的名为AddComponentExt扩展方法,您可以在这里获得它。 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. 这就是反射的用途。

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. 这并不意味着是一个实际的解决方案,我想说的是,可能有(更好)的方法来建立整个结构,以使您完全没有这个问题。

For anyone reading this post now, the method posted by the OP works well in the editor mode but it won't allow for the game to be built because MonoScript is exclusive to UnityEditor. 对于现在阅读此帖子的任何人,OP发布的方法在编辑器模式下都可以很好地工作,但是由于MonoScript是UnityEditor专有的,因此不允许构建游戏。 Instead try making an abstract class and methods inheriting from that. 而是尝试使abstract class和方法继承自class then use GetComponent<MyAbstractClass>().MyMethod(); 然后使用GetComponent<MyAbstractClass>().MyMethod(); to run your command. 运行您的命令。 Finally you need to attach the script you want on the same GameObject containing the "parent" script. 最后,您需要将所需的脚本附加到包含“父”脚本的同一GameObject上。

Here is an example: 这是一个例子:

public abstract class TestSkill : MonoBehaviour
{
    public abstract void Activate();
}

public class TestFireball : TestSkill
{
    public override void Activate()
    {
        Debug.Log("Do Stuff");
    }
}

public class TestSkillBook : MonoBehaviour
{

    private TestSkill script;

    void Start ()
    {
        script = gameObject.GetComponent<TestSkill>();
        script.Activate();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM