Как я могу повторно использовать код в monobehaviour классе? - PullRequest
1 голос
/ 18 апреля 2019

Сначала я хотел бы дать краткую версию своего вопроса: как я могу получить доступ к другим частям кода, прикрепленным к другому игровому объекту, или как я могу инициировать класс без привязки игрового объекта.

Когда я делал небольшую игру в Unity, я создал конструктор юнитов, в котором вы указываете какое-то значение, например, сколько оружия у него есть, и статус этого юнита (атака, дальность, скорость и т. Д.) Будет рассчитываться с помощью ComputeValues ​​() и сохраняется при нажатии подтверждения.Но все эти значения были скорректированы путем нажатия кнопки вместо прямого ввода.(Т.е. нажмите кнопку и добавьте / уменьшите 1 оружие)

Однако, когда я пытаюсь добавить какой-либо шаблонный модуль при запуске, он не будет работать.Поэтому я сделал функцию CreateDesignWithValue ().Который принимает входные данные для всех связанных данных и использует вышеуказанную функцию ComputeValues ​​() для вычисления значения для этого объекта.

Проблема в том, что я пытаюсь сделать это в классе игрока.Но я не могу создать новый ShipDesigner, и я не могу установить его на статический.Как я могу получить к нему доступ?

Ответы [ 2 ]

3 голосов
/ 18 апреля 2019

Не зная вашего точного варианта использования и методов, о которых вы говорите, мы можем дать только очень общий ответ:

Не все классы должны быть типа MonoBehaviour это действительно зависит от ваших потребностей.

Методы расширения

Если у вас есть определенный расчет для определенного типа, вы можете использовать Методы расширения вроде

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);

1027 * Инстансы * Конечно, иногда вы не хотите, чтобы что-то было доступно отовсюду, поэтому вы можете просто иметь обычный экземплярный класс для своих вычислений, например 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

То, что вы описали, также звучит как ScriptableObjects ( Tutorial ) может быть интересным для вас.

ScriptableObjects являются своего рода активами, похожими на префабы, но могут хранить значения, а также методы. Вы можете ссылаться на них в полях 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());
    }
}
0 голосов
/ 18 апреля 2019

Ответ коротких версий:


Как получить доступ к другим фрагментам кода, прикрепленным к другому игровому объекту : Объявите открытое поле для скрипта, к которому вы хотите обратиться, например, public ExampleScript exampleScript; и присвойте игровому объекту, имеющему ExampleScript, свое поле в инспекторе.


как я могу инициализировать класс без привязки игрового объекта : Вы не можете создать экземпляр сценария, производного от MonoBehaviour, как new ExampleScript();. Но вместо этого вы можете добавить этот сценарий к существующему игровому объекту с помощью gameObject.AddComponent<ExampleScript>();, и вы можете получить доступ к этому сценарию из другого сценария, к которому прикреплен тот же самый игровой объект, например: gameObject.GetComponent<ExampleScript>();

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...