GAD3000 Games Scripting III

nebraskaslowΛογισμικό & κατασκευή λογ/κού

31 Οκτ 2013 (πριν από 3 χρόνια και 10 μήνες)

120 εμφανίσεις


GAD3000 Games Scripting III


Week 05 A pachinko game


This week we (ie you) will be building a pachinko game. There is a certain amount of
building to do and then there is some considerable scripting, which I will help you with.
This is what the example tha
t I have built looks like:
















Finally, you will need to take the example that you have built and add some extra features


you will do these extra features.


Tasks

1.

First of all, create a plane. The scale of this plane should be (1,1,1).

2.

The b
ackboard is a cube, which looks like this in the inspector window (see below).
You should scale the cube as I have and make sure the rotation is correct.
However, the precise location does not matter too much (although some of your
later scripts will have
to take account of where your cube is). You must make sure
that the cube sits on the plane (it must not be intersecting the plane, as the
rigidbody will not properly if it is). Note the Mass on the rigidbody.





















3.

Add a couple of lights to
the scene (I have used a point light and a spot light but it
does not matter what you have). Move the main camera around until you can see
the scene (such as it is) in the game window.

4.

Each of the pegs in the pachinko system is a small cylinder. It does n
ot matter
where they go but they should be duplicates of each other. See below for the
inspector window for the pegs. You need to make sure the scale is the same as
mine but the locations will vary of course. Note particularly the rigid body settings.
You
also need to add a fixed joint and add it to the cube. Note particularly that you
need to embed the peg inside the cube


approximately one third of the peg should
stick out. Make sure you have every setting correct before you start duplicating.
Start with

a few pegs


you can add more later.




























5.

Now create a sphere, which once will become the ball. This is quite a complicated
object and we will use it as the basis for a prefab. For the time being, create it like
this (again, note the

setting on the rigidbody):

























6.

Notice that there is a script attached to this object. This script is called
KeepSphereIn2d. The code looks like this:

function Update () {


transform.position.z = 1.86;

}


You
MUST

note that 1.86 is cor
rect for my system, based on where my cube is. It is
unlikely to be correct for yours. You want the sphere to be close to the backboard (ie
so that it will hit some of the pins on the way down) but not intersecting, because in
that case the physics will no
t work. Experiment with this until it works properly. The
code here simply clamps the z coordinate of the sphere to a specific position


although we have a 3d environment, the ball is only able to move in two
dimensions. Create an appropriate script and t
ie it to the sphere.


7.

Test out your system thoroughly and make sure that it is working correctly.

8.

In a while, we are going to be instantiating balls where the mouse cursor is placed.
In order to do instantiation efficiently, we need to use a prefab, not a
game object.
Therefore, create a prefab called ball and drag the sphere onto it (ie so that the
small cube in the Project window turns blue).

9.

We're now going to look at how to instantiate these balls. What I want to achieve is
for the player to click on th
e backboard (presumably somewhere near the top)
where s/he wants to drop the ball. The ball then falls through the pins from that
point. The question is, how do we tell where on the board the player clicked?

10.

There are more than one way to do this, but I wa
nted to use this approach because
we are going to look at ray
-
casting later on and I want to introduce it here. What we
are going to do is to cast a ray (imagine shining a laser) from the camera onto the
backboard. Wherever that ray “hits” the board, we wa
nt to position a ball. The ball
drops when the player clicks the mouse. The functionality to do this is in a script
called dropball. For various reasons, I wanted to incorporate the script in an empty
object . To be precise, it runs in the Update() functio
n of this empty object. This
means, “Once every frame the system should check if the player has clicked on the
back
-
board. If so, drop a ball at the point where s/he clicked.”

11.

Add an empty object to your Unity project at this point. Mine is called empty.

12.

Now create a script and call it dropball. Type the following into the script:


var newBall : GameObject;

function Update () {


if(Input.GetButtonDown ("Fire1")) {


// Construct a ray from the current mouse coordinates


var ray : Ray = Camera
.main.ScreenPointToRay(Input.mousePosition);


var hit : RaycastHit;


if(Physics.Raycast(ray, hit)) {


// Create a ball if hit


var pos : Vector3;


pos = hit.point;


pos.z = 1.86; // This needs to be

your z, not mine!


Instantiate(newBall, pos, transform.rotation);


}


}

}


13.

Before progressing, read sections 14 to 21 and make sure you understand
this!!

14.

What does all this code do? The first line simply declares an empty variable


