You are on page 1of 64

Kanad Institute of Engineering &

Management

Simulating Car Racing Game by Applying Path


finding Algorithms

Submitted by

BITHIKA BARIK 25200111002

MANAS KARMAKAR 25200111005

RISHABH SINGH 25200111007

VIVEK NASKAR 25200111014

In particular fulfillments for the requirements of the degree of

BACHELOR OF TECHNOLOGY

In

COMPUTER SCIENCE & ENGINEERING

awarded by the

WEST BENGAL UNIVERSITY OF TECHNOLOGY

May 2015
ACKNOWLEDGEMENT

We express our sincere gratitude to our college Kanad Institute of


Engineering & Management, Durgapur for providing us an
opportunity to undertake and complete such an interesting project
report.

We are very thankful to our respected Director, Prof. Dr. S. N.


Chaudhuri, M.Sc, Ph.D., for the confidence he had on us regarding
this project. We are very much obliged to our respected Chairman,
Mr. Pradip Kr. Agasthy, Secretary, Mr. S. N. Jaiswal and our
Principal, Dr. Anil Baran Adhikari, B.E, PGDCA, Ph. D, for
inspiring and motivating us to bring out a successful project.

We are very grateful to our respected faculty, Mr. Barun Kumar


Das who was our backbone and our guide throughout this project.
Without his assistance we wouldn’t have completed this project within
a short period of time.

It would be really very unfair without the mention of our friends and
families. The immense love and moral support they have given is truly
unmeasurable.
CERTIFICATE

This is to certify the project entitled “Simulating Car Racing


Game by Applying Path finding Algorithms” is a bona fide work
carried out by the following students:

BITHIKA BARIK , Roll no. – 25200111002


MANAS KARMAKAR , Roll no. - 25200111005
RISHABH SINGH , Roll no. – 25200111007
VIVEK NASKAR , Roll no. – 25200111014

Has prepared their FINAL YEAR PROJECT according to the


regulations of Bachelor of Technology degree course in CSE in Kanad
Institute of Engineering and Management and the students have
fulfilled all the requirements for submission of the project work.

………………………………………. …….………………………..
Prof, (Dr.) S. N. Chaudhuri Dr. Anil B. Adhikari
Director Principal
KIEM, Mankar (Burdwan) KIEM, Mankar (Burdwan)

……………………………………….
Mr. Barun Kumar Das
Project Guide
Dept. of CSE
KIEM, Mankar (Burdwan)
PROJECT REPORT ON

“Simulating Car Racing Game by Applying


Path finding Algorithms”

Has successfully completed by

BITHIKA BARIK (Roll no. - 25200111002)

MANAS KARMAKAR (Roll no. - 25200111006)

RISHABH SINGH (Roll no. - 25200111007)

VIVEK NASKAR (Roll no. - 25200111014)

Under the esteemed guidance of Mr. Barun Kumar Das.


Faculty of Computer Science & Engineering dept.
Kanad Institute of Engineering & Management,
Mankar
INDEX
S/no. Topics Page no.

Abstract 1
1 Introduction 2
2 Game Design 3
2.1 Game Design and Concepts
2.1.1 Initial Concept
2.1.2 Seceond Iteration
2.1.3 Final Concept
2.2 Devlopment Process
3 Game Engine 5
3.1 Game Framework
3.2 Unity 3D
3.3 Car Physics 6
3.4 Advance Car Physics 7
4 The Game Camera 8
4.1 Basic Camera
4.2 Smooth Camera
5 The Other Camera 10
6 Materials And Methods 10
6.1 Implementing The A*algorithm
6.2 The First modified A*algorithm : reducing 12
waypoints by a line-of-sight algorithm 13
6.3 Dynamic path finding algorithm for random
obstacles avoidance 13
7 Designing The Car Model 14
8 Creating Terrain 25
8.1 Basic Concept 25
9 Track Design 35
9.1 Add Road Marker 36
9.2 Insert Road Marker
36
10 Coding 39
10.1 AI Script 39
10.2 Path Finding Script
42
10.3 Car Camera Script
10.4 Speedometer Script 53
55
11 References 58
12 Conclusion 59
ABSTRACT

This bachelor thesis describes a case study, where we are focusing on


developing a 3D racing car game, using a process based upon agile
development; an evolutionary development method.

The thesis will cover implementation of real-time graphics, physics


engine, network support, as well as sound effects and background
music.

In the end, our case study will show that this development process was
an appropriate choice for our game development project.

1|Page
1. Introduction
Developing software applications is a time-consuming process, and with
time-consuming processes come high costs. During the last years, several
software development methodologies, often known as agile software
development, have become widely used by software developers to address this
issue. Many different development methodologies can be more or less good,
depending of the task and application type.

One of the software development methodologies is the evolutionary software


method, which, as the name hints, takes on an evolutionary approach to the
problem, and allows the project to evolve through different stages of the
project. Our case study will show how well this evolutionary approach worked
on our project where we choose to develop a 3D graphic computer game. Some
requirements for the computer game were given from the beginning, such as:

3D graphics – The game must contain 3D models, and render these in the
game. 3D environments were never a requirement, and platform games with
2D environment could still open up for 3D objects.

Impressive result – The game result must impress whoever plays the
game. It should last long, and make the players come back and play it over
and over again.

Graphical effects – To achieve an impressive result, we would need to add


modern graphical effects, such as real-time rendered soft shadows, motion blur,
and ambient occlusion.

Working with these requirements, we decided to use Unity 3D as our platform to


develop our 3D game with. This decision was made with regard to that the platform
had many in-built tools and provided a good framework for us to get started with
the development as fast as possible. The fact that Unity 3D also used javascript as
development language was also in consideration, since we wanted to learn this
newly developed javascript language.

The requirement for the game to contain 3D graphics introduced an interesting


challenge for the project group, since all had none or little experience in 3D
modelling. Spending time learning how to model proper 3D models for our game
was therefore necessary. During the research to find out what 3D modelling
program to use, we found that we could use different studios to create models that
we could later import to our game project. The complete game contains models
made in both Blender and 3D Studio MAX.

With these choices made, we soon had our development environment set to use
Unity 3D supporting the framework, and Blender and 3D Studio MAX for modelling
the graphical components. For some of the sound effects we also made use of Adobe
Audition 2.0.
2|Page
2. Game Design
2.1. Game Design and Concepts
In this project, we were left free to decide what type of game we wanted to develop.
The suggestion was that a racing game would be suitable, since such a game usually
do not depend on advanced assets, e.g. animated models. After some
brainstorming, it was decided that a racing game should be developed. However,
there were two different racing game ideas, which will be described below.

In compliance with our development process, the game concept evolved, as more
and more features were added. To further explain how the game concept evolved,
the development has been divided into three parts.

2.1.1. Initial Concept


Our first concept had a game play similar to Remedy’s game in 1996, called Death
Rally1, where each player had a car equipped with a weapon, and the goal was to
hunt down the opponent’s cars. The other idea was to create a simple race track
where players could collect coins in order to win. Since the first idea involved much
greater work than the latter one, it was decided that the first idea were to be given a
low priority, whereas the second were to be given a high priority.

2.1.2. Second Iteration


