How to park my car completely?

Hi dev,

Im new here and trying to learn unity. Im actually working on a car parking game and was wondering if someone could help me in how to park the car completely within the lines rather than just adding an OnTrigger/OnCollision function which I believe wouldn’t be satisfactory for me.
So if anyone could help me in how to code this specific function would be highly appreciated.

Thanks.

Well, if you want to avoid doing things more in code, you could surround the parking spot with thick box triggers. Then wait until the car doesn’t touch any if the four sides. That would mean that the car is either completely without the bounds, or completely outside the trigger zone… So naturally you have to think about the entry situation too (i.e. when you enter the spot area), maybe use triggers for it, too. Just a quick idea.

Thanks for the idea.

btw is there any way I could code as the function shouldn’t called untill the object is completely inside the box collider. I mean Im thinking of to add a full box collider to the parking slot and until the car is completely not entered in the box collider the window shouldn’t pop up that yes the car is parked.

1 Like

Hi @neginfinity

Is there anyway you could help?

@shez561 I think you’re either thinking it a bit backwards, or not thinking about all the solutions.
If you want to go the way you’re seemingly going, why can’t you then put small corner/boundary markers in your car. Then check when each and every one of them is inside a collider?

Actually Im not so good in coding. its not about thinking backwards, its about the easiest way to solve it. Your idea was superb but Im basically weak in how to write specific code according to your idea by adding thick colliders.

You might want to try using Collider.Bounds like this:

@SINePrime there’s many ways to doing this. But something as simple as this will work fine and is easier to customize (imo):

public class DetectVehicle : MonoBehaviour
{
    int collisionCount;

    void Update()
    {
        if (collisionCount >= 4) {
            Debug.Log("Vehicle parked successfully.");
        }
    }

    void OnTriggerEnter(Collider coll)
    {
        if (coll.tag == "Wheel") {
            collisionCount++;
        }
    }

    void OnTriggerExit(Collider coll)
    {
        if (coll.tag == "Wheel") {
            collisionCount--;
        }
    }
}

Anyway, then just add small colliders to wheels, or maybe the extents of the vehicle, and just wait until the collision count is high enough. If it was some 18-wheeler or something like that, you would probably add more colliders and watch for the count needed.

EDIT:
Here’s a mock scene to visualize the setup in case it’s still unclear after my code snippet:

1 Like

Thank you so much @Olmi . You really made it easy for me.
Thanks again

I don’t have “mention” notification enabled, so tagging me is not very useful. For the future reference. I wander around forum randomly, respond to things I find interesting and tend to hang out in general.

Regarding the car.

This is a 2d problem, pretty much.

I would create two components: “ParkingLot” and “ParkingCar”, each representing a rectangle with configurable width and length, and each would draw a wireframe rectangle gizmo in OnDrawGizmos/OnDrawGizmosSelected.
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnDrawGizmos.html

It would look like this in scene view:
5802394--613399--upload_2020-5-4_18-26-18.png

Then I’d place a trigger around the parking lot, and while a car is touching the trigger, I would poll the car for “ParkingCar” component and then solve the problem in 2d by hand:
5802394--613402--upload_2020-5-4_18-29-8.png
(car is green, parking lot is blue)
Basically, both parking lot store width and length, and you want car to be oriented in specific way.

If you merely place colliders around the parking box, this will be a valid parking placement:

Upside-down, wrong direction, on the side, stuck into ground nose down, and so on. As long as colliders aren’t touched.

Hence I’d prefer to solve it in 2d with debug visualization.

To solve it in 2d, transform orientation vecotrs of “ParkingCar” (front/right/up) into parking lot space. This can be done by using parkingLot.transform.worldToLocalMatrix or by calling parkingLot.transform.InverseTransformPoint for position (of ParkingCar), and parkingLot.transform.InverseTransformDirection for directions.
https://docs.unity3d.com/ScriptReference/Transform-worldToLocalMatrix.html
https://docs.unity3d.com/ScriptReference/Transform.InverseTransformDirection.html
https://docs.unity3d.com/ScriptReference/Transform.html

By doing that you get basis vectors of the car in parking lot space.

var carVectorUp = parkingLot.transform.InverseTransformDirection(car.transform.up);
var carVectorForward = parkginLot.transform.InverseTransformDirection(car.transform.forward);
var carVectorRight = parkingLot.transform.InverseTransformDirection(car.transform.right);
var carVectorPos = parkingLot.transform.InverseTransformPosition(car.transform.position);

