Я немного не согласен с ответом Филиппа ; или хотя бы с тем, как он это представил. Создается впечатление, что лучше было бы передвигать мир вокруг игрока; когда все наоборот. Так вот мой собственный ответ ...
Оба варианта могут работать, но, как правило, плохая идея «инвертировать физику», перемещая мир вокруг игрока, а не игрока по всему миру.
Потеря производительности / растрата:
В мире обычно будет много объектов; многие, если не большинство, статичные или спящие. У игрока будет один или относительно немного объектов. Перемещение всего мира вокруг игрока означает перемещение всего на сцене, кроме игрока. Статические объекты, спящие динамические объекты, активные динамические объекты, источники света, источники звука и т. Д .; все должны быть перемещены.
Это (очевидно) значительно дороже, чем перемещать только то, что на самом деле движется (игрок, и, возможно, еще несколько вещей).
Ремонтопригодность и расширяемость:
Перемещение мира вокруг игрока делает мир (и все, что в нем) тем моментом, когда все происходит наиболее активно. Любая ошибка или изменение в системе означает, что потенциально все меняется. Это не хороший способ делать вещи; вы хотите, чтобы ошибки / изменения были как можно более изолированными, чтобы вы не получили неожиданного поведения там, где вы не внесли изменений.
Есть также много других проблем с этим подходом. Например, это нарушает многие предположения о том, как все должно работать в двигателе. Вы не сможете использовать динамические RigidBody
для чего-либо, кроме игрока, например; поскольку объект с прикрепленным, RigidBody
не установленным кинематическим, будет вести себя неожиданно при настройке позиции / поворота / масштаба (что вы будете делать каждый кадр, для каждого объекта в сцене, кроме игрока 😨)
Таким образом, ответ - двигать игрока только тогда!
Ну ... да и нет . Как упомянуто в ответе Филиппа, в играх с бесконечным бегущим (или в любой игре с большой бесшовной исследуемой областью) слишком большое расстояние от источника может в конечном итоге привести к появлению заметных FPPE ( ошибок точности с плавающей запятой ), и еще дальше, в конце концов, Переполнение числового типа, что может привести к сбою в игре или, по сути, к образованию дыма в игровом мире ... На стероидах! 😵 (потому что к этому моменту FPPE сделает игру уже на «нормальном» трещине)
Фактическое решение:
Не делай ни того, ни другого! Вы должны держать мир неподвижным и перемещать игрока вокруг него. Но «подкореним» и игрока, и мир, когда игрок начинает слишком далеко уходить от корня (позиция [0, 0, 0]
) сцены.
Если вы сохраняете относительное положение вещей (игрок по отношению к окружающему миру) и выполняете этот процесс в одном обновлении кадра, (реальный) игрок даже не заметит!
Для этого у вас есть два основных варианта:
- Переместите игрока в корень сцены и переместите кусок мира в его новую позицию относительно игрока.
- Думайте о мире как о сетке; переместите часть сетки, в которой находится игрок, в корень, и переместите игрока в его новое положение относительно этой части сетки.
Вот пример этого процесса в действии
Но как далеко это слишком далеко?
Если вы посмотрите на исходный код Unity, они используют 1e-5
( 0.00001
) в качестве основы для рассмотрения двух значений с плавающей запятой «равными» внутри Vector2
и Vector3
(типы данных, отвечающие за положение объектов, [euler-] повороты и масштабирование). Поскольку потеря точности с плавающей точкой происходит в обоих направлениях от нуля, можно с уверенностью предположить, что все, что находится под единицами 1e+5
( 100000
) от корня / источника сцены, безопасно для работы.
Но! Поскольку...
- Более уместно сделать систему для автоматической обработки этих процессов повторного укоренения.
- Какой бы ни была ваша игра, нет необходимости в непрерывной «части» мира шириной 100 000 единиц (метров [?]).
... тогда, вероятно, будет хорошей идеей повторно получить root намного раньше / чаще, чем отметка в 100000 единиц. Например, приведенный мной пример видео, кажется, делает это каждые 1000 единиц или около того.