We decided that a joint solution would be best, where players are able to collect
coins and then use the money to make upgrades. Example of upgrades was better
weapons, faster engine, and heavier car body. These upgrades would be similar to
the concept of levelling, something that many players appreciate. It was also decided
that the racing track should be a garage or a store-house, filled with containers,
boxes, and miscellaneous objects suitable for that environment. Since driving a real
car around a garage is virtually impossible, it was decided that we should make
remote controlled cars instead.

2.1.3. Final Concept


We kept most of the ideas from the second iteration with one exception for the death
rally concept. It appeared that our first instinct, to give this idea a low priority, was
right and in this last iteration, the idea was dropped. However, a racing game where
players only may collect coins and nothing more, sounded a bit boring. Influenced
by games like Super Mario Kart, it was decided that power-ups should be added.
There are a number of different power-ups, and they could be divided into two
groups; those that affect the car that hit the power-up, and those that affect the
opponents’ cars. A more profound description of the different power-ups follows.

In addition to the other improvements, one change was made to the points system.
It should be possible to collect three types of coins, worth 50, 100 and 200 points.
2.2. Development Process
In a software development project, the resulting product is required to fulfil many
different qualities. Examples of such quality requirements are:

3|Page
robustness, availability, maintainability, dependability and usability. To meet such
varying demands, it is important to base the work on a well prepared strategy. In
software engineering, the term for such a strategy is commonly known as software
process, which is built on one or several software process models.

What Is a Software Process Model?


A software process model is a theoretical philosophy that describes the best way of
developing software. Based on one or several models, a software process is formed
providing guidance on how to operate. A software process model may also be
described as an abstract representation of a soft-ware process. The concept of the
process model is similar to an abstract java class, which cannot be instantiated, but
it can be implemented by another class, thus providing basic guidelines for that
other class.
A model may for example demand customer involvement, but it does
not state exactly how. A process implementing that model should
involve the customer in the process’ activities, but is free to choose
how.
There is not only one type of process model, but two. The first one is the most
common, and described above. The second type of process model is called a process
paradigm, which is a model even more general than an ordinary process model.
Such a model does not hold any details on how the activities that lead to the
completion of a project should be performed, but what it does hold is basic
guidelines of how to develop software, and assumptions about what sort of project
could benefit from implementing a particular model. With this in regard, one can
conclude that a process paradigm provides a framework that may be adapted to
form a process which suits a particular project.

There are three major process paradigms that are commonly used today in software
engineering practice; the waterfall model, component-based software engineering
and evolutionary development.
The Waterfall Model
The Waterfall Model is recommended for large and complex systems that have a
long life-time2. Some systems which carry these attributes are also critical systems.
This means that if a fault would occur, it may result in:

Threat to human life (death or injury)

Economic loss

Environmental damage

It is believed that the waterfall model would be an appropriate choice when


developing a critical system, since the model emphasizes on thoroughness.
The basic concept is to take all the activities and treat them separately. One activity
is always followed by another, in the same way water travels down some falls. This
description becomes even more obvious when looking at a visualization of the
model.

4|Page
1. Requirements definition:
All requirements on the system are found by talking to system users. Example
of requirements can be services, constraints and goals, such as “We want a
webpage that color-blind people can enjoy”.
2. System and software design:
In this activity, the overall architecture of the system is established.
3. Implementation and unit testing:
The software is implemented in units which also are tested.
4. Integration and system testing :
The units are merged together into a complete system. Further testing is
required.
5. Operation and maintenance:
The system is delivered to the customer and put into operation.

“Bugs” are almost always found, and therefore the system required bug-
fixing and maintenance.

In each of the activities described above, one or several documents are


produced. The idea is not to start on a new activity until the documents
belonging to the previous activity is signed off, but in practice, this is not
how it is done. Instead most of the activities overlap and all the
documents feed information to the different activities. Although these
documents provide a good overlook.

3. Game Engine

3.1. Game Framework


To save time in our development process, we choose to use Unity 3d, when
developing our game.
3.2 .Unity 3D
Unity is a cross-platform game engine developed by Unity Technologies and used
to develop video games for PC, consoles, mobile devices and websites. First
announced only for Mac OS, at Apple’s Worldwide Developers Conference in

5|Page
2005, it has since been extended to target more than fifteen platforms. It is now
the default software development kit (SDK) for the Wii U.

Unity Pro is available for a fee and Unity Personal has no fee; it is available for any
use to individuals or companies with less than US$100,000 of annual gross
revenue. On March 3, 2015 with the release of Unity 5.0, Unity Technologies made
the complete engine available for free including all features, less source code and
support. Unity is noted for an ability to target games to multiple platforms.

Five versions of Unity have been released. In 2006 at the 2006 WWDC trade
show, Apple, Inc. named Unity as the runner up for its Best Use of Mac OS X
Graphics category.

3.3 Car Physics:


In this scene, we want to start to affect the player’s car through the use of forces
and torques (angular forces) rather than position and rotation directly. This has
several advantages including more realistic motion, but more importantly, we
don’t have to multiply movements by Time. The deltaTime when working with
physics because forces are already time independent. Once again, start by opening
up the Basic Setup scene, then click on Car Control -> 4 Physics -> carcontrol.js
and examine it in the Inspector panel.

In this section we will build the first version of a raycast car. A raycast car is a car
which slides over the ground. Its wheels don’t spin as at drives forward; in this
respect it is actually more like a snowmobile than a car. Every frame we apply a force
to move it forward. It doesn’t move sideways because we will use a Physic Material
with anisotropic friction. Anisotropic friction is a necessary part of a game involving
motion because it allows you to have different friction values for forward or
sideways motion. When moving sideways we will use a much higher friction value
than forward. This will make the car tend to slide forward instead of sideways and
follow the front wheels when they are rotated. We’ll use a simple, three-step process
to build the first version of a raycast car for the player to control. First, we want to
create colliders for the car: add a box collider to the car body of Player Car, then add
raycast colliders to each of the four wheels. These are added to an object by selecting
the object in the Scene view or the Hierarchy panel, and then selecting Component
-> Dynamics from the menu bar. A raycast collider simply uses a ray for collision
detection instead of a volume shape; i.e., a sphere. Also attach a RigidBody with a
mass of 10 to the Player Car. Second, create a Physic Material and set it up as shown
in the following screenshot. Rename it WheelMaterial and move it to the 4 Physics
directory. Assign this new material to all the 4 wheels using drag and drop.

6|Page
3.4. Advanced Car Physics:
In this section we’re going to improve the raycast car. The main change we’ll make
is that we will now rotate the wheels instead of applying a torque to the entire car to
make it rotate. Start by opening up the Basic Setup scene, and adding a box collider,
raycast colliders, and a RigidBody to the various Player Car parts as we did on page
12 in the previous section. Save as... the scene now in the 5 More Physics directory
naming it simply Physics. Now create and save two new Physic Materials – one for
the back wheel named BackWheel, and one for the front wheel named FrontWheel.
These will give us more control over the car handling, because we can tweak and
fiddle with the friction values for the front and back wheels as separate entities in
the Inspector. Set these up using the values as shown in the smaller Physic Materials
setting screen shot in the left sidebar on page 12. Notice how we refined the values
we’ve assigned the Physic Materials by adding a springy contact to the wheel’s
physics material to make it soft. This is done by enabling the use Spring flag, and
setting spring to 25 and damper to 5. Feel free to play around with these values to
get the dampers in your car right. We can now Run this scene and watch the
improved motion of our car. Now let’s tackle the script associated with this scene:
PlayerCar.js. There’s two things in this script that will give the car better physics in
this section. 1) In the script we will now tweak the center of mass and inertia tensor
so that the car has a lower center of mass (to prevent it from flipping over too easily).
2) We remove the torque from the car because we’ll modify the rotation of the
wheels based on the input horizontal axis instead of torque. When we attach this
script to the player car, the four declared variables will have to be connected in the
Inspector so that the script knows which variable is associated with which wheel
(shown at top left).

Figure: Car physics with while collider

7|Page
4. The Game Camera:
The goal of this shorter section is to create and manage a camera to follow the
player’s car as it races around the track. In a racing game, one of the most common
camera views is from a third-person perspective; that is, behind and slightly above
the player. This project will show you how to create one of these cameras and then
to move it along in a fluid manner with the player car. In more advanced games
you might wish to set up numerous cameras to capture the action from different
angles. This more complex camera work is done by enabling and disabling various
cameras based on user input.

4.1. Basic Camera:


Let’s start by first simply getting the main camera positioned above and behind the
player car. Open our previous scene’s Physics.unity scene. Camera Control Scripts
-> 1 Basic Follow Camera and name the file Camera. This scene contains all of the
elements and scripts from the previous section of the tutorial. Now attach the
Camera.js script to the main camera. The Camera.js script has a distance and
height variable that we will be able to modify from the Inspector, but also a
"target" variable that we will need to assign to the player’s car. Connect this
variable to the player car object the same way we connected the wheel control
variables to the wheel objects of the car object.
The Camera.js script is very simple:
1. We set up variables for height, distance and target.
2. We use the function LateUpdate in this script to make sure that this particular script
runs after any other scripts that are run during a frame.
3. It gets the position and direction of the car to position itself.
4. It places itself a specific distance and height behind the target using variables. In this
instance we’ve specified in the script that behind means along the negative z-axis of the
target. Then we move the camera upwards by height, so the camera looks down on the car.
5. We rotate the camera to always look at the target. Run the scene and drive the player
car to see the camera in action. Neat! But this is a very simple solution. What we’d really
like to see is the camera reacting better to the motion of the player car. We need to create
and use a camera script that smoothes out the motion of the camera as it follows the car.

4.2. Smooth Camera:


Start again by opening the Physics.unity scene.Camera Control Scripts -> 2
Smooth Camera and name the file Smooth Camera. This time, attach the Smooth
Camera script to the main camera. Connect the target variable to the car object as
we did in the previous scene and Run the scene to see the camera react more

8|Page
smoothly to the car’s movement. What’s now happening is that this camera script
smoothes out rotation around the y-axis and height, while still maintaining a static
horizontal distance. This method gives you a lot of control over how the camera
behaves because you can tweak lots of the variables. For every of those smoothed
values we calculate a wanted value and the current value. Then we smooth it using
the Lerp function.

The Smooth Camera.js script is very simple.


1. We set up variables for height, distance and additionally for damping.
2. We calculate both current and wanted rotation and height for the camera.
3. We dampen the height and rotation by using the Lerp function (explained below).
4. We convert our rotation calculation from degrees into radians so that the Quaternion
interface understands it.
5. In this part we finally position the camera where we want it and point the camera to
always look at the target. Run the scene and drive the player car to see the improved
camera in action. Notice that we’re using specifically the Mathf.LerpAngle to damp the
rotation around the player car’s vertical (y) axis, and using Mathf.Lerp to damp the height.
It also uses some other basic functions built into Unity such as EulerAngles, Time.
deltaTime and others. Most of the rest of the script uses basic variables and functions to
move the camera with the car. It’s now time to add opponent vehicles and program them
to race around the track against the player. Otherwise known as the "cool stuff."

Figure: Main camera inspector

9|Page
5. The Other Cars and AI:
This section is where the fun begins. Up until this point we’ve been focusing on
getting a car under the control of the player and also to set up a simple camera that
will smoothly follow the car along a race track. But this is a "racing" game – we
certainly need some other cars on the track that will race around the course trying
to beat us. It will be the most difficult to date as the scripts in this section are more
advanced than anything we’ve looked at so far, mainly because we need to create a
method for opponent cars to drive themselves around the track. To begin the
section we’ll start by creating a car that drives itself around the race track. This car
will be duplicated in the scene to create multiple opponent cars.
Many different types of pathfinding problems exist. Unfortunately, no one
solution is appropriate to every type of pathfinding problem. The solution depends
on the specifics of the pathfinding requirements for any given game. For most racing
game, the artificial intelligence (AI) for opponent characters is needed to find there
path . In our paper, we focus on the car racing game, which can be seen as a kind of
pathfinding problems.

In a car racing game, pathfinding is one of the most important problems. Poor
pathfinding can make game characters seem very headless and artificial. Handling
the problem of pathfinding effectively can go a long way toward making a game
more enjoyable and immersive for the player. The A* algorithm provides an effective
solution to the problem of pathfinding and it also be one of the most popular
algorithm used for the game’s development . Assuming a path exists between the
starting point and the ending point; then the A* algorithm guarantees to find the
best path. Although the A* algorithm is efficient, it still can consume considerable
CPU cycles, especially if you want to simulate pathfinding for a large number of
game characters. The chief shortcoming of the A* algorithm in a racing game is that
it can not solve the problem of random dynamics obstacles avoidance.

In this project, we will first study the A* algorithm in a car racing game, and then
proposes two modified A* algorithm to do pathfinding. After that, we propose a
more general dynamic pathfinding algorithm to solve the problem of random
dynamics obstacles avoidance. All the three algorithms are able to find the path for
a car racing game and can save the most import resource in game, CPU cycles.

6. Materials and Methods:


For a car racing game, the most common artificial intelligence is waypoint
navigation by carefully placing points (nodes) in the game environment to move the
game- controlled characters between each point. The major drawback of this
method is that these waypoints need to be manually setup, and it is a time
consuming work. Meanwhile, these waypoints will depend upon the speedway
track; different speedway track requires different configuration waypoints. In
addition, the number of waypoints and the location of waypoints are also different

10 | P a g e
due to human factors. In order to overcome these problems, we propose two
modified A* algorithms to solve them. Finally, a more general dynamic pathfinding
algorithm which can solve the random obstacles avoidance problem in a racing
game is also proposed. In our paper, we will use the A* algorithm, to find the
shortest path while avoiding the obstacles. The A* algorithm uses path scoring to
determine the best path from the starting node to the destination node. To actually
score each node, A* basically adds together two components. First, it looks at the
cost to move from the starting node to any given node. Next, it looks at the cost to
move from the given node to the destination node.
Equation (1) shows the equation used for scoring any given node. This equation
computes each node's score by adding the cost of getting there from the starting
location to the heuristic value, which is an estimate of the cost of getting from the
given node to the final destination.

f(n) = g(n) + h(n) (1)

where g(n) is the total distance; it has taken to get from the starting position to the
current location. h(n) is the estimated distance from the current position to the goal
destination. A heuristic function is used to create this estimate on how far away it
will take to reach the goal state. f(n) is the sum of g(n) and h(n). This is the current
estimated shortest path. The pseudo code of A* algorithm is shown as Fig. 1

add START to OPEN list while OPEN not


