简体   繁体   English

我可以从非单一行为脚本中访问单一行为脚本吗?

[英]Can i access a monobehaviour script from within a non monobehaviour script?

I'm trying to access a monobehaviour script from within a non monobehaviour script and haven't had any luck yet.我正在尝试从非单一行为脚本中访问单一行为脚本,但还没有成功。 These two classes need to stay as they are as changing them will break a lot of functionality so i cant create an instance and cant attach to a gameobject to drag and drop.这两个类需要保持原样,因为更改它们会破坏很多功能,因此我无法创建实例并且无法附加到游戏对象以进行拖放。

Any ideas?有任何想法吗?

public class myClass1 : monoBehaviour
{
  public String text = "hello";
}

public class myClass2
{
  private myClass1 monoClass = new myClass1();

  private void Start()
  {
    Debug.Log(monoClass.text);
  }
}
//THIS DOES NOT WORK

Yes, but... 对,但是...

You can't call new on any script that inherits from MonoBehaviour due to requiring being attached to a game object. 由于需要附加到游戏对象,因此无法在任何从MonoBehaviour继承的脚本上调用new So you can't create references, but you can absolutely pass them around: 所以你不能创建引用,但你绝对可以传递它们:

public class myClass1 : monoBehaviour
{
  public String text = "hello";
}

public class myClass2
{
  private void Start(myClass1 mc1)
  {
    Debug.Log(mc1.text);
  }
}

Now, myClass2#Start is going to be difficult to call in this example, but it will compile. 现在, myClass2#Start在这个例子中很难调用,但它会编译。

I do stuff like this in my projects all the time. 我总是在我的项目中做这样的事情。 I usually have one class that is a MonoBehaviour component that's attached to the main camera with a static instance field that I can reference from anywhere else, though most of the non-MB scripts don't deal with Unity objects most of the time (they only hold data and one of the manager classes handle updating game objects with that data by maintaining a dictionary between them). 我通常有一个MonoBehaviour组件,它附加到主摄像机,带有我可以从其他任何地方引用的静态实例字段 ,尽管大多数非MB脚本大多数时间都不处理Unity对象(它们只保存数据,其中一个管理器类通过在它们之间维护字典来处理用该数据更新游戏对象。

Though sometimes the object holds its own GO reference (the result of trying different things to see what worked or wanting to avoid a dictionary lookup--regardless of if it was efficient or not). 虽然有时候对象拥有自己的GO引用(尝试不同的东西以查看哪些有效或者想要避免字典查找的结果 - 无论它是否有效)。

Wow I did not know you could pass them as parameters. 哇我不知道你可以将它们作为参数传递给我们。 This is good to know, however in my project this wouldn't have worked as I was calling the method from another non-MB script which did not have the the MB script referenced anywhere for me to pass it on. 这很好知道,但是在我的项目中这不会起作用,因为我从另一个非MB脚本中调用该方法,该脚本没有任何地方引用MB脚本来传递它。

What i did was create a empty gameobject and attach the script as a component then use the class from there across the non_MB script. 我所做的是创建一个空的游戏对象并将脚本作为一个组件附加,然后在非MB脚本中使用该类。

3 lines of code: 3行代码:

GameObject obj = new GameObject();
obj.AddComponent<MyScript1>();
MyScript1 myscript1 = obj.GetComponent<MyScript1>();

Works great as gameobjects are not restricted to MB. 由于游戏对象不限于MB,因此效果很好。

Hope this helps someone else out there 希望这有助于其他人

As an alternative to the GetComponent approach from @Zaine I'd like to throw the singleton pattern into the pool of possible answers: 作为GetComponent方法的替代方法,我想将单例模式放入可能的答案池中:

public class SomeClass : MonoBehaviour {
    private static SomeClass _instance;
    public String text = "singleton text";

    public static SomeClass Instance { get { return _instance; } }
    private void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Destroy(this.gameObject);
        } else {
            _instance = this;
        }
    }
}

It only works if you have exactly one of these scripts. 它只有当你有完全这些脚本作品之一 But from all other scripts, you can access it easily: 但是从所有其他脚本中,您可以轻松访问它:

public class SomeOtherClass : MonoBehaviour {
     private void Start(myClass1 mc1)
     {
         Debug.Log(SomeClass.Instance.text);
     }
}

Sometimes What I did is create an interface that can receive Component object for Non-Monobehaviour class.有时我所做的是创建一个interface ,该接口可以Non-Monobehaviour class 接收Component object。

public interface IComponentReceiver<T> where T: Component{
    void AddComponent(T pComponent);
}

public class ExampleNonMonoBehaviour : IComponentReceiver<CharacterController>{
    private CharacterController _cc;
    public void AddComponent(CharacterController cc)
    {
     _cc = cc;
    }
}

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

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