Architectural question regarding MonoBehaviours and Input.

I currently have a 3D block/tile based scene (think Minecraft) that I wish to pathfind in. Technically it works perfectly, I’m just wondering about an architecture problem that I have.

The way my code is structured as follows:

  • Environment.cs (Non-Monobehaviour) - The scene is represented by a class called “Environment” which contains a 3D Array of all of the tiles in the scene

  • Tile.cs (Non-Monobehaviour) - Each individual tile is represented by the class “Tile” which handles any logic for the tile - it then contains a reference to the tile view class.

  • TileView.cs (MonoBehaviour) - A script which represents the tiles view in the scene - it is a component of the tile object in the scene.

Then outside of these scripts I have the following:

  • InputManager.cs (Non-MonoBehaviour) - A class whose purpose is to detect when a tile is touched.

  • Pathfinding.cs (Non-MonoBehaviour) - A class which accepts a start tile (Tile.cs), an end tile (Tile.cs) and the search space (an array of Tile.cs) and plots a path between them.

So what I want to do now is when a tile is touched I want to generate a path between a given tile and the tile that has been touched. The problem is that my “InputManager” works by raycasting and thus can only detect touches of MonoBehaviours which aren’t very useful for pathfinding (given that it uses Tile.cs rather than TileView.cs).

I have several solutions but I’m not sure which is best or if theres a better solution?

  • The first is for TileView to hold a reference to Tile so that when the InputManager detects a TileView touch it can retrieve the reference to the Tile. What I don’t like about this is that it tightly couples the tile view with the tile logic and features circular referencing.

  • The second is for Tile to register for an event with the TileView and for the InputManager to throw that event when it touches the TileView which the Environment can then register and re-throw. What I don’t like about this is that the InputManager doesn’t seem to be in total control.

  • The final idea I had is for the InputManager to take the touched TileView and hand it to the Environment which can then lookup which of the Tiles it’s associated with. This is perhaps the cleanest solution but it seems like such a convoluted process.

What does anyone else think - any better ideas?

The third one isn’t that convoluted if you just write the coordinates of the Tile to the TileView.

You can’t really avoid two-way coupling between the view and the model here. The view needs to know what part of the model it represents.

I’m kinda confused by the direction your logic flows in - why does the Tile have a reference to the TileView, and why does the TileView not have a reference to the Tile?

Usually in a Model/View split like what you’ve got going, the Model (your Tiles) should have no idea about the View (TileView) - it should hang out on it’s own, get messages from the user, and respond to those. Then you have a View that just draws whatever the Model represents.

So in my head, your Tiles should have no idea about the TileViews, and asking a TileView about it’s Tile shouldn’t represent any coupling that doesn’t already have to exist.