Войти
ПроектыФорумОцените

Искуственный интеллект для ботов в 2D квейкоподобной игре. Помогите с код-ревью (Godot, GDScript) (2 стр)

Страницы: 1 2 3 Следующая »
#15
(Правка: 20:59) 20:14, 24 ноя. 2020

Robotex
> А если где-то пропустил, то они не удаляются автоматически при удалении парента?
А что считать парентом? Но в любом случае, Object удаляется только вручную, только явным вызовом функции free() и ни как иначе.

> У нее производительность почти такая же, как у Object?
Не должно как то сильно повлиять на производительность. К тому же в GDScript если явно не указано наследование, то по умолчанию класс/скрипт наследуется от Reference.

> А как объекты передаются в функции: по ссылке или по значению?
Все объекты передаются по ссылке, а вот всякие PoolByteArray, PoolVectorArray, Pool* передаются по значению (т. е. встроенные типы начинающиеся с Pool).

Еще такое дело - в GDScript нет перегрузки методов и конструкторов по параметрам. К примеру следующий код не будет работать:

class Foo:
  func _init():
    pass
  func _init(a): # Ошибка т. к. ранее уже объявлен метод _init.
    pass
  func _init(a, b): # Ошибка т. к. ранее уже объявлен метод _init.
    pass


#16
20:36, 24 ноя. 2020

Daimos
> А что считать парентом?
Класс, который хранит в себе эту переменную. Например, в Qt все поля класса удаляются автоматично при удалении самого этого класса. Почему-то ожидал что будет так же.

Daimos
> по умолчанию класс/скрипт наследуется от Reference
Блин, не знал этого. Думал, что как в C++ - если явно ничего не указано, то и наследования нет. Получается, что зря я везде тулил этот Object, нужно было пустым оставлять

Daimos
> Все объекты передаются по ссылке
У меня была проблема с Vector2. Я передавал его в функцию, как аргумент, изменял внутри функции, но снаружи функции значение не менялось. Пришлось сделать эту переменную полем класса и внутри функции присваивать значение этому полю. Не понимаю, почему значение не менялось, если оно по ссылке передано

#17
20:39, 24 ноя. 2020

В этой функции:

Steering/SteeringBehavior.gd

func AccumulateForce(ForceToAdd : Vector2) -> bool:
  # calculate how much steering force the vehicle has used so far
  var MagnitudeSoFar : float = steeringForce.length()
  
  # calculate how much steering force remains to be used by this vehicle
  var MagnitudeRemaining : float = agent.maxForce - MagnitudeSoFar
  
  # return false if there is no more force left to use
  if MagnitudeRemaining <= 0.0:
    return false
  
  # calculate the magnitude of the force we want to add
  var MagnitudeToAdd : float = ForceToAdd.length()
  
  # if the magnitude of the sum of ForceToAdd and the running total
  # does not exceed the maximum force available to this vehicle, just
  # add together. Otherwise add as much of the ForceToAdd vector is
  # possible without going over the max.
  if MagnitudeToAdd < MagnitudeRemaining:
    steeringForce += ForceToAdd
  else:
    MagnitudeToAdd = MagnitudeRemaining
    
    # add it to the steering force
    steeringForce += (ForceToAdd.normalized() * MagnitudeToAdd)
  
  return true

steeringForce тоже раньше передавалось аргументом, но почему-то не изменяло своего значения после вызова функции

#18
(Правка: 20:55) 20:53, 24 ноя. 2020

Robotex
> Класс, который хранит в себе эту переменную.
Если унаследован от Object, то такой объект удаляется только явным вызовом free и никак иначе.

> Получается, что зря я везде тулил этот Object, нужно было пустым оставлять
Да, можно просто убрать строку "extends Object" и все.

> У меня была проблема с Vector2
Vector2/Vector3/Basis/Transform так же являются встроенными типами и передаются по значению. В общем в редакторе скриптов Godot они помечаются другим цветом нежели объекты передающиеся по ссылке. Исключением составляют типы Array и Dictionary, они передаются по ссылке.

#19
21:10, 24 ноя. 2020

Daimos
> Vector2/Vector3/Basis/Transform так же являются встроенными типами и передаются
> по значению
вон оно че. Ясно, спасибо

Daimos
> Да, можно просто убрать строку "extends Object" и все.
Спасибо, поудаляю

#20
1:05, 25 ноя. 2020

Daimos
> Еще такое дело - в GDScript нет перегрузки методов и конструкторов по
> параметрам. К примеру следующий код не будет работать
Да, я уже понял и в тех скриптах, которые уже в работе переписал (FzAND.gd)
Спасибо

Daimos
> Если унаследован от Object, то такой объект удаляется только явным вызовом free
> и никак иначе.
У меня и так везде free стояли, но походу где-то пропустил

Переписал на референсы и взлетело до 100-160 ФПС. Правда комп теперь гудит как бешеный. Как бы залочить на 60?

Но потом активировал евалуаторы поиска и выбора оружия и ФПС упали до 3-4 0_o Дейкстра чтоли тормозит так?

#21
1:08, 25 ноя. 2020

Вот такие ошибки постоянно сыпятся в консоль:

ERROR: get_global_transform: Condition "!is_inside_tree()" is true. Returned: get_transform()
   At: scene/2d/canvas_item.cpp:483.
ERROR: get_global_transform: Condition "!is_inside_tree()" is true. Returned: get_transform()
   At: scene/2d/canvas_item.cpp:483.
ERROR: get_global_transform: Condition "!is_inside_tree()" is true. Returned: get_transform()
   At: scene/2d/canvas_item.cpp:483.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112.
#22
12:42, 25 ноя. 2020

Robotex
> можно переписать на C++ и в дальнейшем я так и сделаю
надо переписать на Юнити, и тогда я посмотрю код ... :)

#23
(Правка: 13:22) 13:01, 25 ноя. 2020

Robotex
> Вот такие ошибки постоянно сыпятся в консоль:
Я же ответил уже по этой ошибке:
https://gamedev.ru/projects/forum/?id=256731&m=5292865#m8

По отрисовке: иногда сыпется ошибка что в коде вызываешь get_global_transform (возможно просто считываешь свойство global_transform, что одно и тоже) когда узел не находится в дереве (т. е. Node у которого ты вызываешь это свойство уже удален или просто не добавлен из/в SceneTree) и как бы система тебя предупреждает что результат является только локальная матрица (get_transform()).

Так же get_global_transform может вызываться когда используешь свойство global_position. Например в скрипте TriggerSoundNotify.gd, в методе _init, используется это свойство. Теперь смотрим по логике что происходит: _init вызывается при создании объекта (конструктор), на этом этапе сам объект еще не добавлен в SceneTree, а значит использование global_position в методе провоцирует эту ошибку.

Robotex
> Как бы залочить на 60?
Можно попробовать так:

Engine.target_fps = 60
Или настроить в конфиге проекта:
Project Settings -> Debug -> Settings -> Force FPS


Ну и вообще есть свойство Use VSync - подстраивает FPS под частоту обновления монитора:
Project Settings -> Display -> Window -> Use Vsync
Тоже самое только через код:

OS.vsync_enabled = true
#24
14:12, 25 ноя. 2020

Daimos
> когда узел не находится в дереве
Ну да. Это у тех самых Object'ов, которые теперь Reference вызывается метод draw(parent : CanvasItem) и внутри пересчитывается их информация в локальные координаты и отрисовывается на канве парента.

Так нельзя делать? Они обязательно должны лежать именно на сцене и быть унаследованы от Node?

#25
(Правка: 17:22) 17:16, 25 ноя. 2020

Robotex
get_global_transform есть только у Node2D и Spatial и всех типов которые унаследованы от них. TriggerSoundNotify в конечном счете унаследован от Position2D который от Node2D.

func _init(source, distance : float, type : int).(UserOptions.TriggerTestRegulatorTime):
  soundSource = source
  soundType = type
  # set position and range
  global_position = soundSource.global_position
  
  boundingRadius = distance
  
  # create and set this trigger's region of fluence
  AddCircularTriggerRegion(global_position, boundingRadius, self, "_on_body_entered")