empty
get node n from OPEN that has the lowest f(n) if n is GOAL
then return path
move n to CLOSED
for each n' = CanMove(n, direction) g(n') = g(n) + 1
calculate h(n')
if n' in OPEN list and new n' is not better, continue
if n' in CLOSED list and new n' is not better, continue remove any n'
from OPEN and CLOSED
add n as n's parent add n' to OPEN end for
end while
if we get to here, then there is No Solution
.

Fig. 1. Pseudo code of A* algorithm

11 | P a g e
6.1. Implementing the A* algorithm
Because the first step in pathfinding is to define the search area, we need some way
to represent the game world in a manner that allows the search algorithm to search
for and find the best path. In our game, we use the trick of color collision to do the
collision detection. Using this trick you first need to make a collision detection map,
as shown in Fig. This can be done easily by using any image processing software
(e.g., Photoshop), and then changes the track to the color which users want to set it
as the collision detection color (e.g., block color). Everything else in the collision
detection map, where the cars are not allowed to drive, you just need to paint them
to white (or any color just do not use the track color black). Ultimately, the game
world is simplified by placing 1280*782 nodes, throughout the game environment.
White color nodes represent obstacles and other colors nodes represent the nodes
which can be passed. After that, we have divided our search area into a 1280*782
square grid. This particular method reduces our search area to a simple two
dimensional array. Each item in the array represents one of the squares on the grid,
and its status is recorded as passable or un-passable. The path is found by figuring
out which squares we should take to get from node A to node B. Once the path is
found, the game-controlled car moves from the center of one square to the center of
the next until the target is reached.

In the implementation of our A* algorithm, each time step only four adjacent
nodes (up, down, right and left) will be checked, as shown in Fig. 2. In Fig. 2 the
blue node represents the current node and the green nodes are the adjacent nodes.
In addition, the image size of car is 18*12 pixels and moving speed is two pixels per
time frame. The racing game uses the default frame rate setting in XNA (60 frame /
sec). Therefore, the maximum linear velocity of the car is equal to 120 pixels per
second.

Fig. 2. The current node and the adjacent nodes in A* algorithm

12 | P a g e
6.2. The first modified A* algorithm: reducing waypoints by a line-of-
sight algorithm

As you known, the more nodes placed in the game world the slower the
pathfinding process. If we simplify the search area by using fewer nodes, the
pathfinding work will save many CPU cycles. In our study, we first used the
original A* pathfinding algorithm to find the best path between the start waypoint
and the end waypoint.

After that, we refine above found path by considering a line-of-sight algorithm to


further reduce the number of nodes.
To implement this, the mathematical formula of the Pythagoras Theorem for
triangles is used. It first calculates the way length (distance) between the two
different nodes. If there is no obstacle across the way, then no collision occurs, as
shown in Fig. 3 the waypoints (1, 2) and waypoints (1, 3). Because the waypoint 2
is between the waypoint 1 and 3 and there is no collision occurs, we can remove
the waypoint 2 using the shortcut 1-> 3 instead of the path 1-> 2-> 3. This line-of-
sight process will continue until the end waypoint reached.

Fig. 3. Modified A* algorithm by a line-of-sight algorithm

6.3. Dynamic path finding algorithm for random obstacles


avoidance

In order to generalize the pathfinding algorithm in a racing game solves the


dynamic obstacles avoidance problem. We have recently proposed a dynamic
pathfinding method. Two collision detection points are put in front of the car’s right
side and left side, as shown in Fig. 4. Where the variable y is the half width of car,
that is 6 pixels, and the collision detection distance x is an adjusted variable
indicated the distance from the car center to the center of the two collision detection
points.

13 | P a g e
Fig. 4. Collision detection points of car

How do we actually perform the collision detection in this algorithm? It is easy.


We just need to put several color detection points in front of (or around) the moving
car. Anytime, if the position of the car’s color detection point its color is the same as
the track color (black), then no collision occurs. Otherwise, if the position of the
color detection point its color is white (or not the track color), indicating the car is
leaving the track, which means the car needs to turn a direction to keep the car
inside the track. In our game’s implementation, we will calculate the car’s position
in advance. If in the next time frame the collision is detected. We just simply turn a
default setting radian for the car to avoid collision. In other words, when the
detection point of left front touches the edge of track, the car will turn in a clockwise
direction. Otherwise, the car will turn in a counterclockwise direction, if the
detection point of right front touches the edge of track. In order to make the game-
controlled car look more natural and smooth, the car’s rotation speed is set to 0.25
radians (14.3 degrees) in this study.

Figure: New collision detection points when two original collision


detection points are activated at the same time
7. Designing the Car Model:
For designing the car required for the game, we had to sketch out a blueprint
which would fulfill all the requirements for the game.

First we need to get hold of some blueprints of the car that we want to model. We

14 | P a g e
tend to use www.the-blueprints.com.

Once we have the blueprint we opened Photoshop (or equivalent imaging


program). Then pressed Ctrl+O to bring up the open window, and on finding our
blueprint, we opened the file. The window looked similar to the one below.
Next using the marquee tool (shortcut M) we created a selection box around the
top view of our chosen car. (See below image)

Once selected we pressed Ctrl+C to copy the selection then Ctrl+N to open a new
document. Then pasted the selection into that new document.

15 | P a g e
After doing that we moved onto the next view, which was
going to be the side view. To do that we simply moved the
existing selection box to the bottom of the wheels, and then
right clicked (RMB) and choose the option “Transform
Selection Tool”. Then we moved the top of the box down so
that it was just above the top of the car then we pressed
enter to confirm the change. We copied the selection and
pasted it to the same document as the top view we did.
Using that method, we did the same for the Front and Rear
views also.

Then we had all four views in a single document as individual layers we saved them
as Individual JPG files. To do this hide the side, front and rear views so that all we
saw the top view. We pressed Ctrl+Shift+S to open the saved document. Before
saving we made sure that we had changed the file type to JPEG and
called it something like “Top” or “Top View”.

We did that
for all four
views to make
sure that we
could only see
one image at a
time.

After we saved them as individual image we saved them as a PSD (Photoshop’s


native file type) file as well.

16 | P a g e
Then we opened
3Ds Max.

We started by creating the planes. In the top viewport we created a plane of any
size. In the modify panel, we changed the size of the plane to match the size (In
pixels) of the top view for the car. Our image size was 2662x1386. (Note: in 3ds
Max the length value is the second number we would see in the explorer window.
In our case length is 1386 and our width value is 2662)

17 | P a g e
Now we had our first plane we needed to create 3 more. There was more than one
way of doing this but we found this way to be the quickest. We pressed the snap
rotation button (Circled in the image below) then pressed the “select and rotate”
button (Shortcut E).

Holding Shift we rotated the plane on the X-axis (the red one) we needed to rotate
90 degrees.

18 | P a g e
Continue to do this until you have 4 planes that look similar to the
image below.

Then we had the 4 planes set up, we wanted to add the blueprints to
them. We opened the Materials window (Shortcut M), then clicked
the small box next to diffuse (right) which opened a new window
(below). We double clicked on “Bitmap” to “Open file” window. Then
we navigated through our file and found our blueprints then double
clicked on one of them.

19 | P a g e
Then we had our blueprints in 3ds Max
changed the name of the material (for the
front image we called the material “Front” or
“Front View” and changed the Self-
Illumination to 100 (see left). We repeated
this for each of the views.

Once we had all four images in 3ds Max we made


sure the “Visible in Viewport” (Right: Right Circle) was
clicked on. We choose the plane we wanted to add
the image to (In our example we used the top view)
and clicked “Add Material to Selected”. Our screen
should look similar to the one below.

20 | P a g e
We did this for all four planes. After this was done we selected all four planes and
right clicked, then we choose “Object Properties” to open a new window. Then we
unchecked “Show Frozen in Gray” and “Renderable”. Next we checked “Backface
Cull” (this made the back of the planes invisible).

21 | P a g e
Then we converted all four planes to editable polygon.

After selecting one plane (front, side or rear) and we checked


the “Preserve UVs” box (right). This allowed us to move edges
of the plane without affecting the image.

22 | P a g e
Then we changed to sub-object mode and selected Edge (box with a picture of a
triangle). On the side view of the car we selected the top (or bottom) edge and moved
it down (or up) until no white remained. We were careful not to cut off the top of the
car. Then repeated the process for the other views, getting rid of any white parts.

Once our planes had no white borders it was time to move them into position. Using
the “Select and Move” tool we moved the side view back to the edge of the top view.
The front and back views went to either end of the top view. (Note: Front view
should be positioned at the rear end of the car and the rear view at the front end).
Then we moved the top view down to the bottom of the side view (See below).

23 | P a g e
Then we selected all planes, right clicked and selected “Freeze Selection”.

Then we saved the file and modelled our car.

24 | P a g e
8. Creating Terrain

8.1. Basic Concepts

A. Coordinate Space
Three axes X, Y and Z – based on the Cartesian coordinate system
(René Descartes, 1637)

B. User Interface
File > New Project

We don’t have to import any of the packages at this point, but do specify
the save to location in the dialog window. We kept all our project related
assets in this location to avoid missing files and broken links later in the
game development process.

File > Save Scene as…

Window > Layouts > 2 by 3

25 | P a g e
User Interface Components (see screenshot on previous page):

1. Scene: This is where you will place any visual assets in your Unity
environment. It will update in real-time when you are previewing the game.
Note the manipulator on the top right; this allows you to switch between a
number of standard views. We are currently in the perspective view (toggle
between isometric (2D) and perspective (3D)). Although this doesn't matter
too much, it allows us to view our scene with a vanishing point, which is the
standard way Unity games will display.

2. Game: When you're not actively running the game, it will show a rendering
of how the game will look, ignoring graphical effects that need to be computed
at run-time, from the point of view of the main camera. When you're
previewing the game, you'll be playing through this window. Since our scene
is currently empty, all this window is showing is the background color.
3. Hierarchy: This lists all the objects in the currently loaded scene, and any
children they may have. Children are objects that can be thought of as
subordinate to the parent object; wherever the top object moves, they'll
follow, keeping the current offset they have to this object. This is an
important concept for Unity beginners to understand; we'll cover it more in
detail later and in the workshops.

4. Project/Assets view: This is a list of all custom assets for our game,
including graphical assets, sound, scripts (more on these later), prefabs
(pre- assembled game objects), and much more. Our current game is
currently using only one empty scene (titled “myFirstScene”).
5. Inspector: Since we currently don't have any objects selected in the
Hierarchy or the Project/Assets view, it's completely blank. The inspector
allows us to look at and tweak individual settings of various game objects and
assets, as well as adjust some global settings. The Inspector is content-
sensitive and changes its parameters based on which game object/asset is
selected. This is also a place to show you your project settings and
preferences by choosing them from the Edit menu.

6. Graphical icons for moving the scene and its contents. The hand
allows us to pan around the scene; when combined with other scene camera
controls, Unity becomes very easy to navigate (see below). The icon on its
right, which looks like four arrows, allows you to move a selected object
around. We call this transforming the object. The next icon allows for rotation
of the object, and the final one allows for uniform scaling of the object.

26 | P a g e
7. Playback bar. This allows us to play, pause, and stop running our game in
the Unity editor. This is the quickest and easiest way to test and tweak the
game.

C. Navigating the scene window

The scene view is what allows us to look around and move the visual assets we
import into Unity. It's how you'll assemble your levels and place important things
like lighting, trigger zones, audio, and much more. Being able to control the
camera is important if we want to do anything at all with it.

Hand Tool (shortcut Q): drag around in the scene to pan our view.
Holding down alt+drag will rotate the view, Ctrl.+drag will allow you to
zoom. It is important to remember that this doesn't move anything in the
scene, just your point of view.
Translate Tool (shortcut X): active selection tool, enables to drag an
object’s axis handles in order to reposition it.
Rotate Tool (shortcut E): using handles to allow us to rotate an object
around either of its axes.
Scale Tool (shortcut R): works the same as the previous two tools, allows
scaling of an object.

D. Our First Unity3D Scene

Now that we can look around the scene, let's learn a few ways we can place things
in it. First we'll take a look at the basic game objects Unity can create without
importing external assets. Unity 3 has geometric primitives (cubes, spheres,
planes, capsule, etc.), lights, particle systems, cameras, and more that it can
create without needing external assets. To access these, go to the top menu bar,
select Game Object ->Create Other and make a choice. To begin with, try making
a simple scene with a cube (functioning as a floor), a sphere, and a light. There's
three different types of light - for now, a directional should work just fine, as light
travels in rays with the direction of the arrows of the light, a good way to simulate
the sun in Unity.

Start by creating a cube:


Game Object > Create Other > Cube
27 | P a g e
We can already use the Inspector window (after selecting the cube in the
hierarchy) to modify its scale properties: Scale: X: 25, Y: 1, Z: 25 and to translate
it Position: X: 0, Y: - 10, Z: 0

Now we just need to move our camera a little back and point it downward to see
the newly created box (it looks more like a plane now, see screenshot on the
following page – we changed the view in the Scene window to left-isometric)

Position: X: 0, Y: 0, Z: -25; Rotation: X: 20, Y: 0, Z: 0;

Tip: If we would like to remove a game objects from the hierarchy/scene –


select them press command+delete or go to Edit>Delete.

E. Basic lights

See: http://docs.unity3d.com/Documentation/Components/class-Light.html

• Directional lights are placed infinitely far away and affect


everything in the scene, like the sun.
• Point lights shine from a location equally in all directions, like a light bulb.
• Spot lights shine from a point in a direction and only illuminate objects
within a cone - like the headlights of a car.
• Area lights (only available for lightmap baking) shine in all directions to

28 | P a g e
one side of a rectangular section of a plane.

We create a directional light source to illuminate the box in the Game window:
Game Object > Create Other > Directional Light

We should also move the light source a little back, up and tilt it downward to
see its effect on the box object:
Position: X: 0, Y: 10, Z: 20; Rotation: X: 30, Y: 180, Z: 0;

See the change in how the light affects the visual appearance of the
box by experimenting with different angles and directions of your
light source: For example:
Position: X: 0, Y: 10, Z: -20; Rotation: X: 30, Y: 0, Z: 0;

29 | P a g e
F. Basic Physics and Materials

First, create a sphere and place it above the ground plane:


Game Object > Create Other > Sphere

Position: X: 0, Y: 2, Z: 0; Scale: X: 4, Y: 4, Z: 4

Since there is a main camera that comes with every scene, you could hit the play
button now and view your scene. Unfortunately, it will be entirely static. You
can't control the movement of the camera and none of the scene is moving itself.
It would be nice if the sphere would behave as we expect it to from our
observations in the real world – it would fall down and bounce (to a certain
extend) when hitting the ground plane. We can simulate this behavior thanks to
Unity3D’s built-in physics engine.

The first thing we need to do is to give the sphere a rigid body component.
Select the sphere and go to: Component > Physics > Rigid Body.
Hit the play button and you see how the sphere is falling, but not bouncing.

In the next step we create a physic material, which will provide the material
properties to make the game object bouncy:
Asset > Create > Physics Material
30 | P a g e
Then drag the newly created physics material from the Asset window onto the
“Sphere” game object in the Hierarchy window (or directly onto the sphere in the
Scene window).

We experimented with the properties of the physics material to make it behave


like a rubber ball – from the default settings, we changed Bounciness to 0.8 and
Bounce Combine to Maximum (for more information on the properties of physic
materials see: http://docs.unity3d.com/Documentation/Components/class-
PhysicMaterial.html).
Hit the play button and see how the sphere is bouncing similar to a rubber ball.

We started experimenting with different heights from which the ball is falling as
well as different angles of the box to see what response they create in the
behavior of the sphere.

G. Creating Materials:
Assets->Create->Material

We will see the new material in you Project/Assets window and its properties in
the Inspector window. In order to change its color double click the color swatch
next to Main color and choose a different color. We apply the material to a game
object by simply dragging it from the Project window onto the game object in
31 | P a g e
the Hierarchy window (like you did when you applied the physics material
above). We can then start tweaking the material’s properties by experimenting
with different shaders from the shader drop-down menu in the Inspector
window.

Another way to change the visual appearance of game objects is to use 2D


textures. A good overview of 2D texture features in Unity is in this chapter of
the software’s documentation: http://unity3d
.com/support/documentation/Components/class-Texture2D.html. I hope we
can take a closer look at textures in one of the following workshops.

H. Using the Terrain Editor and Prefabs (First Person Controller)

After we have learned how to create simple primitive geometries in Unity3D


and attach physics properties to them, let’s explore how we can use prefabs to
move around a virtual environment interactively, using a first person point of
view.
We also create a terrain, so we have a very basic environment to explore. We
can use Unity’s Terrain editor to do this – we start with a simple plane, which
can be easily turned into a topographical landscape.
Note: In 2004 the art ensemble Futurefarmers created Fingerprint Maze a very

32 | P a g e
charming interactive artwork by automatically generating a terrain from
audience member’s fingerprint scans. Visitors were then able to navigate
through their own fingerprint terrain in a first person perspective, see
http://www.futurefarmers.com/survey/fingerprint2.php

First create a new Scene and save it. Then create a terrain:
GameObject > Create Other > Create Terrain.

Access its heightmap resolution by selecting the Terrain in the Hierarchy


window and then working with its resolution properties in the Inspector
window.

I also moved the camera up and over a little, this helps you seeing the original
plane for the terrain a little better: Position: X: 500, Y: 100, Z: 0
I changed the view in the Scene window to top view by clicking on the view
manipulator icon in the Scene window’s top right corner (top-isometric).

33 | P a g e
Now, using the Raise/Lower Terrain tool in the
Inspector window (make sure the Terrain is selected
in the Hierarchy window), I can simply “draw” on
the top view of the ground plane in the Scene
window to create certain terrain features.

I used Brush Size: 70 and Opacity: 90 to create


shapes that are immediately visible, but you can
fine-tune these settings based on what we have
created.
We also already created a directional light (Position: X: 500 Y: 150 Z: 500 and
Rotation: X: 20 Y: 80 Z: 0) so the terrain’s features would look a little more
dramatic.

34 | P a g e
Experiment also with some of the other terrain paint tools, such as “lower terrain
height”, “set terrain height” and “smooth terrain height.”

To see a larger version of your terrain for working on it select the Scene window
and press the “space” bar – this will maximize the window (hitting the space bar
again allows you to return to the regular 2 by 3 layout).

This time we created a terrain manually by “drawing” on the ground plane.


However, you can also import heightmaps to create terrains from actual
images/maps/drawings.

9. Track Design

Select New EasyRoads3D Object from the EasyRoads3D Menu. A dialog


window will appear where you can name the new road object. The new road
object will be added to the hierarchy panel after clicking the Create
Object button.

35 | P a g e
In the property Inspector you will
see the EasyRoads3D toolbar:

9.1. Add Road Markers

Add road markers by activating the Add Markers toolbar tab. Move the mouse to
the position where you want the road to start and click the left mouse button
while holding the [shift] key.

Continue adding markers according the shape of the desired road. We will see
that the road system will create surfaces representing the road and the affected
surrounding which are configurable in General Settings.

9.2. Insert Road Markers

Insert road markers works similar as adding road markers but instead of adding
the marker at the end of the road, it will insert the marker between the 2 closest
markers to the mouse position. Make sure you are in Insert Markers mode by
activating the Insert Markers toolbar tab!

NOTE: In order to add or insert markers make sure is active!

Additional Marker Functions

When two markers are selected you will see the below buttons in the Inspector:

36 | P a g e
Align XYZ: This will align all markers
between the two selected markers on a
straight line

Align XZ: This will align all markers


between the two selected markers on the x
and z-axis

Align XZ Snap Y: This will align all


markers between the two selected markers on the x and z-axis and snap the y
position to the terrain height at that position.

Average Heights: This will average the heights of all markers between the two
selected markers.

Procedural Object Editor Window:

For procedural objects we defined the shape of the object in the Procedural
Object Editor Window. This window will open when we click the button "Edit
Geometry" on the right of the Object Type combo box. This button will become
visible when "Procedural Mesh Object" is selected.

37 | P a g e
The editor window gives a 2D representation of the shape of the procedural
geometry. We can define any shape we want:

1. Add new vertical positions by double clicking on the stage there where we
want to position the new point. Points will be connected to give a clear idea of
the shape.
2. Move points by selecting them (the point turns red) and dragging it while
keeping the mouse down.
3. Delete points with the "Backspace" or "Delete" key.

Controls / Hot Keys:

 [Shift] click: Select and drag or delete multiple points


 [Control] double click: Insert a point between the two closest points
 Z key: Zooms the grid so all the points are clearly visible
 R key: Resets the zoom and positioning to the original values
 Mouse down: and drag, will move the grid
 [alt] drag stage on Y-axis, Mouse scroll, [Command] & drag, right mouse
button & drag: Zooms in / out on the grid.

Side Object Geometry Controls:

1. Selected Index: When we select a point the associated index value will be
displayed in the ComboBox. The purpose of this is become explained in the
NOTE here below.
2. Close Geometry: When checked, the first and last point will connect.
3. Trace Object: if we added a Start or / and End object to the associated slots
in the Object Manager this object will appear here. It can be used to
analyze the geometry and automatically define the shape of the procedural
geometry accordingly. Make sure that those vertices used to connect the start
and end assets with the procedural with each other are at position 0 on,
depending on our modeling application, the y-axis or z-axis.
4. Trace On: Depending on the rotation of the asset we may have to switch
between x-axis, y-axis and z-axis until we clearly see the shape that the
procedural geometry should have. By default objects are traced on the z-axis
when opening the editor window and no points are stored yet for this side
object.
5. Auto Connect: Below the situation is described where we can clearly see
that the dots are positioned correctly but they do not connect in the right
order. Auto Connect will be enabled when we select the first point, from this it
38 | P a g e
will connect all points according the closest neighbor. Depending on the
geometry structure it may simplify reordering of point indexes.
6. Mirror Horizontally: This mirrors the shape horizontally and is useful
when correcting the shape of a duplicated side object or when it turns out that
tracing the geometry of the start or end asset results in a flipped shape.
7. Mirror Vertically: This mirrors the shape vertically.
8. Flip Faces: It may happen that the normal point in the wrong direction, we
will notice this when rendering the side object. This button will flip the faces
so it will appear correctly. This feature is also available in the Side Object
Inspector.

10. Coding

10.1. AI Script:

var centerOfMass : Vector3;

var path : Array;

var pathGroup : Transform;

var maxSteer : float = 15.0;

var wheelFL : WheelCollider;

var wheelFR : WheelCollider;

var wheelRL : WheelCollider;

var wheelRR : WheelCollider;

var currentPathObj : int;

var distFromPath : float = 20;

var maxTorque : float = 50;

var currentSpeed : float;

39 | P a g e
var topSpeed : float = 150;

var decellarationSpeed : float = 10;

function Start () {

rigidbody.centerOfMass = centerOfMass;

GetPath();

function GetPath (){

var path_objs : Array = pathGroup.GetComponentsInChildren(Transform);

path = new Array();

for (var path_obj : Transform in path_objs){

if (path_obj != pathGroup)

path [path.length] = path_obj;

function Update () {

GetSteer();

Move();

function GetSteer(){

40 | P a g e
var steerVector : Vector3 =
transform.InverseTransformPoint(Vector3(path[currentPathObj].position.x,tran
sform.position.y,path[currentPathObj].position.z));

var newSteer : float = maxSteer * (steerVector.x / steerVector.magnitude);

wheelFL.steerAngle = newSteer;

wheelFR.steerAngle = newSteer;

if (steerVector.magnitude <= distFromPath){

currentPathObj++;

if (currentPathObj >= path.length)

currentPathObj = 0;

function Move (){

currentSpeed = 2*(22/7)*wheelRL.radius*wheelRL.rpm * 60 / 1000;

currentSpeed = Mathf.Round (currentSpeed);

if (currentSpeed <= topSpeed){

wheelRL.motorTorque = maxTorque;

wheelRR.motorTorque = maxTorque;

wheelRL.brakeTorque = 0;

wheelRR.brakeTorque = 0;

41 | P a g e
}

else {

wheelRL.motorTorque = 0;

wheelRR.motorTorque = 0;

wheelRL.brakeTorque = decellarationSpeed;

wheelRR.brakeTorque = decellarationSpeed;

10.2. Path Finding Script:

var path:Array;

var rayColor:Color=Color.red;

function OnDrawGizmos()

Gizmos.color=rayColor;

var path_objs:Array=transform.GetComponentsInChildren(Transform);

path=new Array();

for(var path_obj:Transform in path_objs)

if(path_obj!=transform)

42 | P a g e
path[path.length]=path_obj;

for(var i:int=0;i<path.length;i++)

var pos:Vector3=path[i].position;

if(i>0)

var prv=path[i-1].position;

Gizmos.DrawLine(prv,pos);

Gizmos.DrawWireSphere(pos,0.3);

Car control script:

#pragma strict

var WheelFL : WheelCollider;

var WheelFR : WheelCollider;

var WheelRL : WheelCollider;

var WheelRR : WheelCollider;

43 | P a g e
var wheelFLTrans:Transform;

var wheelFRTrans:Transform;

var wheelRLTrans:Transform;

var wheelRRTrans:Transform;

var lowestSteerAtSpeed:float=50;

var lowSpeedSteerAngle:float=10;

var highSpeedSteerAngle:float=1;

var deccelarationSpeed:float=20;

var currentSpeed:float;

var maxReverseSpeed:float=50;

var topSpeed:float=200;

var backLightsObject:GameObject;

var idleLightMaterial:Material;

var breakLightMaterial:Material;

var reverseLightMaterial:Material;

var maxTorque:float=250;

var braked:boolean=false;

var maxBrakeTorque:float=100;

private var mySidewayFriction:float;

44 | P a g e
private var myForwardFriction:float;

private var slipSidewayFriction:float;

private var slipForwardFriction:float;

function Start () {

rigidbody.centerOfMass.y=0.0;

//rigidbody.centerOfMass.x=0.4;

//rigidbody.centerOfMass.z=0.4;

SetValues();

function FixedUpdate () {

Controle();

handBraked();

function SetValues(){

mySidewayFriction=WheelRR.forwardFriction.stiffness;

myForwardFriction=WheelRR.forwardFriction.stiffness;

slipForwardFriction=0.4;

slipSidewayFriction=0.8;

45 | P a g e
function Update () {

wheelFLTrans.Rotate(WheelFL.rpm/60*360*Time.deltaTime,0,0);

wheelFRTrans.Rotate(WheelFR.rpm/60*360*Time.deltaTime,0,0);

wheelRLTrans.Rotate(WheelRL.rpm/60*360*Time.deltaTime,0,0);

wheelRRTrans.Rotate(WheelRR.rpm/60*360*Time.deltaTime,0,0);

wheelFLTrans.localEulerAngles.y=WheelFL.steerAngle-
wheelFLTrans.localEulerAngles.z;

wheelFRTrans.localEulerAngles.y=WheelFR.steerAngle-
wheelFRTrans.localEulerAngles.z;

backLights();

WheelPosition();

EngineSound();

function Controle(){

currentSpeed=2*22/7*WheelRL.radius*WheelRL.rpm*60/1000;

currentSpeed=Mathf.Round(currentSpeed);

if(currentSpeed<topSpeed && currentSpeed>-maxReverseSpeed && !braked){

WheelRR.motorTorque=maxTorque*Input.GetAxis("Vertical");

WheelRL.motorTorque=maxTorque*Input.GetAxis("Vertical");

46 | P a g e
else{

WheelRR.motorTorque=0;

WheelRL.motorTorque=0;

if(Input.GetButtonUp("Vertical")==false){

WheelRR.brakeTorque=deccelarationSpeed;

WheelRL.brakeTorque=deccelarationSpeed;

else{

WheelRR.brakeTorque=0;

WheelRL.brakeTorque=0;

var speedFactor=rigidbody.velocity.magnitude/lowestSteerAtSpeed;

var
currentSteerAngle=Mathf.Lerp(lowSpeedSteerAngle,highSpeedSteerAngle,speed
Factor);

currentSteerAngle*=Input.GetAxis("Horizontal");

WheelFL.steerAngle=currentSteerAngle;

WheelFR.steerAngle=currentSteerAngle;

//WheelFL.steerAngle=10*Input.GetAxis("Horizontal");

47 | P a g e
//WheelFR.steerAngle=10*Input.GetAxis("Horizontal");

function backLights(){

if(currentSpeed>0 && Input.GetAxis("Vertical")<0 && !braked){

backLightsObject.renderer.material=breakLightMaterial;

else if(currentSpeed<0 && Input.GetAxis("Vertical")>0 && !braked){

backLightsObject.renderer.material=breakLightMaterial;

else if(currentSpeed<0 && Input.GetAxis("Vertical")<0 && !braked){

backLightsObject.renderer.material=reverseLightMaterial;

else if(!braked){

backLightsObject.renderer.material=idleLightMaterial;

function WheelPosition()

var hit:RaycastHit;

48 | P a g e
var WheelPos:Vector3;

if(Physics.Raycast(WheelFL.transform.position,-
WheelFL.transform.up,hit,WheelFL.radius+WheelFL.suspensionDistance)){

WheelPos=hit.point+WheelFL.transform.up*WheelFL.radius;

else

WheelPos=WheelFL.transform.position-
WheelFL.transform.up*WheelFL.suspensionDistance;

wheelFLTrans.position=WheelPos;

if(Physics.Raycast(WheelFR.transform.position,-
WheelFR.transform.up,hit,WheelFR.radius+WheelFR.suspensionDistance)){

WheelPos=hit.point+WheelFR.transform.up*WheelFR.radius;

else

WheelPos=WheelFR.transform.position-
WheelFR.transform.up*WheelFR.suspensionDistance;

wheelFRTrans.position=WheelPos;

49 | P a g e
if(Physics.Raycast(WheelRL.transform.position,-
WheelRL.transform.up,hit,WheelRL.radius+WheelRL.suspensionDistance)){

WheelPos=hit.point+WheelRL.transform.up*WheelRL.radius;

else

WheelPos=WheelRL.transform.position-
WheelRL.transform.up*WheelRL.suspensionDistance;

wheelRLTrans.position=WheelPos;

if(Physics.Raycast(WheelRR.transform.position,-
WheelRR.transform.up,hit,WheelRR.radius+WheelRR.suspensionDistance)){

WheelPos=hit.point+WheelRR.transform.up*WheelRR.radius;

else

WheelPos=WheelRR.transform.position-
WheelRR.transform.up*WheelRR.suspensionDistance;

wheelRRTrans.position=WheelPos;

50 | P a g e
function EngineSound()

audio.pitch=currentSpeed/topSpeed+1;

function handBraked(){

if(Input.GetButton("Jump")){

braked=true;

else{

braked=false;

if(braked){

WheelRL.brakeTorque=maxBrakeTorque;

WheelRR.brakeTorque=maxBrakeTorque;

WheelRL.brakeTorque=0;

WheelRR.brakeTorque=0;

SetSlip(slipForwardFriction,slipSidewayFriction);

if(currentSpeed<1 && currentSpeed>-1){

backLightsObject.renderer.material=idleLightMaterial;

51 | P a g e
}

else{

backLightsObject.renderer.material=idleLightMaterial;

if(rigidbody.velocity.magnitude>1){

SetSlip(slipForwardFriction,slipSidewayFriction);

else{

SetSlip(1,1);

function SetSlip(currentForwardFriction:float,currentSidewayFriction:float)

WheelRR.forwardFriction.stiffness=currentForwardFriction;

WheelRL.forwardFriction.stiffness=currentForwardFriction;

WheelFL.forwardFriction.stiffness=currentForwardFriction;

52 | P a g e
WheelFR.forwardFriction.stiffness=currentForwardFriction;

WheelRR.sidewaysFriction.stiffness=currentSidewayFriction;

WheelRL.sidewaysFriction.stiffness=currentSidewayFriction;

WheelFL.sidewaysFriction.stiffness=currentSidewayFriction;

WheelFR.sidewaysFriction.stiffness=currentSidewayFriction;

10.3. Car Camera Script:

#pragma strict

var car : Transform;

var distance:float=6.4;

var height:float=7.4;

var rotationDamping:float=3.0;

var heightDamping:float=2.0;

var zoomRacio:float=0.5;

var DefaultFOV:float=60;

private var rotationVector:Vector3;

function Start () {

53 | P a g e
function LateUpdate () {

var wantedAngle=rotationVector.y;

var wantedHeight=car.position.y+height;

var myAngle=transform.eulerAngles.y;

var myHeight=transform.position.y;

myAngle=Mathf.LerpAngle(myAngle,wantedAngle,rotationDamping*Time.delta
Time);

myHeight=Mathf.Lerp(myHeight,wantedHeight,heightDamping*Time.deltaTim
e);

var currentRotation=Quaternion.Euler(0,myAngle,0);

transform.position=car.position;

transform.position-=currentRotation*Vector3.forward*distance;

transform.position.y=myHeight;

transform.LookAt(car);

function FixedUpdate () {

var localVilocity=car.InverseTransformDirection(car.rigidbody.velocity);

if(localVilocity.z<-0.5){

rotationVector.y=car.eulerAngles.y+180;

54 | P a g e
else{

rotationVector.y=car.eulerAngles.y;

var acc=car.rigidbody.velocity.magnitude;

camera.fieldOfView=DefaultFOV+acc*zoomRacio;

10.4. Speedometer Script:

#pragma strict

// Arrow object

private var m_arrow:blindGUITexturedContainer;

// Arrow shadow object

private var m_arrowShadow:blindGUITexturedContainer;

// Car object

private var car:GameObject = null;

// Initialization

function Start() {

// Get "Car" game object

car = GameObject.Find("barun1");

// Then "Arrow" from child of current object

55 | P a g e
var goArrowTransform:Transform = this.transform.FindChild("Arrow");

if (goArrowTransform) {

m_arrow =
goArrowTransform.gameObject.GetComponent(blindGUITexturedContainer);

// And "ArrowShadow" form child

var goArrowShadowTransform:Transform =
this.transform.FindChild("ArrowShadow");

if (goArrowShadowTransform) {

m_arrowShadow =
goArrowShadowTransform.gameObject.GetComponent(blindGUITexturedConta
iner);

// At every frame

function Update () {

var speed:float = 0.0f;

if (car != null) {

// Get Car's rigid body

var carRigidBody:Rigidbody = car.GetComponent(Rigidbody);

// Get speed of car in car's coordinate system

56 | P a g e
var relativeVelocity:Vector3 =
car.transform.InverseTransformDirection(carRigidBody.velocity);

// Set Z as speed of car

speed = relativeVelocity.z;

if ((m_arrow == null) || (m_arrowShadow == null)) return;

// Set speed angle. 0 is -135 degrees. 160 is 135 degrees.

// Speed arrow angle = (135-(-135))/160 * speed - 135

speed = -135.0f+(Mathf.Abs(speed)/47.0f)*270.0f;

// Set angle to arrow and shadow

//m_arrow.speed = speed;

//m_arrowShadow.speed = speed;

m_arrow.m_angle = speed;

m_arrowShadow.m_angle = speed;

57 | P a g e
11. References

We have gone through certain books, done some research work using
internet, understanding the technologies being used in our project work.

The following references are:

 http://vimeo.com/album/150503

 http://www.futurefarmers.com/survey/fingerprint2.php

 http://unity3d .com/support/documentation/Components/class-

Texture2D.html

 http://unity3d .com/learn/tutorials/modules

 http://unity3d .com/learn

 http://catlikecoding.com>Catlike Coding>Unity

 http://unity3dstudent.com/

 http://cgcookie.com/unity

58 | P a g e
12. Conclusion:

The most common artificial intelligence in a racing game is waypoint


navigation by carefully placing waypoints (nodes) in the game environment to
move the game-controlled characters between each point. This is a very time
consuming and CPU intensive problem. Using the A* algorithm can effectively
solve the path finding problem in a static racing game environment; therefore, we
present two modified A* algorithm instead of putting waypoints by hand and
minimum the lap time. Finally, we propose a more general dynamic algorithm
which can solve the random obstacles avoidance problem in a racing game. All the
three algorithms are able to find the path for a car racing game and can save the
most import resource in game, CPU cycles.

59 | P a g e

You might also like