Как сделать рывок unity

Добавил пользователь Alex
Обновлено: 04.10.2024

public int modes = 0; // переменная для определения режимов стрельбы
public bool canShoot = true; // триггер
public int currentMode; // текущий режим стрельбы
public int bulletsToGo; // переменная необходимая для реализации режима стрельбы очередями с отсечкой по 3 выстрела

public void Awake()
audio = gameObject.AddComponent(); // добавляем компонент AudioSource
anim = gameObject.GetComponent(); // ищем компонент Animation у нашего оружия (да да, именно ищем, а не добавляем)

anim.wrapMode = WrapMode.Loop; // настраиваем компонент Animation, а конкретно зацикливаем анимации
anim[reload.name].wrapMode = WrapMode.Clamp; // анимацию перезарядки останавливаем на последнем кадре после воспроизведения
anim[fire.name].wrapMode = WrapMode.Clamp; // анимацию выстрела останавливаем на последнем кадре после воспроизведения
anim[idle.name].layer = -1; // меняем слой анимации бездействия, это нам позволяет воспроизводить другие анимации поверх этой
anim.Stop(); // останавливаем все анимации

GunModes(SingleShoot, BurstAuto, FullAuto); // используем метод GunModes для определения какие режимы стрельбы у нас доступны

int B = 0; // временная переменная для определения текущего режима стрельбы
while (BitRead(modes, B) == 0) // если данный режим не поддерживается, то проверяем следующий режим
currentMode = B; // как найдем первый поддерживаемый режим назначаем его текущим

gunAmmo = maxAmmoInClip; // кладем в магазин патроны в колистве емкости магазина
>

public void Update ()
// анимация бездействия воспроизводится все время
anim.CrossFade(idle.name);

// при нажатии на левую кнопку мыши и если нам разрешено стрелять
if (Input.GetMouseButtonDown(0) & canShoot) // выключаем триггер (то есть уже стрелять нельзя)
canShoot = false;
// если текущий режим стрельбы очередью с отсечкой по 3 выстрела, то переменной bulletsToGo
// присваиваем значение равное 2 (то есть 0, 1, 2 - три выстрела)
if (currentMode == 1)
// стреляем
Shoot();
>

// Метод стрельбы
public void Shoot () // уменьшаем количество патронов в магазине
gunAmmo--;
// воспроизводим звук выстрела
audio.PlayOneShot(fireSound);
// воспроизводим анимацию выстрела
anim.CrossFadeQueued(fire.name, 0.3f, QueueMode.PlayNow);

Vector3 DirectionRay = Camera.mainCamera.transform.TransformDirection(Vector3.forward);
RaycastHit hit;
Debug.DrawLine(Camera.mainCamera.transform.position,DirectionRay*range,Color.red);

if(Physics.Raycast(Camera.mainCamera.transform.position,DirectionRay, out hit, range))
if(hit.collider)
Debug.Log("Shoot in |" + hit.collider.name + "| at a distance |" + hit.distance + "|");
>
>
// (услови №1) если патронов в магазине меньше 1.
if (gunAmmo 0)
// то перезаряжаем оружие
StartCoroutine(CoroutineReload());
>else // то переходим к сопрограмме связанной со стрельбой
StartCoroutine(CoroutineShoot());
>
>

// index0 - стрельба одиночными
// index1 - стрельба очередью с отсечкой по 3 выстрела
// index2 - непрерывными очередями
public void GunModes (bool index0, bool index1, bool index2) if (index0)
if (index1)
if (index2)
>

