Когда одна фигурка наехала на другую, должно происходить реагирование-триггер и вызваться событие возврата назад. Но это событие триггер не всегда срабатывает.
Что происходит:
Когда начинаю двигать фигурку, то несколько раз всё происходит как надо. Фигурка перемещается на 1 по Y вниз, входит в другую фигурку, срабатывает событие OnTriggerStay2d, вызывается функция MoveBlockCollision и фигурка возвращается на прежнее место до столкновения. Но иногда, 1 раз из 5,10,20,50 это реагирование на триггер не происходит и фигурка наезжает на другую. При следующем передвижении, он возвращается на нужное место из за того что происходит два последовательных столкновения и функция MoveBlockCollision вызывается два раза.
Что пробовал?:
Применял Transform.position к RigidBody вместо объекта. Менял у RigidBody параметр Collision Detection на Continius, но там только этот параметр.
Вначале вместо FixedUpdate, было просто Update. Смотрел Как выглядит Polygon Collider в 3d(Координата Z=0 у обоих фигурок). Вместо Transform.Position делал Transform.Translate, но тогда начинается реакция на столкновение и фигурки отскакивают или разваливаются.
История:
Создал префабы фигурок. Всё с помощью кубов 1x1. Тестирую на примере фигурки L. То есть 4 куба 1x1. Один куб, который в палке из трёх кубов является родителем, остальные 3 куба являются потомками.
Сделано для того чтобы двигая или вращая один куб-родитель, двигались все потомки.
На кубах-потомках есть Transform, Mesh render, Cube(Mesh filter) три компоненты.
На кубе- родителе добавлен RigidBody2d, Polygon Collider 2d, Script(В котором добавлено событие OnTriggerStay2d).
PolygonCollider2d настроил так чтобы он захватывал полностью всю фигурку и чуть уменьшил по краям, чтобы не происходило столкновение когда фигурки в притык друг к другу.
Далее на сцене есть GameObject пустой, к которому добавлен скрипт(Перемещение текущей фигурки).
На сцене добавил две фигурки L. Одинаковых.
Скрипт добавленный к GameObject
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour {
// Use this for initialization
public GameObject CurrentBlock ;
private Quaternion rotateAngle;
private float dx = 0;
private float dy = 0;
public bool isMove = false;
public bool isCollision = false;
public Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, 0));
void Start () {
CurrentBlock = GameObject.Find ("L_Left");
}
// Update is called once per frame
void FixedUpdate () {
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
dx = -1;
dy = 0;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.RightArrow)) {
dx = 1;
dy = 0;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.DownArrow)) {
dx = 0;
dy = -1;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.UpArrow)) {
dx = 0;
dy = 1;
isMove = true;
MoveBlock();
// CurrentBlock.transform.Rotate = Quaternion.Euler(
// rotateAngle = Quaternion.Euler(new Vector3(1,1,1));
// CurrentBlock.transform.Rotate (rotateAngle);
// CurrentBlock.transform.Rotate(new Vector3(0, 0 , 90));
// Vector3 up = Vector3.forward;
// CurrentBlock.transform.rotation *= Quaternion.AngleAxis(Random.Range(-50, 50), up);
}
}
void MoveBlock(){
CurrentBlock.transform.position += new Vector3 (dx, dy, 0);
}
public void MoveBlockCollision(){
CurrentBlock.transform.position += new Vector3 (-dx, -dy, 0);
}
}
using System.Collections;
public class GameController : MonoBehaviour {
// Use this for initialization
public GameObject CurrentBlock ;
private Quaternion rotateAngle;
private float dx = 0;
private float dy = 0;
public bool isMove = false;
public bool isCollision = false;
public Quaternion rotation = Quaternion.Euler(new Vector3(0, 0, 0));
void Start () {
CurrentBlock = GameObject.Find ("L_Left");
}
// Update is called once per frame
void FixedUpdate () {
if (Input.GetKeyDown(KeyCode.LeftArrow)) {
dx = -1;
dy = 0;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.RightArrow)) {
dx = 1;
dy = 0;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.DownArrow)) {
dx = 0;
dy = -1;
isMove = true;
MoveBlock();
}
if (Input.GetKeyDown(KeyCode.UpArrow)) {
dx = 0;
dy = 1;
isMove = true;
MoveBlock();
// CurrentBlock.transform.Rotate = Quaternion.Euler(
// rotateAngle = Quaternion.Euler(new Vector3(1,1,1));
// CurrentBlock.transform.Rotate (rotateAngle);
// CurrentBlock.transform.Rotate(new Vector3(0, 0 , 90));
// Vector3 up = Vector3.forward;
// CurrentBlock.transform.rotation *= Quaternion.AngleAxis(Random.Range(-50, 50), up);
}
}
void MoveBlock(){
CurrentBlock.transform.position += new Vector3 (dx, dy, 0);
}
public void MoveBlockCollision(){
CurrentBlock.transform.position += new Vector3 (-dx, -dy, 0);
}
}
Код добавленный к Фигурке
Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;
public class CheckCollision : MonoBehaviour {
private GameObject CurrentBlock;
private GameController GameController;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerStay2D(Collider2D coll){
GameController = GameObject.Find ("GameController").GetComponent<GameController> ();
CurrentBlock = GameController.CurrentBlock;
if (coll.gameObject != CurrentBlock) {
GameController.isCollision = true;
GameController.MoveBlockCollision ();
Debug.Log ("Collision:"+ coll);
}
}
}
using System.Collections;
public class CheckCollision : MonoBehaviour {
private GameObject CurrentBlock;
private GameController GameController;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerStay2D(Collider2D coll){
GameController = GameObject.Find ("GameController").GetComponent<GameController> ();
CurrentBlock = GameController.CurrentBlock;
if (coll.gameObject != CurrentBlock) {
GameController.isCollision = true;
GameController.MoveBlockCollision ();
Debug.Log ("Collision:"+ coll);
}
}
}