Как сделать так, чтобы действие повторялось каждые x секунд с таймером в C#? - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь закодировать функцию в игре в Unity, которая позволяет игроку go вернуться к нему через 5 секунд после go, поэтому я хочу, чтобы каждые 5 секунд координаты игрока сохранялись go вернуться к ним, если вы нажмете клавишу.

Единственное, что я не знаю из этого, это все, что связано со временем. Я видел руководство по использованию таймера, но я не понимаю, кто-то может помочь?

Ответы [ 3 ]

1 голос
/ 26 апреля 2020

Если вы используете Unity, то простейшим способом кодирования действий, связанных со временем, являются сопрограммы . Вы можете просто позвонить StartCoroutine и затем использовать yield return new WaitForSecondsRealtime(5f). Использование. NET таймеров также вариант, но в большинстве случаев я бы не рекомендовал его при работе над игрой в Unity.

Например, если вы определяете метод, подобный этому

IEnumerator MyCoroutine()
{
    yield return new WaitForSeconds(5f);
    //code here will execute after 5 seconds
}

Позже вы можете назвать его так:

StartCoroutine(MyCoroutine)

Другой подход - использовать Time.deltaTime внутри Update метода. При таком подходе ваш код может выглядеть примерно так:

float timePassed = 0f;
void Update()
{
    timePassed += Time.deltaTime;
    if(timePassed > 5f)
    {
        //do something
    } 
}

Если вы действительно не хотите, чтобы ваш код указывал Unity, c, вам придется выбирать между System.Threading.Timer и System.Timers.Timer

0 голосов
/ 26 апреля 2020

Вы можете использовать один из двух системных таймеров - System.Timers.Timer и System.Threading.Timer. Вот пример с первым:

 System.Timers.Timer timer = new System.Timers.Timer(5000);
 timer.Start();
 timer.Elapsed += SaveDataPeriodically;

, где SaveDataPeriodically - это метод, который принимает два аргумента:

void SaveDataPeriodically(object sender, ElapsedEventArgs e)
{
    //Save the coordinates
}

Вы просто подписываетесь на событие Elapsed, которое будет срабатывать каждые 5000 миллисекунд.

0 голосов
/ 26 апреля 2020

Я не уверен на 100% в единстве, но обычно в играх вы не используете таймеры для игр. То, что вы хотите, звучит как Принц Персии: Пески Времени Механизм перемотки c.

Игры в реальном времени - это просто игры с большим количеством ходов, которые не ждут пользователя вход. «Тик» является общим термином для этих поворотов. Вместо того, чтобы использовать таймеры, вы считаете тики. Вместо секунд вы учитываете тики - с известной цифрой / секундами. Unity немного скрывает галочки, чтобы упростить программирование, но они есть. Начиная с понга, тики являются единственной константой развития игры Единственное, что является фундаментальным для выполнения программы: https://en.wikipedia.org/wiki/Video_game_programming#Game_structure

Однако в этом случае вам понадобится история позиций с максимумом. Думайте об этом как историю отмен любого текстового редактора. Он также возвращается к «последнему сохранению вручную» или с некоторым разумным ограничением записей истории.

Вам необходимо сохранить позицию, каждый игровой штрих, в Коллекцию. После того, как точка в этом собрании была более 5 секунд в прошлом, ее можно отбросить, чтобы освободить место для новой. Специальная коллекция c подлежит обсуждению. Эта историческая диаграмма имеет сходство с очередью - в том, что вы хотите добавить последнюю, не разрушенную вещь. Он имеет элементы связанного списка, так как вы не хотите сдвигать заполненную коллекцию каждый тик игры, так как добавляется новая запись. Но вы также хотите иметь возможность быстро очистить его после перемотки (до точки, которую вы также перематывали), для которой требуется функция очистки или произвольный доступ.

В качестве примера я сделал этот старый и Примитивный Счетчик FPS. Он считает кадры, но только за последнюю секунду:

using System;
using System.Collections.Generic;

namespace FPS_Counter
{
    class FPS_Counter
    {
        List<DateTime> FrameCounter = new List<DateTime>();

        public void countFrame(){
            FrameCounter.Add(DateTime.Now);
        }

        private void clearOld()
        {
            bool continueLoop;
            DateTime decayLimit = DateTime.Now.AddSeconds(-1);

            do
            {
                continueLoop = false;
                if (FrameCounter.Count > 0 && FrameCounter[0] < decayLimit)
                {
                    FrameCounter.RemoveAt(0);
                    //If you removed one, the one after might be too old too.
                    continueLoop = true;
                }
            }while (continueLoop);
        }

        public int FPS
        {
            get
            {
                clearOld();
                return FrameCounter.Count;
            }
        }
    }
}

По сути, он создает историю всех подсчетов countFrame(). Я использовал простой список и очистил, когда вызывается get. Это неэффективно и может легко переполнить коллекцию, если вы подсчитываете число фреймов, но на самом деле не получаете значение.

Это было достаточно эффективно для работы, так как get называется регулярным. Ваша история будет намного больше, как по количеству записей, так и по размеру записей, поэтому вам, вероятно, придется очищать старое каждый раз, когда вы добавляете что-то новое. И ваш эквивалент countFrame() должен принять позицию и метку в качестве аргумента.

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