Gaming Your Way

May contain nuts.

Colliders are mean shits in Unity, let me tell you.

Lots of problems have been revealed since I started to roll my own set of car physics *without* car physics. At first it all seems so easy and logical, get rid of wheels, torque, motor and what not else to get a better control over the car's handling and setup.

 


(first setup, notice the shitload of settings ...)

 

I wanted to be able to take the car and set a top-speed from 1 to 10, as well as acceleration, a value I called "handling" and maybe "boost" or something like that.
Normal wheel based setups are a bugger to tune and I've spent a fair time trying to get the values right but still it felt ... wrong.
Anyway, the idea was simple enough: make a rigidbody box (so I can have "easy" collisions) and move it along the track, but you cannot simply move rigidbodies (or it isn't a particulary good idea as physics calculations depend on force). 

 


(simple box collider setup)

 

OK, just apply force to the box in the direction I want the car to move, which works (in a way) but then failed after I altered the track's physics material to behave more like a road.
Now the friction killed any movement and the easy solution was to just let the box float (representing the car's body only) and that seemed to work well until I recalled that I have sloped tiles. "Oh no problem", I thought and was wrong again.

[we fast forward here a good deal and stop at a point where I have a semi floating box that is always aligned to the ground, does slopes, accelerates, breaks and what not else]

 


(new setup, less settings, looks odd, but the
capsule colliders have their purpose...)

 

Looking at the image you might ask where the difference is, the most obvious are the 4 capsule colliders at the car's corners and you might have noticed that the wheel colliders are back.
There is a simple reason for this setup: it works. Using wheel colliders with no friction is heavy cheating, but it keeps the car's body afloat and always aligned to the ground (esp. on slopes). Reading out their contact points also allows the put the tires on the ground and using the suspension.
The rest of the setup consists of a box collider for the car's body and four capsule colliders (not really needed, but they simplify the handling of some of the collisions).

Yeha!

On to colliders ...

Reading out collisions is easy and Unity offers three events to track these:
- OnCollisionEnter
- OnCollisionStay
- OnCollisionExit

"Oh cool, just listen to OnCollisionEnter and detect when the car crashes into something."

In theory, yes.

In reality it isn't reliably reporting when you collide, and OnCollisionStay is reporting all the time as the wheels nearly always touch the ground (as they are part of the rigidbody setup).

But this is the story for the next post ... 

 

nGFX

And with this I killed a perfectly working game.

This post seems to be somewhat out of context, I fear - but if you follow my posts on google+ you know that I've been working on a racing game.

The problem is that this blog needs writing and updates, but it always seems to be an overkill to post the minor updates (mostly just a few lines)... sometimes these become longer post that would well fit in here - this is one of them and to make it more appealing using an rss reader I start with an image...

 

Where am I?

My last post on MTR dealt with the fact that I tinkered with the tiles, mainly allowing tiles that are larger than 1x1, which resulted in a shitload of new possibilities and problems.

Map formats: [,]

As always there's more than one way to fuck things up and I think it starts with the way you handle our map data. Lets start with the basic things a single tile needs to know: the tile to use and in this case the way it is facing (3d and all that).

The most obvious choice would be the 2d array [x,y], it is easy, clean and simple. Placing a tile is a nobrainer.

So we can use aMap[x,y] = Tile;

Any basic tilebased tutorial teaches you that. We need to store a direction in there to and as we're lazy right now the 2d array becomes a 3d array, using the 3rd dimension to store tile and direction.

aMap[x,y, 0] = Tile;
aMap[x,y, 1] = Dir.

Still easy enough. I'll skip the part where you use an object to store the data of a tile.

Now we're adding 2x2 tiles to this map and voila: instant fuckup.
You could just store the pivot of the tile and leave the other map slots empty (not good if you need to test if the place you want to store a new tile in is already used or not).
Or you could store a reference to the pivot - either as id (but then you have too look up where the pivot is) or as coords pointing at the pivot (but then you need to find a way to store the coords).

Map format [] and [,]

Another way to store the map is to just store the tiles as sequence and use a simple int[,] as index. The size of the tile doesn't matter that much this way (but it offers it's own range of trouble, again, I'll skip that part unless someone wants to know).

We'll use a simple struct for storing the data (tile, direction and some meta stuff):
aTiles[index] = new Tile(Tile, Dir [, coords]);

and store the index in the 2d map array:
aMap[x, y] = index;

Getting back the tile needs some more code, but it's still readable:
Tile = aTiles[aMap[x, y]];

The neat thing is, for a 2x2 tile I can now add a single tile to the aTiles array and do whatever pleases me to keep the map in sync. I settled with -(id + 1000), as -1 marks an empty space on the map. So a larger tile will be stored like this:

aTiles[10] = new Tile(1, 0, 10, 5); // meta shows a 2x2 tile ..., also storing coords in here
aMap[10, 5] = 10; // pivot
aMap[11, 5] = -1010; // this place is used, but it's not the pivot
aMap[10, 6] = -1010; // this place is used, but it's not the pivot
aMap[11, 6] = -1010; // this place is used, but it's not the pivot 

This way storing the map is also a bit easier as we just have to spit out aTiles as "[Tile, x, y]" (instead of dumping the whole map).

Of course ...

... the drawback of changing the map format is that the whole game stops working unless you have all the methods back in place and working again - and that's what I'll be doing after this commercial break.

And hopefully I'll rember to post the next dev log here .... otherwise you know where to find updates.

nGFX