// index0 - переменная для определения режимов стрельбы
// index1 - режим стрельбы (0, 1, 2)
public int BitOn (int index0, int index1) return index0 | (1 > B;
>

// index0 - режим стрельбы (0, 1, 2)
public int ChangeGunMode (int index0) if (BitRead(modes, index0) == 1)
return index0;
>

// сопрограмма стрельбы
public IEnumerator CoroutineShoot() // текущий режим стрельбы
switch (currentMode) // стрельба одиночными
case 0:
// небольшая задержка
yield return new WaitForSeconds(0.1f);
// разрешаем стрелять
canShoot = true;
// выходим с сопрограммы
yield break;
break;

// стрельба очередью с отсечкой по 3 выстрела
case 1:
// небольшая задержка
yield return new WaitForSeconds(0.1f);
// если еще не все выстрелы произвели.
if (bulletsToGo > 0) // то уменьшаем нашу переменную
bulletsToGo--;
// и еще раз стреляем
Shoot();
>else // то небольшая задержка
yield return new WaitForSeconds(0.1f);
// разрешаем стрелять
canShoot = true;
// выходим с сопрограммы
yield break;
>
break;

// стрельба очередью
case 2:
// небольшая задержка
yield return new WaitForSeconds(0.1f);
// если зажата левая кнопка мыши
if (Input.GetButton ("Fire1"))
// стреляем
Shoot();
>else < // если не зажата левая кнопка мыши.
// включаем триггер (стрелять можно)
canShoot = true;
// выходим с сопрограммы
yield break;
>
break;
>
>

// сопрограмма перезарядки
public IEnumerator CoroutineReload()

anim.PlayQueued(reload.name);
yield return new WaitForSeconds(0.2f);
audio.PlayOneShot(reloadSound);

// делаем задержку равную длине анимации перезарядки + 0.5 секунд
yield return new WaitForSeconds(reload.length + 0.5f);

// вводим временную переменную (она служит для красоты перезарядки)
var ammo = 0;
// если у нас были патроны в магазине то нашей временной переменной присваиваем значение оставшихся патронов
if (gunAmmo > 0)
// (условие №2)если дополнительных патронов меньше чем максимальная емкость магазина.
if (maxAmmoInClip > maxAmmo) // (условие №3) если количество дополнительных патронов + оставшихся в магазине больше максимальной емкости магазина.
if (maxAmmo + ammo > maxAmmoInClip) // то кладем в магазин патроны в каличестве максимального его объема
gunAmmo = maxAmmoInClip;
// а дополнительные патроны считаем по формуле: дополнительные патроны = дополнительные патроны + оставшиеся патроны - объем магазина
maxAmmo = maxAmmo + ammo - maxAmmoInClip;
>else // то кладем в магазин патроны в количетсве равное дополнительные патроны + те что остались
gunAmmo = maxAmmo + ammo;
// а дополнительные патроны приравниваем нулю
maxAmmo = 0;
>
>else // то кладем в магазин патроны в каличестве максимального его объема
gunAmmo = maxAmmoInClip;
// а дополнительные патроны считаем по формуле: дополнительные патроны = дополнительные патроны - объем магазина + оставшиеся
maxAmmo = maxAmmo - maxAmmoInClip + ammo;
>
// включаем триггер (стрелять можно)
canShoot = true;
>
>

Захотелось мне сделать двухмерную игру. Благо, в Unity3D недавно появился соответствующий инструментарий. Однако, когда я дошел до момента, когда мне нужно было просто повернуть спрайт к какой-то позиции, я жутко разочаровался - все функции, принимающие в качестве параметров местоположение, и возвращающие соответствующее вращение (Quaternion.LookRotation, Quaternion.FromToRotation, Transform.LookAt), ориентированы исключительно на трехмерное пространство, а в трехмерном пространстве, если один объект повернут ко второму, это значит, что его вектор forward (вектор, представляющий ось Z локальной системы координат объекта) "смотрит" на цель.

В двухмерной же игре этот вектор как раз должен выступать осью вращения. Получается, если вы поворачиваете один спрайт к другому стандартными методами, то он "стает на ребро", в результате чего его в принципе не видно. Поэтому, нужен другой подход.

Видео-урок и пример как использовать

Добавить комментарий Отменить ответ

Мы - Wow Games,
команда, которая разрабатывает игры, а также приложения, помогающие Вам делать свои игры. Мы поможем, если у Вас возникли проблемы, и мы всегда рады новым участникам в нашей команде. Не бойтесь задавать вопросы, мы всегда на них ответим.

Всем привет!
Мы - Wow Games, команда, которая разрабатывает игры, а также приложения, помогающие Вам делать свои игры. Мы поможем, если у Вас возникли проблемы, и мы всегда рады новым участникам в нашей команде. Не бойтесь задавать вопросы, мы всегда на них ответим.

Самый простой способ сериализации для строк или других блоков с переменным размером - это сериализовать сначала размер при сериализации целых чисел, а затем просто скопировать содержимое в выходной поток.

При чтении сначала читайте размер , затем выделите строку и затем заполните ее, прочитав правильное количество байтов из потока.

Альтернативой является использование разделителя и экранирования, но для этого требуется больше кода и медленнее как при сериализации, так и при десериализации ( однако результат может быть сохранен для чтения человеком).

2 ответа

Есть много способов подождать в Единстве. Это действительно просто, но я думаю, что стоит обратить внимание на большинство способов сделать это:

далеко простейший путь. Поместите весь код, который вам нужно подождать некоторое время в функции сопрограммы, вы можете подождать с помощью WaitForSeconds . Обратите внимание, что в функции coroutine вы вызываете функцию с помощью StartCoroutine(yourFunction) .

Пример ниже повернет на 90 град, подождите 4 секунды, поверните на 40 градусов и подождите 2 секунды, а затем, наконец, поверните вращать 20 град.

Единственная разница между WaitForSeconds и WaitForSecondsRealtime заключается в том, что WaitForSecondsRealtime использует немасштабированное время ожидания, что означает, что при приостановке игры с Time.timeScale функция WaitForSecondsRealtime не будет затронута, но WaitForSeconds будет.

Подождите и вы сможете увидеть, сколько времени вы ждали:

3. С сопрограммой и приращением переменной каждый кадр с помощью Time.deltaTime .

Хорошим примером этого является то, когда вам нужно, чтобы таймер отображал на экране сколько времени он ждал. В принципе, как таймер.

Также хорошо, когда вы хотите прервать wait / sleep с переменной boolean , когда это правда. Здесь можно использовать yield break; .

Вы все же можете упростить это, перемещая петлю while в другую функцию сопрограммы и уступая ее, а также все еще сможете видеть ее и даже

Подождите / спящий режим до тех пор, пока переменная не изменится или не сравняется с другим значением:

4. С сопрограммой и WaitUntil :

Подождите, пока условие не станет true . Примером является функция, ожидающая, что оценка игрока будет 100 , а затем загружает следующий уровень.

5. С сопрограммой и функцией WaitWhile .

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

Вы можете позвонить в Unity для вызова функции в будущем. Когда вы вызываете функцию Invoke , вы можете передать время ожидания, прежде чем вызывать эту функцию во второй параметр. Пример ниже вызовет функцию feedDog() после 5 секунд, когда вызывается Invoke .

7. С функцией Update() и Time.deltaTime .

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

Есть еще другие способы подождать в Unity, но вы обязательно должны знать те, о которых говорилось выше, поскольку это облегчает создание игр в Unity. Когда использовать каждый из них зависит от обстоятельств.

Для вашей конкретной проблемы это решение:

И вызывать / запускать функцию сопрограммы с самого начала или Обновить вы вызываете его с помощью


Never Stop by Safetysuit w / lyrics (Свадебная версия)

Я совершил глупую ошибку и внутри void Update() вместо того, чтобы писать if(var) я написал while(var) и var никогда не изменялся внутри while, поэтому я закончил программирование бесконечного цикла внутри моего Update()

Сама история на самом деле не важна. Важно то, что я не мог остановить Play Mode. На самом деле я ничего не мог сделать с Unity, пока не перезапустил.

Итак, мой вопрос: знает ли кто-нибудь, как изящно остановить режим воспроизведения в Unity? Есть ли какой-нибудь ярлык или несколько строк кода для принудительного тайм-аута?

Я знаю, что лучший способ - избегать бесконечных циклов, но иногда можно допустить глупую опечатку.

Дополнительное примечание: Я долго искал решение этой проблемы, к сожалению, безуспешно. Однако я нашел решение побочного эффекта этой проблемы. Когда вы нажимаете ctrl-alt-del, вы можете потерять все, что вы не сохранили в своей сцене (что может быть часами работы).

Таким образом, Unity выполняет автоматическое сохранение, когда вы нажимаете кнопку воспроизведения, а резервная копия сцены находится в папке Temp folder , если вы не запустите Unity снова после принудительного выхода.

  • 4 Вы не можете этого сделать из самого Unity. Вы должны убить Unity из диспетчера задач, когда это произойдет. Опубликуйте код, вызывающий эту проблему, и вы, скорее всего, получите ответ.
  • Спасибо за ответ. На самом деле я сам обнаружил проблему, как я сказал в вопросе, я написал while () вместо if () в том, что для тестирования я все время оставлял истинным.
  • 1 Сам никогда не использовал его, но в магазине есть (платный) актив, чтобы остановить Unity в подобной ситуации.

Я только что попал в такую ​​ситуацию: случайный бесконечный цикл, застревание в режиме воспроизведения на сцене с несохраненной работой, Unity не отвечает.

Но мне посчастливилось открыть Monodevelop, хотя я в основном использовал Sublime для написания сценариев. Я нажал кнопку, чтобы начать отладку в левом верхнем углу окна Monodevelop, затем нажал кнопку паузы. Выполнение остановилось на строке в середине моего бесконечного цикла. Диспетчер задач Windows подтвердил, что Unity больше не блокирует ЦП.

(Unity 2017.4.1f1 Personal, Windows 10 Home x64, Monodevelop 5.9.6)

Следующее сработало для меня (реквизиты для @LinusR и, по расширению, @Kinxil). Это всего лишь быстрый шаг за шагом.

Это должно сработать для вас, если вы используете Visual Studio с инструментами Unity.

Найдите петлю:

  1. Откройте Visual Studio (если еще не открыто)
  2. Нажмите Присоединиться к Unity (если еще не прикреплен)
  3. Нажмите Сломать все (Пауза II символ)
  4. Открой Стек вызовов, Потоки а также Немедленно окна. (Все в Отладка Windows )
  5. Глядя на Стек вызовов, щелкните темы в Потоки окно.
  6. Остановитесь, когда найдете нить, в которой находится цикл. (Стек вызовов помогает в этом)
  7. Вы должны быть в потоке с циклом для выполнения необходимых команд в Немедленно окно.

А теперь вытащи меня отсюда !:

[Решение LinusR показалось самым пуленепробиваемым и универсальным.]

Разорвать цикл с нулевым значением и некоторыми другими параметрами

  1. в Немедленно window, установите для одного из обнуляемых объектов / полей / свойств, используемых в цикле, значение значение NULL например за Thread.SpinWait.SpinUntil(() => someObject.NeverTrue());
    • someObject = null;
    • Unity снова ответит в этом случае (при условии, что someObject остается нулевым).
  2. Альтернатива для НЕКОТОРЫЕ петли просто прерывает и изменяет инструкцию или значения и / или перетаскивает стрелку текущей инструкции (желтая стрелка) из цикла, хотя это может быть невозможно в зависимости от типа цикла.
    • Подумайте, как работает петля; Как часто это выполняется? Будет ли называться каждый кадр? и т.п.
  3. Ничего не работает? Прочтите другие ответы здесь, проявите творческий подход с Немедленное окно. Также в будущем было бы разумно иметь Ошибка Пауза всегда включен в Unity.

Для меня это сработало.

Как выйти из бесконечного цикла

Решение

  1. Присоедините свою IDE к Unity
  2. Приостановить выполнение
  3. Выйти из цикла
  4. При необходимости выполните Debug.Break (), чтобы предотвратить повторное включение цикла при следующем Update ()
  5. Возобновить выполнение
  6. Вернуться в редактор Unity

Для Visual Studio

(Я не тестировал другие IDE)

  1. Нажмите Прикрепить к Unity
  2. Подождите, пока процесс прикрепится (иногда это занимает некоторое время)
  3. Нажмите "Разбить все" (пауза II символ)
  4. Нажмите на меню Debug Windows Threads
  5. Щелкните ветку, содержащую ваш исходный код (см. Столбец местоположения)
  6. В исходном коде (текстовом редакторе) переместите указатель программы (желтая стрелка) за пределы цикла, перетащив его на другую строку исходного кода.

Необязательно в случае, когда цикл находится внутри некоторого события Update (), которое снова войдет в цикл:

  1. Нажмите на меню Debug Windows Immediate
  2. Тип UnityEngine.Debug.Break() внутри окна Immediate Window и нажмите Enter

Жаль, что Unreal Engine по большей части действительно хорош в обнаружении бесконечных циклов и выходе, когда они это делают, но Unity почти никогда этого не делает. Трудно понять, что происходит, потому что Debug.Log не срабатывает, пока кадр не завершится, поэтому вы не можете видеть, что происходит. Обходной путь, чтобы просто попытаться посмотреть, что происходит, - это использовать какой-то ограничитель вроде этого:

Конечно, это гораздо более простой пример, потому что while петли могут очень легко превратиться в бесконечные петли, но если у вас есть парк мячей, где это может происходить, вы можете установить там ограничитель.

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

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

Читайте также: