Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Seth-Bergman · Nov 20, 2010 at 09:56 AM · aicarwaypointracingwaypoints

How To Add AI To Car/Racer?

As a school project, my class is attempting to mod the unity car tutorial. For a week I have been struggling to get working AI cars which will simply drive around the track. I have found a few tutorials online that deal with this, but none seem to work in Unity3. All I want is for the car to follow the series of waypoints and still react to normal physics (like colliding with another car). I've borrowed the script from the old racer tutorial:

// Variables defined outside of functions appear in the inspector // and can be changed there without having to change the script var frontLeftWheel : Transform; var frontRightWheel : Transform; var backLeftWheel : Transform; var backRightWheel : Transform; var wheelForce = 120.0; //var lookAtPoint : Transform;

// All these variables are only used internally, thus we make them private private var hasWheelContact = false; private var steerMaxAngle = 40.0; private var activeWayPoint : WayPoint;

function Start () { // Initialize the waypoint we drive towards! activeWayPoint = WayPoint.start;

 // Tweak the center of mass.
 // - Low center of mass a bit towards the front
 // - model a long long and not very high car
 rigidbody.centerOfMass = Vector3 (0, 0, 0);
 rigidbody.inertiaTensorRotation = Quaternion.identity;
 rigidbody.inertiaTensor = Vector3 (1, 1, 2) * rigidbody.mass;

}

function UpdateWithTargetPosition (target : Vector3) {

 // Calculate the target position relative to the this transforms coordinate system.
 // eg. a positive x value means the target is to the right of the car,
 // a positive z means the target is in front of the car
 relativeTarget = transform.InverseTransformPoint (target);
 // Calculate the target angle for the wheels, so they point towards the target
 targetAngle = Mathf.Atan2 (relativeTarget.x, relativeTarget.z);
 // Atan returns the angle in radians, convert to degrees
 targetAngle *= Mathf.Rad2Deg;
 // The wheels have a maximum rotation angle
 targetAngle = Mathf.Clamp (targetAngle, -steerMaxAngle, steerMaxAngle);

 // Apply the rotation to the wheels
 // We want the wheels to rotate around the y-axis
 // The rotation has to be relative to the car, which is the transform parent of the wheels
 frontLeftWheel.localEulerAngles = Vector3 (0, targetAngle, 0);
 frontRightWheel.localEulerAngles = Vector3 (0, targetAngle, 0);

 rigidbody.drag = 0;
 if (hasWheelContact)
 {
     // Accelerate
     //force = maxSpeed * force;
     rigidbody.AddRelativeForce (0, 0, wheelForce);

     // We are too fast and need to turn too much. Slow down!
     if (Mathf.Abs (targetAngle) > 15 && rigidbody.velocity.magnitude > 10) {
         // We are too fast
         rigidbody.drag = 4;
     }
 }

 // This is handy for debug visualizing where we actually want to drive
  Debug.DrawLine (transform.position, target);

 // This is reset every frame. OnCollisionStay enables it again.
 hasWheelContact = false;

}

function Update () {

//lookAtPoint = activeWayPoint.Transform;

//transform.LookAt(lookAtPoint);

//}

//function Update() { // Calculate the position the ai car should drive towards targetPosition = activeWayPoint.CalculateTargetPosition (transform.position); // Apply forces, steer the wheels UpdateWithTargetPosition (targetPosition); }

// Whenever we hit a waypoint, skip forward to the next way point function OnTriggerEnter (triggerWaypoint : Collider) { if (activeWayPoint.collider == triggerWaypoint) { activeWayPoint = activeWayPoint.next; } }

// Track if we the wheels are grounded function OnCollisionStay (collision : Collision) { for (var p : ContactPoint in collision.contacts) { if (p.thisCollider.transform == frontLeftWheel) hasWheelContact = true; if (p.thisCollider.transform == frontRightWheel) hasWheelContact = true; if (p.thisCollider.transform == backLeftWheel) hasWheelContact = true; if (p.thisCollider.transform == backRightWheel) hasWheelContact = true; } }

This seems like it's trying to work, but as soon as the car reaches the first waypoint it starts flipping through the air wildly and acting unpredictably. My waypoints have box colliders set as triggers and this script:

// The start waypoint, this is initialized in Awake. // This variable is static thus all instances of the waypoint script share it. static var start : WayPoint;

// The next waypoint, this variable needs to be assigned in the inspector. // You can select all waypoints to see the full waypoint path. var next : WayPoint;

// This is used to determine where the start waypoint is. var isStart = false;

// Returns where the AI should drive towards. // position is the current position of the car. function CalculateTargetPosition (position : Vector3) {

 // If we are getting close to the waypoint, we return the next waypoint.
 // This gives us better car behaviour when cars don't exactly hit the waypoint
 if (Vector3.Distance (transform.position, position) < 6) {
     return next.transform.position;
 }
 // We are still far away from the next waypoint, just return the waypoints position
 else {
     return transform.position;
 }

}

// This initializes the start and goal static variables. // We have to do this inside Awake because the waypoints need // to be initialized before the AI scripts use it. // All Awake function are always called before all Start functions. function Awake () { if (!next) Debug.Log ("This waypoint is not connected, you need to set the next waypoint!", this);

 if (isStart)
     start = this;

}

// Draw the waypoint pickable gizmo function OnDrawGizmos () { Gizmos.DrawIcon (transform.position, "Waypoint.tif"); }

// Draw the waypoint lines only when you select one of the waypoints function OnDrawGizmosSelected () { if (next) { Gizmos.color = Color.green; Gizmos.DrawLine (transform.position, next.transform.position); } }

I'm new at this, so the simplest bare-bones method to do this is all I'm after.. just a car or two to race around the track. Thanks for any help!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by duck · Nov 20, 2010 at 11:35 AM

Perhaps the problem is that you have too few waypoints, resulting in a large sudden change in direction as you reach one and start heading to the next.

The way I tend to do this is to have lots of waypoints (more than it would be practical to manually assign each one's "next" reference).

I create them using a spacing tool along a spline so that you have 100 or more waypoints around the track, and each one is no more than a few metres apart.

If you make sure that these waypoint objects are named sequentially, eg: "trackmarker 0" - "trackmarker 100", rather than assigning the order manually in the editor, you can collect all the references in code, via a loop like this:

using UnityEngine; using System.Collections; using System.Collections.Generic;

public class Track : MonoBehaviour {

 public static Vector3[] routePoints;

 void Start() {

     List<Vector3> collectPoints = new List<Vector3>();
     bool found = true;
     int num = 1;
     while (found) {
         GameObject obj = GameObject.Find("trackmarker "+num);
         if (obj != null)
         {
             collectPoints.Add(obj.transform.position);
             obj.active = false;
         } else {
             found = false;
         }
     }

     routePoints = collectPoints.ToArray();

 }

}

You then have a fairly detailed representation of the curve of the track, as an array of Vector3s.

The next trick is to not use the 'trigger' method of checking whether you reached a waypoint, but rather use vector maths. The reason for this is that you want your target waypoint to always be a certain distance ahead of your car - and that distance should be based on how fast it's travelling. I.E. if the car is travelling very fast, it should be looking much further along the waypoints than its current position.

I don't have time to add further detail to this question right now, but it's something I spend a lot of time on so I'll come back soon to flesh this out a bit!

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Seth-Bergman · Feb 17, 2012 at 12:49 AM 0
Share

Hey thanks a lot, it's been a long time since I asked this, and to be honest at the time the answer was beyond my means.. Now that I've got a little time to play, I've been looking back over some old stuff.. So now, finally, I'm ready to start attempting this method, to refine my old build, which looked ok but didn't really work great.. Thanks!

avatar image
1

Answer by GluedBrain · May 31, 2013 at 04:47 PM

This might help you link text

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Seth-Bergman · Nov 20, 2010 at 10:57 AM

Update: By lowering the y value for centerOfMass to -1 or so the car no longer flies. It still jerks around a lot, but does make it around the track. I'm thinking now it's just a question of tweaking everything.. Still would appreciate any suggestions for refining this!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Mentalist4006 · Jan 11, 2011 at 03:27 AM

I had the same exact question as you did, and it was answered here. I believe it should work.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

How to implement traffic system efficiently in Unity game to run smoothly on mobile device? 1 Answer

Steering an AI vehicle to a waypoint using float of -1 to 1? 1 Answer

Car AI Avoiding Obstacle 0 Answers

Make a Lapping System for a Car Game 1 Answer

Why isn't a Ai Waypoint Spawning??? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges