2014-09-30 3 views
1

A GIF, который показывает столкновение несоответствия: http://imgur.com/QB4XOv0.gifне OnTriggerEnter2D называется последовательно

В моей игре Unity2D У меня есть рогатка (игрок) огневые мраморы вверх по стене (думает Puzzle Bobble типа головоломки шутер игра). Каждый из мраморов является клоном из сборных и каждого из сборных имеют Rigidbody с IsKinematic проверяются вместе с CircleCollider с OnTrigger проверяемого.

Когда мрамор сталкивается с двумя боковыми стенками, я использую OnTriggerEnter2D() и поворачиваем угол так, чтобы он отскакивал от стен под углом. Когда мрамор сталкивается с верхней стенкой, он в основном замерзает, и в этот момент я удаляю компонент rigidbody и устанавливаю «topObjects».

Несоответствия возникают, когда мрамор сталкивается с другим мрамором. Иногда вызывается функция триггера, иногда это не так. Триггеры кажутся случайными и непредсказуемыми.

Вот мой C# код для обнаружения столкновений и поведения, которые идут вместе с ним (прилагается к мрамору):

using UnityEngine; 
using System.Collections; 
using System.Collections.Generic; 

public class RockMove : MonoBehaviour 
{ 
    public float speed = 0.5f; 
    private Vector2 direction = new Vector2(0, 1); 

    // current angle 
    private float currentAngleZ; 
    // indendiary angle 
    private float angleB; 

    // rotation speed 
    private float rot; 

    // curving speed 
    private float rotMod; 

    // stops marble when collides with wall 
    private bool IsMoving = true; 


    void Start() { 
    } 

    void Update() 
    { 

     if (IsMoving) { 
      rot = RockSpawn.rot; 

      currentAngleZ = transform.eulerAngles.z; 

      rotMod = transform.position.x * -0.5f; 
      // moves it forward + adds speed 
      transform.Translate(direction * Time.deltaTime * speed, Space.Self); 
      // curving 
      transform.Rotate (0, 0, rotMod, Space.Self); 
      if (transform.position.x >= 0) { 
       // faster speed when near walls "gravity/magnetism" 
       speed += transform.position.x * 8 * Time.deltaTime; 
      } 
      if (transform.position.x < 0) { 
       // faster speed when near walls "gravity/magnetism" 
       speed += transform.position.x * -8 * Time.deltaTime; 
      } 
     } 
     else { 
      // when object is stationary 
      speed = 0; 
     } 
    } 


    void OnTriggerEnter2D(Collider2D collider){ 

     // if collides with another marble 

     if (collider.gameObject.tag == "topObjects") { 
      // get rid of rigidbody 
      // can't have 2 rigidbodies when 2 objects collide 
      Destroy(rigidbody2D); 
      // freeze movement 
      IsMoving = false; 

      Debug.Log ("you collided with a marble"); 

      // freeze rotation 
      this.transform.Rotate (0, 0, 0, Space.Self); 

      // assign the new tag 
      this.tag = "topObjects"; 
     } 
     else if(collider.name == "TopWall") 
     { 
      Destroy(rigidbody2D); 
      IsMoving = false; 

      Debug.Log ("you broke the fourth wall!"); 
      transform.Rotate (0, 0, 0); 

      this.tag = "topObjects"; 
     } 
     else { 
      // bounce off walls 
      currentAngleZ = transform.eulerAngles.z; 
      angleB = 360 - (2 * currentAngleZ); 
      transform.Rotate (0, 0, angleB); 
     } 
    } 

} 

Update: Простое изменение функции Update() для FixedUpdate() похоже, делает триггер более последовательным, однако все еще существуют несоответствия в том, как они обнаружены.

Я тестировал rigidbody2d.velocity, transform.position и различные другие функции преобразования, но Transform.Translate дал наилучшие результаты, отскакивая от стен, хотя он просто теоретически просто телепортирует объект в новое место.

Снижение скорости также не влияет на консистенцию вообще и не меняет размер коллайдеров круга.

+0

В моем опыте события столкновения и триггера более согласованы при использовании движения на основе физики, например, 'rigidbody.velocity'. – SirBraneDamuj

+0

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

+0

Стены устанавливаются как триггеры (полигонный коллайдер с проверкой IsTrigger) – BankBits

ответ

0

OnTriggerEnter2D должен работать последовательно независимо от того, используете ли вы физику или нет.

Однако, если gameObject остается в контакте с другим объектом gameObject, вы будете отмечать один раз OnTriggerEnter один раз, в самый первый момент, когда они сталкиваются. После этого вы можете получать информацию о том, все ли два объекта gameObject все еще сталкиваются, вызывая OnTriggerStay.

После того, как они перестанут сталкиваться, OnTriggerEnter перезагрузится и снова запустится при обращении к другому объекту gameObject, даже если это то же самое, что и раньше. Вы проверили это?

Надеюсь, что это поможет, я бы опубликовал комментарий, но у меня недостаточно очков репутации, поэтому я вынужден опубликовать ответ как жаль, если не буду.

+0

Спасибо за это, я попробую OnTriggerStay и дам вам знать, работает ли он. – BankBits

+0

Ну, не говоря о том, что вы должны использовать OnTriggerStay() обязательно, но только так, что так происходит, просто чтобы сделать заметку на случай, если она может помочь. – CodeAssembler

0

Два очевидных момента здесь:

1.) Ваш геймобжекты имеет Rigidbody2D, так что вы не должны переместить его через преобразование, но вместо того, чтобы через RigidBody с функциями, как:

rigidbody2D.MovePosition() 

и

rigidbody2D.MoveRotation() 

Просто посмотреть их в документации Unity.

2.) Поместите все это в

void FixedUpdate() 
{ 
    ... 
} 

Здесь все, что касается физико двигателя входит. также много ресурсов в Интернете, чтобы читать о нем :)

+0

Я пробовал Rigidbody2d.MovePosition() и MoveRotation(), однако ему удавалось только перемещать мраморную часть вверх по экрану, а затем полностью останавливаться. Я проверил, и в этот момент не было других коллайдеров, поэтому он, казалось, прекращался произвольно. Изменение OnTriggerEnter на OnTriggerStay также не устранило проблему и не переместило код преобразования в FixedUpdate(). – BankBits

+0

MovePosition работает в абсолютных положениях. это означает, что если вы хотите двигаться вверх, вам нужно использовать rigidbody2D.MovePosition (rigidbody2D.position + Vector2.up); – Tom

-2

Это мое понимание того, что кинематическая RigidBodies не могут столкнуться в 2D. Я все еще довольно новый, но я нашел это в нескольких ответах с моими собственными проблемами. Вы должны изучить его больше.