I’ve wanted to make a good conveyor system for a while now, but I can’t think of how I wanted to make the placement system. Any good conveyor system can tell which direction each one should face, using the conveyors next to it. So far I know and have just hardcoded these values, but its incredibly difficult and unreliable. I was wondering if there’s a better way of doing it? So far I just use a for loop and check the position and i + 1 and i - 1, then changing the current sprite accordingly. If anyone doesn’t know what I mean, I’m looking for something similar to Lumbermills, if that helps.
maybe check out Code Monkey’s tutorial on conveyors? he made the full system as far as I can remember. and there are even better tutorials out there, I’m also 100% positive there was a recent upload to asset store, this thing is super popular.
In general you can set up the following
Make a cardinal orientation enum
public enum Orientation {
East,
North,
West,
South
}
Then make extensions to make semantical correlations
public static class OrientationExtensions {
public static Vector2 ToVector2(this Orientation value) {
switch(value) {
case Orientation.East: return Vector2.right;
case Orientation.North: return Vector2.up;
case Orientation.West: return Vector2.left;
case Orientation.South: return Vector2.down;
default: throw new NotSupportedException();
}
}
}
Super reliable, easy to read.
Aand just now I have realized you mean that you want to graphically orient the conveyor belts?
But now I’m not sure what’s the problem.
a)
If you know the orientation of each sprite, you just choose the sprite that reflects the orientation.
b)
If you want to auto-detect the nearby orientation when placing, there is no other way but to, well, detect the nearby orientation and adjust accordingly. Can you be more precise in what exactly you’re trying to achieve, what you have already information-wise, and why is that insufficient at this point in time?
I have a functioning system, the problem is that it takes up far more than I feel it should. I have at least 50 lines of just switch and if statements to determine positions, when I feel that this could be cut down to a much smaller number and be far more efficient. What I have now are a million tests like if(cs[i + 1].transform.position == transform.position + northVec2) where northVec2 is just a predefined vector 2, which is currently representing 8, 3.75 since thats the difference in position where the tile goes up-right. Then, if thats the case, I change the sprite to the one I made that fits the up-right orientation. I then do this for every possible straight angle, turn, starting point, etc., which grows very fast.
Sometimes this is unavoidable, but what you can do is to move this logic somewhere else, and build a proper utility that you can use on a high-level.
When you want to track a discrete state, it helps to translate it to an integer.
For example, mystate = 5; and this has some meaning to the rest of the system. This is similar to that enum I described before. When there is a logical correlation between the state components, you can also get away with more dimensions, for example SouthWest would mean South + West even though SouthWest is a constant with a value 5 for example.
If you really want to generalize, think of it this way, let’s say you really want to build a compound state from South and West and then check whether something is both South and West. That’s called composing, and you work with flags.
South is just an information on the North-South axis that has 3 possible states: positive, negative, and zero.
Likewise, West lives on the East-West axis. Notice that each axis can have only one state, because they’re mutually exclusive. And so you can quickly figure out that you need 2 bits of entropy to encode this information, because 2^2 = 4.
00 = zero
01 = positive
10 = negative
11 = unused
Now it’s easy to compose two or more axes into a single state, i.e. 10 00 01 would mean positive X, zero Y, negative Z, but would in itself have a value of 33 (which is 100001 in binary).
But to really stay in control over this new mode of thinking, you need to be able to also decompose it.
To work with this, you need to understand bitwise operators. Try with this guide I wrote earlier.
You can thus compose states like this
mystate = Orientation.South | Orientation.West; // composition is encoded
and you can query it like this
southward = ((int)mystate & (int)Orientation.South) > 0; // returns true or false
Of course, this all comes to fruition when you make a dedicated class or a utility that will help you transcend this into tools that are much more readable, for example
if(something.orientation.HasOrientation(Orientation.West | Orientation.South)) {}
// or more conveniently
if(something.orientation.HasOrientation(Orientation.SouthWest)) {}
// which does the same thing
or
something.orientation = somethingElse.orientation.GetOpposite();
There are ways and ways to set this up.
Also don’t forget that you really want to abstract away rotational and reflection symmetries. If you’re comparing two things and care only about their relative differences in orientation, why repeat yourself for every single axis alignment.
There is no need to repeat the same checks all over the place, if you could’ve done it once somewhere and then reused the whole thing. And I see people do this all the time, so it seems that setting this up really depends on your experience and confidence with such systems.
If it’s too hard for you to come up with an abstraction, maybe it is the most accessible and the most readable to simply state a wall of ‘ifs’ and get it done.