Как вызвать функцию из другого скрипта, который вызывает функцию сопрограммы в Unity C #? [Дубликат]

Я бы использовал решение, которое выполняет сопоставление путем преобразования в строку ...

Вы должны написать простую функцию, реализующую алгоритм поиска Knuth-Morris-Pratt . Это будет самый быстрый простой алгоритм, который вы можете использовать для поиска правильных индексов. (Вы можете использовать Boyer-Moore , но для этого потребуется больше настроек.

После того как вы оптимизировали алгоритм , вы можете попытаться найти другие виды оптимизации. Но вы должны начать с основ.

Например, текущим «самым быстрым» является решение Locate от Jb Evian.

если вы посмотрите на ядро ​​

    for (int i = 0; i < self.Length; i++) {
            if (!IsMatch (self, i, candidate))
                    continue;

            list.Add (i);
    }

. После соответствия под алгоритма он начнет находить совпадение в i + 1, но вы уже знаете, что первым возможным совпадением будет i + кандидат .Length Так что если вы добавите

i += candidate.Length -2; //  -2 instead of -1 because the i++ will add the last index

, это будет намного быстрее, если вы ожидаете много вхождений подмножества в надмножество. (Бруно Конде уже делает это в своем решении)

Но это всего лишь половина алгоритма KNP, вы также должны добавить дополнительный параметр к методу IsMatch, называемому numberOfValidMatches, который будет выходным параметром.

это разрешило бы следующее:

int validMatches = 0;
if (!IsMatch (self, i, candidate, out validMatches))
{
    i += validMatches - 1; // -1 because the i++ will do the last one
    continue;
}

и

static bool IsMatch (byte [] array, int position, byte [] candidate, out int numberOfValidMatches)
{
    numberOfValidMatches = 0;
    if (candidate.Length > (array.Length - position))
            return false;

    for (i = 0; i < candidate.Length; i++)
    {
            if (array [position + i] != candidate [i])
                    return false;
            numberOfValidMatches++; 
    }

    return true;
}

Немного рефакторинга, и вы можете использовать numberOfValidMatches в качестве переменной цикла и переписать цикл Locate с помощью while, чтобы избежать -2 и -1. Но я просто хотел пояснить, как вы могли бы добавить алгоритм KMP.

5
задан Alex 23 May 2016 в 19:41
поделиться

2 ответа

public class Rule : MonoBehaviour{}
Rule rule2 = new Rule();

Вы не можете использовать ключевое слово new для создания нового экземпляра, если вы наследуете его из MonoBehaviour.

Вы должны получить исключение, говорит :

Вы пытаетесь создать MonoBehaviour, используя ключевое слово 'new'. Это запрещено. MonoBehaviours можно добавлять только с помощью AddComponent (). Кроме того, ваш скрипт может наследовать от ScriptableObject или вообще никакого базового класса

. Ваш код работал бы, если у вас public class Rule {}, но у вас есть public class Rule : MonoBehaviour {}.

Создание нового экземпляра класса, полученного из MonoBehaviour:

Пример класса:

public class Rule : MonoBehaviour
{
    public Rule(int i)
    {

    }
}

Если вы наследуете MonoBehaviour, вы должны либо используйте GameObject.AddComponent или Instantiate для создания нового экземпляра.

Rule rule2 = null;
void Start()
{
  rule2 = gameObject.AddComponent<Rule>();
}

ИЛИ

public Rule rulePrefab;
Rule rule2;
void Start()
{
    rule2 = Instantiate(rulePrefab) as Rule;
}

Если скрипт Rule уже существуют и прикреплены к GameObject, вам не нужно создавать / добавлять / создавать новые экземпляры этого сценария. Просто используйте функцию GetComponent, чтобы получить экземпляр скрипта из GameObject, к которому он присоединен.

Rule rule2;
void Start()
{
    rule2 = GameObject.Find("NameObjectScriptIsAttachedTo").GetComponent<Rule>();
}

Вы заметите, что вы не можете использовать параметр в конструкторе, когда вы выводите свой скрипт из MonoBehaviour .



Создание нового экземпляра класса, который НЕ выводится из MonoBehaviour:

Пример класса: (Обратите внимание, что он не является результатом " MonoBehaviour "

public class Rule
{
    public Rule(int i)
    {

    }
}

Если вы не наследуете от MonoBehaviour, вы должны использовать ключевое слово new для создания нового экземпляра. Теперь вы можете использовать параметр в конструкторе, если вы хотите.

Rule rule2 = null;

void Start()
{
    rule2 = new Rule(3);
}

EDIT:

В последней версии Unity создается новый экземпляр скрипта, который наследует от MonoBehaviour с помощью new может не дать вам ошибку и не может быть null слишком , но все функции обратного вызова не будут выполняться . К ним относятся функции Awake, Start, Update и другие. , вы все равно должны сделать это правильно, как указано в начале этого ответа.

15
ответ дан Programmer 19 August 2018 в 08:11
поделиться
  • 1
    Не знал этого, спасибо. Это выглядит как действительно странная конвенция. – Alex 23 May 2016 в 20:10
  • 2
    Пользователи @Alex New Unity испытывают то, что включает меня. О, и обязательно сделайте то же самое, создав экземпляр CatchManager и Net, которые находятся внутри скрипта Rule – Programmer 23 May 2016 в 20:14
  • 3
    Еще раз спасибо, все остальное - на самом деле твердые объекты с персоналом prefabs n '. Не знаю, почему я думал, что могу пойти только с классом в случае с Правилом :) – Alex 23 May 2016 в 21:36

Просто следите за тем, как я это сделал и почему:

  1. Я больше не наследую класс Rule из MonoBehaviour, чтобы избежать отслеживания создания и удаления объектов gameObjects, которая оказалась болью.
  2. Поскольку метод Invoke не существует в родовых классах, я заменил его отражением, как описано здесь здесь
2
ответ дан Community 19 August 2018 в 08:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: