Движок игры - это (дискретное) моделирование событий.Как правило, они реализуются с помощью изменяемых структур данных, таких как куча для событий, четырехъядерные деревья для пространственных запросов об объектах и множество хеш-таблиц.
Для каждой из этих структур данных изменяемые варианты работают быстрее.Кроме того, неизменяемые структуры данных производят мусор, который необходимо собирать, поэтому нагрузка на ГХ выше, а ваше приложение работает медленнее.Там, где проблема в реальном времени, паузы ГХ могут быть вредными (например, это может повлиять на частоту кадров в вашей игре), и это особенно верно для платформ с меньшей вычислительной мощностью, таких как Android.
Что касаетсяметод copy()
- он не должен копировать весь объект для создания обновленной версии.Если ваш объект организован иерархически в виде дерева (например, в виде иерархии классов дел), то для изменения одного свойства объекта требуется переписать только один путь в этом дереве - вам не нужно будет переписывать все.Тем не менее, это будет дороже, чем просто иметь изменяемую версию и обновление на месте.
Пример:
case class World(map: Array[Item], players: Vector[Player])
case class Player(health: Int, speed: Int, weapon: Weapon, shield: Shield)
case class Weapon(strength: Int, ammo: Int)
Чтобы добавить больше боеприпасов к оружию, вам не нужнополная копия World
:
def setAmmo(playerNum: Int, newAmmo: Int, world: World): World = {
val p = players(playerNum)
world.copy(players = players.updated(playerNum, p.copy(weapon = p.weapon.copy(ammo = newAmmo))))
}
В этом примере map
, другие players
и shield
измененного Player
остаются теми же в памяти и не копируются с нетерпением.
Я бы посоветовал использовать изменяемую структуру данных для представления состояния - если только у вас нет параллельного игрового движка с (например) одним писателем, который имитирует игровое состояние, и целым рядом читателей, которые отображают вывод.обработка звука, сети и т. д. Преимущества неизменяемых структур данных в этом случае практически отсутствуют.