Concurency problem

My application have strange behaviour. I have ground 24x24 cells and each cell calls utility calss (in onMouseEnter()) for searching minimum path to the destination cell. When i select cell that have player on it, other cells becomes potential destinations for path searching. Application works well for some time and then starts to don’t respond when i move mouse over cells.

The utility class for searching path is MonoBehaviour attached to empty object as a Component. Now I removed MonoBehaviour nature of this class to be basic class because i need to lock instance of that class to prevent other cells to call this instance while job is not finished and i make this object static in Cell behaviour.

I got warning that this utility class must be MonoBehaviour or SctiptableObject and application don’t work.

I dont know what to do now :frowning:

First the easy question…
In order to attach a script to an object it must inherit from MonoBehaviour. You can use other classes to do the work but they will have to be utilized from a MonoBehaviour.
Ex.

class CustomClass      // This is not a monoBehaviour
{
 public void DoSomething()
 {
 }
}

class myBehaviour : MonoBehaviour  // This is the class unity attaches to the gameObject
{
  public CustomClass myClass;  // Reference to Non monoBehaviour class
  
   void Update()
   {
        myClass.DoSomething()
    }
}

Now for the other…
I’m not sure from your description exactly how you’ve setup what sounds like an A* pathfinder.

If you have a grid of triggers (cells) your triggering with OnMouseEnter() you can potentially call that more than once per update, because if your at a perspective view your mouse could and probably is inside more than one cell at a time.

The quickest fix I can think for you would be have the cells simply notify the Utility node that it is the cell the mouse is in during Update()… Then only calculate the path on LateUpdate(), This should insure only one calculation per update.

The better fix (I think)
I setup an A* system in the past that utilized a raycast to my ground object to get a world position that could be resolved to a single cell. I don’t know if a single raycast would be faster than a grid of triggers using OnMouseEnter… but I would think it should be, Perhaps others can weight in on this one?

Hope that works for you.

Now it is one call for path searching for sure, but application stops responding. I run my application in debugger and when instruction pointer comes to line where is calculation for minimum distance, application stops responding without any Exception.

private bool discoverCells(Cell cell) {
		bool isDiscoveredCell = false;
		if (cell.upCell != null  cell.upCell.isWalkable) {
			if (!passedCells.Contains(cell.upCell) 
				!activeCells.Contains(cell.upCell)) {
				cell.upCell.minDistance = calculateDistance(cell.upCell, destinationCell); // on this line program stops responding
				activeCells.Add(cell.upCell);
				isDiscoveredCell = true;
			}			
		}//...

What can be possible reasons?

Without seeing more code my guess is that when you get into your calculateDistance() call your getting into an infinite loop. Check your cpu usage when it happens, and you’ll probably see a lot of activity.

Debug it by adding some Debug.Log() statements into your A* loop at various places and / or if you have a while statement, Keep a counter and allow a break if the count goes too high. That should let you know if its an infinite loop. And the break will allow you to at least quit playback in the editor, without needing to force quit unity.

If you can, post the calculateDistance() code.

Thanks man. It was infinite loop becouse I made one mistake in that method.

private int calculateDistance(Cell source, Cell destination) {
		int distance = 0;
		
		int sourceX = source.xIndex;
		int sourceZ = source.zIndex;
		
		int destinationX = destination.xIndex;
		int destinationZ = destination.zIndex;
		
		
		while (sourceX != destinationX || sourceZ != destinationZ) {
			if (sourceX < destinationX) {
				sourceX++;
			} else if (sourceX > destinationX) { // It was - if (sourceX > destinationZ)  ....... omg
				sourceX--;
			}
			
			if (sourceZ < destinationZ) {
				sourceZ++;
			} else if (sourceZ > destinationZ) {
				sourceZ--;
			}
			
			distance++;
		}
		
		return distance;
	}