Функция OnMouseEnter() вызывает непреднамеренное взаимодействие с перекрывающимися коллайдерами.C#

Место общения программистов C#
Ответить
Anonymous
 Функция OnMouseEnter() вызывает непреднамеренное взаимодействие с перекрывающимися коллайдерами.

Сообщение Anonymous »

Я работаю над своим проектом Unity, создающим сетку 4*6, которая видна только тогда, когда мышь находится на сетке.
Это работает, но неправильно. Когда я навожу указатель мыши на определенную плитку, сетка не становится видимой, в то время как другие работают нормально.
Это мой код. FiniteStateMachine — простой класс, наследуемый от MonoBehaviour.

Код: Выделить всё

public class grid_visualization : FiniteStateMachine
{
public int x;
public int y;

public float alpha;

public GameObject tilePrefab;
public GameObject[,] grid;

public float tileSize = 1f;

private idle idleState;
private alert alertState;

void Awake()
{
grid = new GameObject[y,x];
generateVisualGrid();
idleState = new idle(gameObject);
alertState = new alert(gameObject);
currentState = idleState;
currentState.onEnter();
}

void Update()
{
currentState.onUpdate();
}

private void generateVisualGrid()
{
if (tilePrefab == null)
{
Debug.LogWarning("tile prefab is needed");
return;
}

float centerAlignmentCorrection_x = (x * tileSize / 2);
float centerAlignmentCorrection_y = (y * tileSize / 2);
float tileSizeCorrection = tileSize / 2;

for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
Vector3 worldPosition = new Vector3(j * tileSize - centerAlignmentCorrection_x + tileSizeCorrection,
-i * tileSize + centerAlignmentCorrection_y - tileSizeCorrection, 0)
+ transform.position;

GameObject tile = Instantiate(tilePrefab, worldPosition, Quaternion.identity, transform);
tile.name = $"Tile_{j}_{i}";

grid[i,j] = tile;
}
}
}

void OnMouseEnter()
{
changeState(alertState);
}

void OnMouseExit()
{
changeState(idleState);
}

public void hideGrid()
{
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
SpriteRenderer gridSprite = grid[i,j].GetComponent();
gridSprite.color = new Color(1,1,1, 0);
}
}
}

public void showGrid()
{
for (int i = 0; i < y; i++)
{
for (int j = 0; j < x; j++)
{
SpriteRenderer gridSprite = grid[i,j].GetComponent();
gridSprite.color = new Color(1,1,1, alpha);
}
}
}
}

public abstract class state
{
public GameObject stateMachine;

public state(GameObject stateMachine)
{
this.stateMachine = stateMachine;
}

public abstract void onEnter();
public abstract void onUpdate();
public abstract void onExit();
}

public abstract class gridState : state
{
public grid_visualization script;

public gridState(GameObject stateMachine) : base(stateMachine)
{
script = stateMachine.GetComponent();
}
}

public class idle : gridState
{
public idle(GameObject stateMachine) : base(stateMachine)
{
}

public override void onEnter()
{
script.hideGrid();
}

public override void onUpdate()
{
}

public override void onExit()
{
}
}

public class alert : gridState
{
public alert(GameObject stateMachine) : base(stateMachine)
{
}

public override void onEnter()
{
script.showGrid();
}

public override void onUpdate()
{
}

public override void onExit()
{
}
}
Этот код реализует конечный автомат с двумя состояниями: режим ожидания и оповещение.
При переходе в состояние простоя необходимо вызвать функцию displayGrid() из конечного автомата (

Код: Выделить всё

grid_visualization
класс).
При входе в состояние оповещения вызовите состояние showGrid() и сделайте сетку видимой.
Я сделал это для того, чтобы код выполнял рейкастинг только тогда, когда мышь находится в сетке (состояние оповещения). Таким образом, код не выполняет рассылку лучей в каждом кадре, где бы ни находилась мышь. И это потому, что я хотел выделить одну плитку, над которой находится курсор мыши.
При первой попытке я попробовал использовать оператор if. Хотя он выполняет рейкастинг в каждом кадре, но на самом деле по большей части работает.
Но когда я очень быстро перемещаю мышь по сетке, она начинает мерцать. Когда я наводил указатель мыши от одного фрагмента к другому, выделенный фрагмент становился белым, а затем становился прозрачным с желаемым значением альфа 0,2f.
Это может быть просто ошибка логики моего кода, но я все равно перешел на конечный автомат.
Чтобы лучше понять эту проблему, вот скриншот. Внешняя строка является коллайдером для запуска функции события OnMouseEnter(). А сетка внутри него представляет собой коллайдер из префабов тайлов размером 4*6
Изображение

При наведении курсора на те конкретные тайлы, которые я отметил, сетка просто остается невидимой. Но при наведении курсора на любую другую плитку сетка станет видимой, как показано на снимке экрана.
Я пробовал еще одну вещь:
  • Регулировка размера коллайдера внешнего блока, который заставляет плитки становиться белыми.
  • Установка «Является триггером» и снятие флажка.
  • Удаление коллайдера блоков из префаба плитки (это каким-то образом решает проблему). но если я это сделаю, я не смогу реализовать функцию выделения)


Подробнее здесь: https://stackoverflow.com/questions/798 ... -colliders
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»