Past that point.
If carVectorUp.y < 0 (or Vector3.Dot(car.transform.up, parkingLot.transform.up), then the car is upside down.
By calling Mathf.Atan(carVectorUp.y) (or Mathf.Atan(Vector3.Dot(car.transfomr.up, parkingLot.transform.up))) you can calculate if the car is tilted and how much (doesn’t tell you in which direction, though).

Next. If Vector3.dot(car.transform.forward, parkingLot.transform.forward) OR Vector3.dot(car.transform.right, parkingLot.transform.right) are less than zero, then the car is facing wrong direction. If they’re both less than zero, then the car is facing in wrong direction, if only one, then it is flipped upside down.

If the car is aligned to ground and ground is perfectly flat, you can compute angle between car and parking lot by calculating Acos(Mathf.dot(car.transform.forward, parkingLot.transform.forward)).

Next. To verify whether the car is within the lot square, I’d perform simple boundary test. Because the car is within parkingLot space, and space is axis-aligned, we can calculate bounding box in 2d space of the car, and then check against lot boundaries:
5802394--613417--upload_2020-5-4_18-42-37.png
Green is the car, blue is box boundaries, red is AABB of the car within the box.

In this case we’d go like this:

Vector3 carVectorForward... ((car vector forward within parking lot space
Vector3 carVectorRight ((car vector pointing right within parking lot space
Vector3 carVectorPos ((car component positio in parking lot space
ParkingCar carComponent ((component representing car
ParkingLot lotComponent ((component representing lot

var halfWidthVector = carVectorRight * carComponent.width * 0.5f;
var halfLengthVector = carVectorForward * carComponent.length * 0.5f;

//Corners of the car.
var a = carVectorPos + halfWidthVector + halfLengthVector;
var b = carVectorPos - halfWidthVector + halfLengthVector;
var c = carVectorPos + halfWidthVector - halfLengthVector;
var d = carVectorPos - halfWidthVector - halfLengthVector;

var aabbMin = Vector3.Min(Vector3.Min(a,b), Vector3.Min(c, d));
var aabbMax = Vector3.Max(Vector3.Max(a,b), Vector3.Max(c, d));

//Actual overlap test:
bool noOverlap =
    (aabbMin.x > -lotComponent.width * 0.5f)
    && (aabbMax.x < lotComponent.width * 0.5f)
    && (aabbMin.z > -lotComponent.length * 0.5f)
    && (aabbMax.z < lotComponent.length * 0.5f);

bool collision = !noOverlap;

I’m using .x component, because “right” corresponds to parkingLot x axis in local space, and z corresponds to forward axis.

The reason why I’d go with this approach rather than placing colliders is because it gives me greater control over what is “acceptable” car orientation. For example, you could specify that even if no boundaries are touched, the car should be parallel to lot boundaries. Additionally, for a new car and a new lot I’d simply need to add one component and specify their width/length, there will be visualization in the debug with DrawGizmos and so on.

Of course that’s not the only way to do it.

Have fun.

6 Likes

One more thing. @shez561

4 colliders thing @Olmi posted earlier is also a perfectly acceptable solution, but it all depends on how fancy do you want to get.

My approach would allow the game to be as pedantic as you want, meaning you could say “20 centimeters from car side to the edge of parking lot on each side, and perfectly parallel”.

Olmi’s approach would detect car inside the box, but the car can be facing wrong way, be flipped over and so on, and it will still count.

So depending on needs you could do it this or that way. Or some other way.

@neginfinity a simple up vector check would fix the problem with being upside down :). But I thought that as a simple starting point. You are of course right about those parallel checks etc. But those too could be implemented easily with my hacky, less-math approach by just measuring distance to the sides of the parking zone. That way it would be easy to calculate the angle from one side wheels, for example.

True, I just prefer more math-oriented appraoch which gives me a component with 2 parameters and cool wireframe visual in the scene view.

Either way there’s more than one way to do it.

There’s also a small matter of those corner colliders technically affecting physical behavior of the car (IIRC triggers don’t collide with triggers, so they’ll end up as a part of a rigidbody somewhere)

Thank you so much @neginfinity & @Olmi
You guys rock. I appreciate that both of you gave me wonderful ideas.

@neginfinity Is there any way I can approach you sometime?

Personally, I’d start with a marker in the middle of the parking lot and use Vector3.Distance(…) and Quaternion.Angle(…), because I could get a first pass in under a minute. However, once I started tweaking things I think I’d ultimately end up with pretty much exactly what @neginfinity posted.

Great write-up, by the way, @neginfinity .

1 Like

It was an interesting problem, hence the larger writeup.

I have PMs enabled, but, uh, I don’t exactly dedicate my time to free tutoring, and usually respond to things that draw my attention in some way or are interesting to me. No offense intended.

3 Likes

I would do something like this, pseud code

if(!(zone.bounds.Contains(car.bounds.max) && zone.bounds.Contains(car.bounds.min)) return;

if(Quaternion.Angle(car.transform.rotation, zone.transform.rotation) > 10) return;

Thanks again guys.

When I was creating this thread trust me I had nothing in my mind how exactly do I tackle this problem cause Im a bit weak in writing code.
But now with everybody’s suggestion and ideas, Im very much clear about all this.
Big thanks to @Olmi and @neginfinity as both of you gave me two different but wonderful way of solving this.

but the wheels of rcc dont have rigid body on them how to detect collison if body dont have rigidbody

Old topic, but seems proposed solutions are unneccesairly over complicating, for such simplistic game.

Just get position tolerance of parking slot and a car. Then calculate dot product of parking slot direction and car direction.
Make a tolerance of let’s say 5-10%, which is somehow around ±0.95 depending on facing direction.

No colliers, no bounding boxes are required.

That ensures car must be parked in proper manner.

Done.