w
e
will drag the ball prefab over this when we have attached it to the empty object.
Each time the mouse is clicked, we need to create a new ball prefab.

15.

Next, we check if the player has pressed fire (ie do they want to create and drop a
ball?)

16.

If they do,
we cast our ray from the camera's viewpoint to the position (in 2d terms)
of the mouse pointer. Remember that the point that the mouse is pointing at does
not have any depth. We “create” depth by casting a ray. We call the ray we are
casting
ray
. We need t
o record it in a variable because we want to use it to find out
if we hit anything.

17.

The next line declares a variable of type
RayCastHit
. At this point, you should
quickly review the Unity 3d scripting manual to see what types
Ray

and
RayCastHit

represent.

18.

The next line (
if(Physics.Raycast(ray, hit))
) is checking to see if the ray
that we cast into the scene actually hit (intersected with) any object in the scene.

19.

Assuming the ray did hit something in the scene, we need to find out at which point
in 3d spac
e it hit the object.
pos

is the point at which we hit the object.

20.

Next, I clamp the z
-
coordinate to the position I want. It is 1.86 in my scene, but it will
probably be different in yours (see task 6).

21.

Once I have the position set up the way I want, I sim
ply instantiate a new ball at that
position.

22.

Now attach dropball.js to the empty object you created in step 11.

23.

You should see the newBall variable exposed in the inspector window (looking at
the empty object). Drag the ball prefab over this so that you wi
ll create a ball when
the user clicks the button.


24.

AT THIS POINT MAKE SURE THAT YOU HAVE SAVED YOUR PROJECT.

25.

If you have followed these instructions correctly, when you run the game, you
should be able to create a ball wherever you click and that ball shou
ld fall through
the pachinko board....

26.


and it will fail to work properly. What is going wrong?



27.

The difficulty is that the system is checking every frame to see if the mouse button
is down. Just clicking a mouse normally might mean that the mouse button

is down
for more than the time it takes to render one frame. In these circumstances, multiple
balls will be created.

28.

What we need is to check to see whether a ball is already being created
before starting to create a new ball. If we are already creating
one, don't try to
create another. I have a fairly quick
-
and
-
dirty approach to doing this and I have
indicated the changes to the previous dropball.js in
bold
:


var newBall : GameObject;

var alreadyCreatingABall = false;


function Update () {


if (Input.Get
ButtonDown("Fire1")) {


// Construct a ray from the current mouse coordinates


var ray : Ray = Camera.main.ScreenPointToRay(Input.mousePosition);


var hit : RaycastHit;


if(Physics.Raycast(ray, hit)
&& !alreadyCreatingABall
) {



alreadyCreatingABall = true;


// Create a ball if hit


var pos : Vector3;


pos = hit.point;


pos.z = 1.86;


Instantiate(newBall, pos, transform.rotation);


}


}




if(Input.G
etButtonUp("Fire1")) {



alreadyCreatingABall = false;


}

}


29.

Obviously, we are using a new variable called alreadyCreatingABall. As you might
expect, this variable is
true

if we are already in the process of creating a ball. Our
modified
if(..)

state
ment now reads like this:

if(Physics.Raycast(ray, hit)
&& !alreadyCreatingABall
) {

What this means is, “if we hit something with our ray
AND

we are
NOT

already
creating a ball, go ahead and create a new ball”. The next statement sets the
variable to
true

s
o that the next time we try to do this, we know that we are already
creating a ball and we should not try to do so again.

30.

This begs a question: “How does it know when it is OK again to create another
ball?”.
Do not proceed unless you can answer this questi
on satisfactorily.


31.

At this point, you should have a working pachinko game. You are now going to
improve it.

32.

Strictly speaking, you don't want the player to be able to drop a ball half
-
way down
the board. Think of a way to force the player to drop the ball

from the top.

33.

We need a scoring system. I envisage three cubes at the bottom of the board (ie
just in front of it. One cube should be in the centre and the player should score 500
(say) for getting a ball into that cube. There should be a cube on either s
ide which
only scores 100.

34.

One question you will need to answer is, “where are you going to maintain your
score?”. Have a look at last week's handout (skittles) to get an idea.

35.

It's a bit lame that the balls just hang around in the system forever


find a
way to
get rid of them after a suitable interval.

36.

Create a limit on how many balls your player can drop.

37.

[Challenging] Create a “game over” screen which displays the player's score.

38.

[Challenging] Create a second scene which is identical to your first (find

a way to
simply copy your first scene). Look in the Scripting manual (see the Unity help for a
link) and investigate the
Application.LoadLevel(..)

command.