AddCircularTriggerRegion первым аргументом ты передаешь global_position, в _init методе, т. е. TriggerSoundNotify еще не добавлен в сцену!

Что можно сделать в данном случае? Можно попробовать заменить global_position на position, но если парент этого объекта имеет position != Vector(0, 0) то будут проблемы с финальной позицией. Тогда можно завести отдельный Node2D у которого всегда нулевая позиция и добавлять новые узлы в него.

Я бы пересмотрел структуру кода, где и когда используется global_position/global_transform, и попробовал бы модифицировать код так чтобы эти данные использовались после добавления узла в сцену. Как пример:

func _init(source, distance : float, type : int).(UserOptions.TriggerTestRegulatorTime):
  soundSource = source
  soundType = type
  # set position and range
  #global_position = soundSource.global_position
  
  boundingRadius = distance
  
  # create and set this trigger's region of fluence
  #AddCircularTriggerRegion(global_position, boundingRadius, self, "_on_body_entered")

func _ready():
  global_position = soundSource.global_position
  AddCircularTriggerRegion(global_position, boundingRadius, self, "_on_body_entered")
#26
18:58, 25 ноя. 2020

Daimos
> global_transform
А если самостоятельно формировать его из Transform2D для тех объектов, которые не будут лежать непосредственно на сцене?

вообще, метод _draw он же в локальных координатах все рисует?

#27
19:53, 25 ноя. 2020

Есть еще такой баг, который мне никак не удается пофиксить.

В коде бота есть такой код, который проверяет, может ли бот пройти между двумя точками, не врезавшись в препятствие (если нет, то включается pathfinding и прокладывает обходной маршрут):

# returns true if this bot can move directly to the given position
# without bumping into any walls

func canWalkTo(pos : Vector2) -> bool:
  return canWalkBetween(global_position, pos)

# similar to above. Returns true if the bot can move between the two
# given positions without bumping into any walls

func canWalkBetween(from : Vector2, to : Vector2) -> bool:
  var t = transform
  t.origin = from
  var res = not test_move(t, to - from)          #(Transform2D((to - from).angle(), from), to, false)
  return res
  # here the first variant is commented which gave the same result
  #  var space_state = get_world_2d().direct_space_state
  #  var motion = to - from
  #  var query = Physics2DShapeQueryParameters.new()
  #  query.motion = motion
  #  query.set_shape(collisionShape.shape) 
  #  query.exclude = [self]
  #  var result = space_state.cast_motion(query)
  #  
  #  return (not result.empty()) and result[0] == 1.0 and result[1] == 1.0

Работает правильно в большинстве случаев, но иногда почему-то бот пытается пройти напрямую сквозь стенку. В чем я ошибся?

#28
20:41, 25 ноя. 2020

Robotex
> А если самостоятельно формировать его из Transform2D
Можно и так. Если нужно учесть трансформацию родителей, то самостоятельно итерируем и умножаем матрицы (трансформации) получая тем самым финальную матрицу.

> вообще, метод _draw он же в локальных координатах все рисует?
Да.

> Работает правильно в большинстве случаев
Возможно в некоторых случаях сказывается ориентация бота, его вращение и масштаб
collision_diff | Искуственный интеллект для ботов в 2D квейкоподобной игре. Помогите с код-ревью (Godot, GDScript)
А возможно дело в логике...

#29
14:57, 27 ноя. 2020

Daimos
> Возможно в некоторых случаях сказывается ориентация бота
возможно, я натупил и не изменял ориентацию в трансформе

Однако иногда они пытаются пройти сквозь стену, через которую нельзя пройти независимо от ориентации. Хотя скорее всего тут pathfinding заглючил и не вернул путь.


Daimos
> AddCircularTriggerRegion первым аргументом ты передаешь global_position, в
> _init методе, т. е. TriggerSoundNotify еще не добавлен в сцену!
Я перенес подобные вещи в функцию _ready() однако ошибки не исчезли и быстрее не стало.

А еще походу FuzzyLogic течет, несмотря на Reference

Страницы: 1 2 3 Следующая »
ПроектыФорумОцените