我如何在monobehaviour类中重用代码?

时间:2019-04-18 17:47:37

标签: c# unity3d

首先,我想简短说明一下我的问题: 我该如何访问附加到另一个游戏对象的其他代码段,或者如何在不附加游戏对象的情况下初始化一个类。

当我在Unity中制作小型游戏时,我做了一个单元设计器,您在其中提供一些值,例如它携带多少武器,并计算该单元的状态(攻击,射程,速度等)。按ComputeValues()并在单击确认时保存。但是所有这些值都是通过单击按钮而不是直接输入来调整的。 (即,单击按钮并添加/减少1种武器)

但是,当我尝试在启动时添加一些模板单元时,它将无法工作。所以我做了一个CreateDesignWithValue()函数。它将所有相关数据作为输入,并使用上面的ComputeValues()来计算该对象的值。

问题是我正在尝试在球员课上这样做。但是我无法创建新的ShipDesigner,也无法将其设置为静态。我如何获得它?

2 个答案:

答案 0 :(得分:3)

在不知道您确切的用例以及您在说什么方法的情况下,我们只能给出一个非常笼统的答案:

并非所有类都必须为MonoBehaviour类型,这实际上取决于您的需求。

扩展方法

如果您对某种类型有某种计算,则可以使用Extension Methods,例如

public static class Vector3Extensions
{
    public static Vector3 DevideBy(this Vector3 a, Vector3 b)
    {
        return new Vector(a.x / b.x, a.y / b.y, a.z / b.z);
    }
}

您可以使用,例如

var newVector = transform.position.DevideBy(new Vector(1, 2, 3));

在所有其他课程中。

公共静态类

通常,您可以使用public static class来实现方法和存储应在任何地方(例如,

public static class Settings
{
    private static int _currentInt = 7;

    public static void SaySomething(string something)
    {
        Debug.Log(something);
    }

    public static void DoubleCurrentInt()
    {
        _currentInt *= 2;
    }

    public static int GetSquareOfCurrentInt()
    {
        return _currentInt * _currentInt;
    }
}

您现在可以像在任何地方一样致电

Settings.DoubleCurrentInt();
Settings.SaySomething(Settings.GetSquareOfCurrentInt.Tostring);

实例

当然,有时您不希望从任何地方都可以访问某些内容,因此您也可以简单地使用普通的实例化类来进行计算,例如

public class Settings
{
    private int _currentInt = 7;

    public Settings(int initialInt = 0)
    {
        _currentInt = initialInt;
    }

    public void SaySomething(string something)
    {
        Debug.Log(something);
    }

    public void DoubleCurrentInt()
    {
        CurrentInt *= 2;
    }

    public int GetSquareOfCurrentInt()
    {
        return CurrentInt * CurrentInt;
    }
}

因此您可以使用

private Settings settings;

private void Start()
{
    new Settings(3);
}

合一MonoBehaviour

private Settings settings;

private void Start()
{
    new Settings(26);
}

在另一个MonoBehaviour中,两者都有不同的实例,但是可以使用其中的所有实现分别计算和处理事情。

公共静态无效

您还只能在特定类型(static)的所有实例之间“共享”一种方法,还可以允许其他类型的方法(public

public class A : MonoBehaviour
{
    // A prefab only this specific component has access to
    [SerializeField] private GameObject prefab;

    // example for a kind of singleton pattern
    private static GameObject prefabSingleton;

    private void Start()
    {
        prefabSingleton = prefab;
    }

    public static void Spawn(int someIntToAssign, string someTextToAssign)
    {
        var obj = Instantiate(prefabSingleton)

;             componentReference = obj.GetComponent();

        componentReference.someIntField = someIntToAssign;

        componentReference.Getcomponent<Text>().text = someTextToAssign;
    }
}

您可以从其他类型调用它

A.Setup(someExampleReference, "Yeay!");

(在此示例中,您可以考虑在SomeExampleType中实现,尽管^^)

ScriptableObjects

您描述的内容听起来也像ScriptableObjectsTutorial)对您来说很有趣。

ScriptableObject是类似于预制件的资产,但可以存储值和方法。然后,您可以在MonoBehaviour组件的字段中引用它们,以根据值更改其行为,或作为容器在多个实例和不同类型之间共享该行为。

使用public方法的实例

最后但并非最不重要的是要做一个

public class A : MonoBehaviour
{
    [SerializeField] private Transform someObject;

    public Vector3 GetObjectPosition()
    {
        return someObject.position;
    }
}

并通过许多GetComponent或/和FindObjectOfType变体之一访问它,或者只需引用相应的组件即可,例如

public class B : MonoBehaviour
{
    // drag in via the Inspector
    public A AReference;

    private void Start()
    {
        // or get it on runtime e.g.
        AReference = GameObject.Find("ObjectWithA").GetComponent<A>();

        // or if there is only one e.g.
        AReference = FindObjectOfType<A>();


        Debug.Log(AReference.GetObjectPosition());
    }
}

答案 1 :(得分:0)

简短版本的答案:


我如何访问附加到另一个游戏对象的其他代码段: 为您要访问的脚本声明一个公共字段,例如public ExampleScript exampleScript;并将具有ExampleScript的游戏对象分配给检查器中的您的字段。


我如何在没有附带游戏对象的情况下初始化类:您不能像new ExampleScript();一样创建从MonoBehaviour派生的脚本实例。但是相反,您可以使用gameObject.AddComponent<ExampleScript>();将该脚本添加到现有的游戏对象中,并且可以从另一个脚本中访问该脚本,该脚本附加了与之类似的游戏对象:gameObject.GetComponent<ExampleScript>();