03 - Conveyors Are For Cool Kids

Welcome Back, Everyone!

We’re here with Dev Blog 03 and things are really starting to heat up. This sprint we had some interesting items on the board for the team so let's catch you guys up.

  • Li - Finalizing the localization system

  • E - Created new art assets

  • Dorian - Creating new SFX and adding them to the manager

  • Josh - Working on input from multiple controllers

  • Me - Working on the beautiful conveyor belts, no fine factory is complete without them

So that’s a rough breakdown of what the team was working on for this sprint and it’s been a journey. So the good news is we’ve successfully retrofitted our factory with some shiny new conveyor belts.

 

As you can see, it could fairly be said that they work… which I’m told is a requirement for a minimum-viable product. So let’s talk about how they work and maybe what can be done better.

 

  1. public void MoveAllItemsOnConveyorBelts()
  2. {
  3. //Guard
  4. if (m_ObjectOnConveyors.Count == 0)
  5. {
  6. return;
  7. }
  8.  
  9. //Iterates through each item that is on a conveyor belt
  10. foreach (var item in m_ObjectOnConveyors)
  11. {
  12. float distance = float.MaxValue;
  13. Belts closestBelt = null;
  14.  
  15. //Iterates through each conveyor belt object and checks the distance to find the closest belt to the item (ie the belt the item is on)
  16. foreach (var belt in m_ConveyorBelts)
  17. {
  18. float delta = (item.transform.position - belt.gameObject.transform.position).sqrMagnitude;
  19.  
  20. if (delta < distance)
  21. {
  22. closestBelt = belt;
  23. distance = delta;
  24. }
  25. }
  26.  
  27. //Copies the list of items on the conveyor belt and removes the current item in the current iteration of the foreach loop we are scope in
  28. m_TempObjectsOnConveyors = m_ObjectOnConveyors.ToList();
  29. m_TempObjectsOnConveyors.Remove(item);
  30.  
  31. float distanceBetweenObjectsOnBelt = float.MaxValue;
  32.  
  33. //Iterates through the list of all OTHER items on conveyors to find the closest one
  34. foreach (var itemTwo in m_TempObjectsOnConveyors)
  35. {
  36. float deltaBetweenObjectsOnBelt = (item.transform.position - itemTwo.gameObject.transform.position).sqrMagnitude;
  37.  
  38. if (deltaBetweenObjectsOnBelt < distanceBetweenObjectsOnBelt)
  39. {
  40. distanceBetweenObjectsOnBelt = deltaBetweenObjectsOnBelt;
  41. }
  42. }
  43.  
  44. //Checks first to see if the next closest item on the belt is not too close then moves the item to the next belt in the chain
  45. if (distanceBetweenObjectsOnBelt > m_BeltItemDistancePadding * m_BeltItemDistancePadding)
  46. {
  47. //Checks that the distance between the item and the closest belt is not too far into the next belts range
  48. if (distance < m_BeltItemRange * m_BeltItemRange)
  49. {
  50. item.transform.position = Vector3.MoveTowards(item.transform.position, closestBelt.m_NextWaypoint.transform.position, m_BeltMoveSpeed * Time.deltaTime);
  51. }
  52. }
  53.  
  54. //Clears the list for the next iteration
  55. m_TempObjectsOnConveyors.Clear();
  56. }
  57. }
 

Alright, so let’s talk about the above monstrosity. So Basically what is happening above can be broken down in plain English as follows. For each item that is on a conveyor belt, we search through all of the conveyor belts to find the closest one, then find the next one in the series and finally we move that object to the next conveyor belt in the series.

This approach works and as a bonus, it does not use the Physics system to do so however, there are some clear downsides. For one, we’re doing a lot of math every single frame. We’ve also built a system that is error-prone as there are a ton of possible edge cases that we’re currently not checking for and maybe the worst of all, it’s awful to read. Frankly finding a way to include a 57-line function in this blog was a technical challenge itself. Oh, and we have a guard clause that is entirely unnecessary because… reasons. Look, this is not my best work frankly so let’s see what we can to do fix it.

With a three-week sprint upcoming we have plenty of time to refactor this into something a lot cleaner. As a starting point without even changing how anything works, we can improve the readability and length by leveraging Linq to shorten this function and remove a ton of reused code. I’ve also been thinking about how to streamline this system further and I have a couple of thoughts on that matter.

  1. Given that we are using a grid system and we know that each grid is 1 x 1 unit we may be able to leverage that somehow to reduce math

  2. Currently, each conveyor holds a waypoint to the next conveyor in the chain which requires a lot of setup when adding new conveyors

  3. There is no easy way to tell if there is an object occupying the space ahead of you with the current system

    1. The astute among you may have noticed that an object will stop moving if there is another object in close proximity either behind or ahead which is not the behavior we desire in this circumstance.

The reality here is that with the given time constraints and the situation at present, this is the system I ultimately went with, but as with most things in life, there is room for improvement. While it may not be the highest on the priority list a refactor for this one is on my DevOps board and with any luck, I’ll be able to make some time to clean it up shortly.

That’s all I’ve got for you all this time around, make sure to tune in next time to read all about how we managed to cobble together machines and conveyors to build an interestingly unique system to process items.

Previous
Previous

04 - Machines Do Stuff

Next
Next

02 - Interactions Everywhere