- Home /
raycasts and vehicle traffic
I've been working on a waypoint-based traffic system but am struggling with making sure the vehicles stop adequately for stop lights and other cars. I am using modified versions of the Unity Standard Assets code for carai and control.
I started with simple box triggers, which worked for the most part but I ran into issues with ontriggerstay, ontriggerexit, and the isdriving boolean I have that tells a car to brake or move.
I then looked into raycasts, which I have never used, and am finding it difficult to use them correctly. Sometimes they work and sometimes they don't.
I'm trying to send out a raycast, which detects triggers, then decides if the trigger is a "stop" trigger, and, if it's below the braking distance, tells the car to brake. Otherwise, I want the car to move.
I realized through debugging that transform.forward was going in one direction, regardless of my truck position/rotation. These trucks are child objects of other gameobjects and I cannot figure out after four hours how to set the raycast to these child forwards so I tried using the destination vector3 from the waypoint system. It's still not working though.
Also, now the target distance of the left vehicle says 0 and the right says 11, though they are basically the same distance from their destinations. I'm very confused
Here is my raycast code, which is called before the move function in fixedupdate:
void RaycastFront()
{
RaycastHit TheHit;
Ray ray = new Ray(transform.position, destination);
if (Physics.Raycast(ray, out TheHit))
{
TargetDistance = TheHit.distance;
Debug.DrawLine(transform.position, destination, Color.white);
if (TheHit.collider.isTrigger == true)
{
Debug.Log("ray hit a trigger");
if (TheHit.collider.gameObject.GetComponent<environmentcontroller>()._triggertype == environmentcontroller.triggerType.carstopbox || TheHit.collider.gameObject.GetComponent<environmentcontroller>()._triggertype == environmentcontroller.triggerType.stopbox)
{
Debug.DrawLine(transform.position, destination, Color.yellow);
if (TargetDistance <= brakedistance)
{
Debug.DrawLine(transform.position, destination, Color.red);
m_Driving = false;
}
else { m_Driving = true; Debug.Log("car driving went back to true"); }
}
}
}
}
Answer by lgarczyn · Jan 20, 2020 at 07:06 PM
Why not have the triggers be further up the road, to tells the cars to slow down?
Anyway, you're not building the Ray right. A Ray takes a starting position and a direction, not a destination.
Ray ray = new Ray(transform.position, destination - transform.position);
would work better.
You cars should also be kinematic rigidbodies and use rigidbody.MovePosition to move on FixedUpdate. Not following the rules to move a rigidbody might skip some events like collisions.
Finally, you can use GetComponent on any component of a gameobject, you don't have to type gameobject.GetComponent()
every time.
Ray ray = new Ray(transform.position, destination - transform.position);
This did the trick for me, thank you very much!
Also, thank you for the general advice. I'm curious to learn more about the third piece of guidance you offered, regarding kinemetic rigidbodies and moveposition. I have been pretty dissatisfied with the standard assets carcontroller, wheelcolliders, etc. and am seriously considering building my own car system from scratch. Would you recommend any resource/tutorial that explains that in more detail?
I really can't thank you enough, Raycasts are totally new to me but just that little misunderstanding really broke my brain. I also learned that debugging with drawline was very different than with drawray, which helped.
No problem!
And yeah, debugging the wrong information by accident is a massive time sink sometimes, but you get better at it. I know it happened to me a lot. If you had used the raycast result ins$$anonymous$$d of your destination point, you would have found it faster!
For the car stuff, well it depends the level of realism you want. WheelCollider is an advanced class basically made for racing and driving games, not really a small-scale simulator.
Basically if you want realistic drift etc, go for a car controller, if you just want cars that can crash into each other, non-kinematic rigidbody is fine but will need some coding, if you only want to move them along waypoints and get trigger events, kinematic is perfect.
Finally I can paste the standard advice I give on how to move rigidbodies:
If it is not kinematic, use rigidbody.velocity or rigidbody.AddForce. For example
rigidbody.velocity = Vector3.forward * Input.GetAxis("Vertical") * playerSpeed;
If it is kinematic, use $$anonymous$$ovePosition:
rigidbody.$$anonymous$$ovePosition(rigidbody.position + Vector3.forward * (Input.GetAxis("Vertical") * playerSpeed * Time.fixedDeltaTime));
If you use a CharacterController, use $$anonymous$$ove or Simple$$anonymous$$ove.
Only use rigidbody.position if you want to teleport your rigidbody ins$$anonymous$$d of moving it continuously.
Only use transform.position if you don't have a rigidbody, or want to teleport a character controller.
Rotations follow nearly the exact same rules. Scaling is however more complicated, and should be avoided for rigidbodies.