2016-11-15 3 views
2

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

Я сделал это наивный способ (псевдо-код):

foreach(object in objects){ 
    actual_position = object.transform.position 
    object.transform.position = object.new_position 
} 
if(Physics.Raycast(...)) objectHit(); 
// Then I revert each of them them back to their actual_position 

После тестирования несколько раз с тем же контекстом (одни и те же позиции между тестами для каждого объекта), то raycast иногда пропускают, иногда нет (~ 50/50).

Совершено несколько исследований и обнаружил, что в док странице Raycast:

При перемещении коллайдеров из сценариев или анимации, там должен быть по крайней мере один FixedUpdate выполнен так, что библиотека физики может обновите свои структуры данных, прежде чем Raycast поразит коллайдер на , это новая позиция.

Поэтому я успокоил свой гнев и начал искать решение. Эта нить есть способ, используя сопрограмму ждать следующий тик: Raycast doesn't work properly

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

Есть ли способ заставить коллайдеры обновить?

Если нет ... должен ли я создавать свои собственные ракисты и коллайдеры? :(

Благодаря

+1

Вы пытались использовать что-то вроде 'Bounds.IntersectRay'? Если на вашем объекте есть простые коллайдеры (или ваши raycasts не должны быть на 100% точными) для чего-то такого же простого, как коллайдер коробки, вы можете сделать 'object.GetComponent () .bounds', чтобы получить границы и переместите объект bounds в новое местоположение, проверьте его, и THEN переместите объект только в том случае, если он не столкнется, это также будет лучше по производительности, чем перемещение в два раза, поскольку оно даже не сдвинет его вообще, если оно не должно, https: //docs.unity3d.com/ScriptReference/Bounds.IntersectRay.html –

+0

Похоже на умное решение, мои коллайдеры - простые капсулы на данный момент, но я думаю, это будет работать и для более сложного MeshCollider. Единственная проблема, которую я вижу, это то, что мне придется ударить все объекты и убедиться, что между ними и источником луча нет стены. Это сложнее, чем просто бросать рейгаст, но почему бы и нет. Большое спасибо за вашу помощь. – FLX

+0

Глядя на ответ, который вы связали, я думал, что, возможно, вы можете попытаться использовать 'yield return new WaitForFixedUpdate();' поскольку он будет вызываться перед каждым обновлением физики? – Kardux

ответ

0

Может быть, вы можете попробовать это (добавление к вашему псевдокоду):

foreach(object in objects) 
{ 
    actual_position = object.transform.position; 
    object.transform.position = object.new_position; 

    StartCoroutine(CheckToRevertOnNextFixedUpdate(object, actual_position)); 
} 

IEnumerator CheckToRevertOnNextFixedUpdate(object, actual_position) 
{ 
    yield return new WaitForFixedUpdate(); 

    if(Physics.Raycast(...)) objectHit(); 
    // Then I revert each of them them back to their actual_position 
} 

По существу это задерживает ваш чек на следующий FixedUpdate() для каждого объекта - и возвращается каждый из них при необходимости.Надеюсь, что это не слишком сложно, так как вы добавляете только несколько строк кода.

Я также предполагаю, что перемещение позиции объекта для 1 кадра FixedUpdate() не будет иметь визуального эффекта объект телепортации в новое положение и назад. Тем не менее, вы всегда можете переместить только коллайдер, а затем переместить остальную часть преобразования там после FixedUpdate().

+0

Вот как они это делали в связанной теме, но если другой игрок стреляет, пока он перемещен, фактическое положение может быть неправильным (я прав, на этом?). Кроме того, решение Paradox выглядит лучше с точки зрения производительности. – FLX

+0

@FLX. Идея использования сопрограммы аналогична этой теме, но детали несколько разные, применимые к вашему контексту. Если другой игрок стреляет во время его перемещения, это не имеет значения, так как позиция коллайдера еще не обновлена ​​в следующем FixedUpdate(). И да, решение Paradox может быть более эффективным, если вы можете приблизить форму коллайдера к ограничивающей рамке, и если процесс выполнения этого не потребует значительных накладных расходов – Lincoln

Смежные вопросы