Как создать перетаскиваемый объект, который мешает на пути?

8

Я задаю еще один вопрос - перетаскивание мышью (я использую Unity с C #), но с менее частой конкретной деталью: наличие препятствий в середине пути, по которому происходит перетаскивание (3D-пространство, а не 2D) ,

Позволь мне объяснить. Предположим, у меня есть самолет, по которому я хочу перетащить куб с именем «obj». Это легко. Вот моя простая реализация для этого:

void Update () {
  Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
  RaycastHit hit;
  if(Physics.Raycast(ray, out hit, 1000000))
  obj.transform.position = new Vector3(hit.point.x,0.25F,hit.point.z);
}

Оно работает. Однако предположим, что у меня также есть несколько других кубов над плоскостью, которые являются препятствиями. Очевидно, что когда игрок перемещает «объект» по плоскости, такое движение должно быть заблокировано препятствиями. И затем, сталкиваясь с препятствиями, «объект» должен двигаться только по обрезанным сторонам этого препятствия. Если мышь перемещается и «obj» перестает сталкиваться с препятствиями, свободное движение в стиле перетаскивания возобновляется снова.

объект перетаскивается к препятствию и останавливается на его краю, а затем возобновляется, когда сопротивление проходит препятствие

Чтобы усложнить задачу, я изо всех сил стараюсь добиться этого без использования компонентов RigidBody на препятствиях (перетаскиваемый объект может иметь это). Любые идеи о том, что является наиболее эффективным способом достижения этого? Большое спасибо!

РЕДАКТИРОВАТЬ: Комментаторы обратили мое внимание, что я должен упомянуть, что объекты могут вращаться при привязке.

РЕДАКТИРОВАТЬ 2: Учитывая сложность первоначальной формулировки, я изменил вопрос, разрешающий использование компонентов Rigidbody на перетаскиваемых объектах. Решение просто не может использовать компоненты Rigidbody на препятствиях.

MAND
источник
Вы перемещаете произвольные выпуклые формы - они всегда четырехсторонние? Они всегда 2D?
Стивен
Могу ли я узнать причину, по которой вы не будете использовать твердые тела? Это самый простой способ сделать то, что вы хотите, без необходимости переопределения кода, уже доступного в Unity.
EvilTak
@ EvilTak Я, скорее, узнаю, как обращаться с геометрией, вовлеченной в задачу, и из-за соображений производительности я не люблю использовать твердотельные тела, если это действительно не является неизбежным. В этом конкретном случае у меня будет много тысяч объектов, которые ведут себя как препятствия
И
Кстати, спасибо @Anko (или тому, кто это сделал) за включение этого анимированного изображения для иллюстрации проблемы! Я все еще думал о лучшем способе сделать это.
MAND
1
@Steven и EvilTak: объект может вращаться, препятствия - нет. Обычные способы обнаружения столкновения кажутся недостаточными: основной объект продолжает проникать внутрь объектов.
15:04

Ответы:

2

Трудно обнаружить столкновение без участия каких-либо твердых тел, но поскольку вы используете кубы, вы можете использовать Bounds.Intersects . Каждое обновление проверяет, пересекаются ли границы перетаскиваемого объекта с границами каких-либо препятствий. Если это так, то вы можете попробовать это:

  1. Отключите Mesh Renderer для перетаскиваемого объекта, чтобы сделать его невидимым (но продолжайте перетаскивать его).
  2. Удалите видимый объект-заполнитель, идентичный перетаскиваемому объекту, в последнюю позицию перед пересечением границ (теперь это выглядит так, как будто объект остановился, но на самом деле вы все еще перетаскиваете оригинал).
  3. Каждое обновление проверяет, пересекаются ли границы объекта, который вы все еще перетаскиваете, с границами препятствия.
  4. Когда границы перетаскиваемого объекта больше не пересекаются с границами препятствия, удалите / деактивируйте объект-заполнитель и повторно включите Mesh Renderer для перетаскиваемого объекта, чтобы он снова стал видимым.

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

Evan
источник
Основываясь на предыдущих комментариях и вашем ответе, я отредактировал вопрос, чтобы упростить его выполнение: давайте теперь скажем, что Rigidbody можно использовать для перетаскиваемого объекта или его заполнителей. Твердое тело просто нельзя было использовать для препятствий.
MAND
1

Не сделав этого сам, вот что я попробую:

  1. Решите, насколько высоко должно быть какое-то препятствие на плоскости, чтобы заблокировать ваш перетаскиваемый объект (где «высокое» означает удаление вдоль любой подходящей оси - я бы предположил, что она указывает на камеру).
  2. Каждое обновление, сохраняйте позицию вашего удара Raycast.
  3. Каждое обновление, перед сохранением позиции текущего попадания лучевой передачи, проверяет позицию текущего попадания лучевой передачи относительно позиции предыдущего попадания лучевой передачи.
  4. Если разница> = высота блокировки, остановите движущийся объект на предыдущей позиции попадания лучей.

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

Evan
источник
Спасибо за ваш ответ, @Evan. Однако это решение не будет точным. Предположим, что RayCast будет запущен из центра ограничительной рамки перетаскиваемого объекта. Что если препятствие на пути блокирует только часть перетаскиваемого объекта, который находится слева или справа от луча? Даже если мы увеличим количество используемых лучей (что может быть экспоненциально большим, если перетаскиваемый объект можно перетаскивать в направлениях 360 ° в измерениях X, Z), в зависимости от того, насколько мало препятствие по отношению к перетаскиваемому объекту, оно все равно может быть в пределах от лучей литой - и , следовательно , не будут обнаружены
MAND
Хорошо, я думаю, я понимаю, что вы имеете в виду.
Эван