Гиф, который показывает несогласованности столкновений: http://imgur.com/QB4XOv0.gif
В моей игре Unity2D у меня есть рогатка (игрок), стреляющая шарами на стену (думаю, головоломка- головоломка типа Puzzle Bobble). Каждый из мраморов является клоном сборника, и каждый сборник имеет твердое тело с проверкой IsKinematic вместе с CircleCollider с проверенным OnTrigger.
Когда мрамор сталкивается с двумя боковыми стенками, я использую OnTriggerEnter2D() и поворачиваю угол так, чтобы он отскакивал от стен под углом. Когда мрамор сталкивается с верхней стенкой, он в основном замерзает, после чего я удаляю компонент жесткого тела и устанавливаю тег "topObjects".
Несоответствия возникают, когда мрамор сталкивается с другим мрамором. Иногда вызывается функция триггера, а другая - нет. Триггеры кажутся случайными и непредсказуемыми.
Вот мой код С# для обнаружения коллизий и поведения, которые идут вместе с ним (прикрепляется к мрамору):
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() на FixedUpdate(), похоже, сделало триггер более последовательным, однако все еще существуют несоответствия в том, как они обнаружены.
Я тестировал rigidbody2d.velocity, transform.position и различные другие функции преобразования, но Transform.Translate дал наилучшие результаты, отскакивая от стен, хотя это просто теоретически просто телепортирует объект в новое место.
Уменьшение скорости также не влияет на консистенцию вообще и не изменяет размер коллайдеров круга.
Здесь есть два очевидных момента:
1.) у вашего игрового объекта есть Rigidbody2D, поэтому вы не должны перемещать его через преобразование, а вместо этого через жесткое тело с такими функциями, как:
rigidbody2D.MovePosition()
а также
rigidbody2D.MoveRotation()
Просто посмотрите их в документации Unity.
2.) Положите все это на
void FixedUpdate()
{
...
}
Здесь все, что касается физического движка, также содержит много ресурсов в Интернете, чтобы прочитать об этом :)
OnTriggerEnter2D должен работать последовательно независимо от того, используете ли вы физику или нет.
Однако, если gameObject остается в контакте с другим объектом gameObject, вы будете отмечать один раз OnTriggerEnter один раз, в самый первый момент, когда они сталкиваются. После этого вы можете получать информацию о том, все ли два объекта gameObject все еще сталкиваются, вызывая OnTriggerStay.
Затем, после того, как они перестанут сталкиваться, OnTriggerEnter перезагрузится и снова запустится при обращении к другому объекту gameObject, даже если это то же самое, что и раньше. Вы проверили это?
Надеюсь, что это поможет, я бы опубликовал комментарий, но у меня недостаточно очков репутации, поэтому я вынужден опубликовать ответ как жаль, если не буду.
Я понимаю, что Kinematic RigidBodies не может столкнуться в 2D. Я все еще довольно новый, но я нашел это в нескольких ответах с моими собственными проблемами. Вы должны изучить его больше.
rigidbody.velocity
.