0% found this document useful (0 votes)
22 views48 pages

SoccerTutorial v2

The document details the development of a simple soccer game in Unity. It describes creating the game window interface to display scores and a timer. It also covers setting up the soccer field, ball, and player assets. Triggers for goals, free kicks, and throw-ins are implemented. Scripts are developed to control the ball and player behaviors.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views48 pages

SoccerTutorial v2

The document details the development of a simple soccer game in Unity. It describes creating the game window interface to display scores and a timer. It also covers setting up the soccer field, ball, and player assets. Triggers for goals, free kicks, and throw-ins are implemented. Scripts are developed to control the ball and player behaviors.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Creating a Soccer Game

Part 1

Author: Thiago Campos Viana


Contents

Contents............................................................................................ 2

Image List ......................................................................................... 2

Script List .......................................................................................... 3

Part 1: A Simple Soccer Game.............................................................. 4

1.1 The game window ...................................................................... 5

1.2 The rules ................................................................................... 7

1.3 The assets ................................................................................. 8

1.4 The ball .................................................................................... 11

1.5 The player positions ................................................................... 14

1.6 Next steps ................................................................................ 48

Image List

Image 1 - Game Window ..................................................................... 5

Image 2 - Classes ............................................................................... 7

Image 3 - Player................................................................................. 9

Image 4 - Player Modeling ................................................................... 9

Image 5 - Player Animation ................................................................. 9

Image 6 - Unity3d ............................................................................. 10

Image 7 - Unity3d and the soccer field ................................................. 11

Image 8 - Defending .......................................................................... 15

Image 9 – Atacking ............................................................................ 16

Image 10 - Setting up the points ......................................................... 17

Image 11 - The invisible box for the goal trigger.................................... 27

Image 12 - The invisible boxes for the free kick trigger .......................... 29

Image 13 - The invisible box for the throw in trigger .............................. 31

2
Script List

Script 1 - BallBehavior.js .................................................................... 14

Script 2 - SoccerTeam.js .................................................................... 27

Script 3 - goalTrigger.js ...................................................................... 29

Script 4 - FreeKickTrigger.js ................................................................ 30

Script 5 - throwInTrigger.js ................................................................. 32

Script 6 - PCThirdPersonController.js .................................................... 37

Script 7 - ThirdPersonController.js ....................................................... 47

3
Part 1: A Simple Soccer Game

This series of tutorials will detail the development of a socer game,


starting with a simple soccer. The first part of the project is based on
Simple Soccer writed by Mat Buckland in his book Programming
Game AI by Example.

The first part of the tutorials has the following objectives:

Provide an overview of the game to be developed.

Create the field, the goals and create the script that records the
occurrence of a goal, side kicks, and corner kicks.

Develop the camera control script.

Create the score field on the game window that will show the
goals on each side of the field.

Create the game timer.

Start the development of scripts responsible for controlling the


ball and players.

4
1.1 The game window

Image 1 - Game Window

In this game, the parts of the screen that will be shown are A and B.
Parts C, D, E and F will be coded in a future tutorial. The script to
display the score and the clock is:

// SGUI.js

// You can assign here an object of type GUISkin, which sets the GUI style.

var gSkin : GUISkin;

private var isLoading = false;

// The variables responsible for storing the amount of goals from each
team.

var teamAScore:int= 0;

var teamBScore:int = 0;

// A float which controls the elapsed time of the match.

var timer:float=0;

5
// Function to show the GUI of the game.

function OnGUI()

// If gSkin variable is not null, change the style of GUI.

if(gSkin)

GUI.skin = gSkin;

// Draw the area that will show the team name and score.

GUI.Button( Rect( 15, 20, 220, 30), "", "button");

// Name of the first team, "BRA" - Brazil

var message = "BRA ";

// The score has 2-digits, so the amount of goals goes from 00 to 99.

if (teamAScore < 10 )

message+="0"+teamAScore;

else message+= teamAScore;

// BRA 00 x ..

message+=" x ";

// BRA 00 x 00 ARG

if (teamBScore < 10 )

message+="0"+teamBScore+" ARG";

else message+= teamBScore+" ARG";

// Draw the timer area.

GUI.Label ( Rect( 20, 20, 210, 35),message, "label");

timer += Time.deltaTime;

GUI.Button( Rect( Screen.width - 110, 20, 80, 30), "", "button");

// Shows the timer.

if( Mathf.Floor((timer - (Mathf.Floor(timer/60)*60))) < 10)

6
GUI.Label ( Rect( Screen.width - 105, 20, 100, 35),
"0"+Mathf.Floor(timer/60)+":0"+Mathf.Floor((timer -
(Mathf.Floor(timer/60)*60))), "label");

else

GUI.Label ( Rect( Screen.width - 105, 20, 100, 35),


"0"+Mathf.Floor(timer/60)+":"+Mathf.Floor((timer -
(Mathf.Floor(timer/60)*60))), "label");

This script should be assigned to the MainCamera object.

1.2 The rules

SoccerPitch

2 2 1

Goal SoccerTeam SoccerBall

4
1 1

FieldPlayer StateMachine GoalKeeper


1 1

Image 2 - Classes

In the game, there are two teams. Each team has four players
and a goalkeeper.

7
The field has two goals and one ball.

There are no faults.

In the event of a goal, the ball goes into the midfield and the
players take their starting positions. The possession of the ball
goes to the team that conceded the goal.

In the event of a corner kick or goal kick, the ball goes into
the midfield. The ball possession goes to the team that was not
with the ball possession.

In the event of a throw-in. The team that was not in


possession of the ball, has a time to catch the ball and put it
back in play.

1.3 The assets

The models were made with "Blender":

Name Animations Details

Player Running ( ok ),
Kicking,
Scoring,
Waiting.

Ball none

Pitch none

Goal none

Stadium none Includes the pitch.

8
Image 3 - Player

Image 4 - Player Modeling

Image 5 - Player Animation

9
Image 6 - Unity3d

10
Image 7 - Unity3d and the soccer field

1.4 The ball

The ball is a GameObject with a rigidbody and a script called


BallBehavior.js.

// BallBehavior.js

// Pointer to the player with the ball.

var myOwner:Transform;

// Store the starting position of the ball.

var iniPosition:Vector3;

// Pointer to the teams.

var teamA:Transform;

var teamB:Transform;

11
var canMove:boolean;

// Variable used in the function keepPosition, that keeps the ball in this
position.

var lastPosition:Vector3;

// Function executed when initializing the object.

function Awake(){

// Start position is set as the position of the ball in the Unity editor.

iniPosition = transform.position;

// The ball can move.

canMove = true;

// Find the team objects.

teamA = GameObject.FindWithTag ("BlueTeam").transform;

teamB = GameObject.FindWithTag ("RedTeam").transform;

lastPosition = iniPosition;

// Update function

function Update () {

// Check if the ball can move.

if ( !canMove ){

keepPosition();

return;

// If there is one player controlling the ball, the ball must remain in
front of him.

if(myOwner){

transform.position = Vector3(0,transform.position.y,0) +
Vector3(myOwner.position.x,0,myOwner.position.z) + myOwner.forward*2;

12
if(myOwner.GetComponent(CharacterController).velocity.sqrMagnitud
e > 10)

transform.RotateAround (transform.position, myOwner.right,


5*Time.deltaTime *
myOwner.GetComponent(CharacterController).velocity.sqrMagnitude);

// Goal function.

function OnGoal(){

// No player has control of the ball.

myOwner = null;

// Sets the linear velocity of the ball to zero.

rigidbody.velocity = Vector3.zero;

// Sets the angular velocity of the ball to zero.

rigidbody.angularVelocity= Vector3.zero;

// Ball should keep the position until the players take their positions.

canMove= false;

// LastPosition is used in the function keepPosition, keeping the ball in


one point

lastPosition = iniPosition;

// Keeps the ball in the lastPosition point.

function keepPosition(){

transform.position=lastPosition;

rigidbody.velocity = Vector3.zero;

rigidbody.angularVelocity= Vector3.zero;

13
// ThrowIn function

function OnThrowIn(){

myOwner = null;

rigidbody.velocity = Vector3.zero;

rigidbody.angularVelocity= Vector3.zero;

lastPosition = transform.position;

Script 1 - BallBehavior.js

1.5 The player positions

In this tutorial, each team has four players and a goalkeeper,


players assumes two formations, attack and defense, each
represented by a set of empty GameObjects, which are arranged on
the map following a certain pattern. Image 8 shows how these
objects should be placed into the position of defense and Image 9 the
attack.

14
Image 8 - Defending

15
Image 9 – Atacking

16
Image 10 - Setting up the points

17
// SoccerTeam.js

// The player that is being controlled.

var controllingPlayer:Transform;

// The player that will give support for the player that is being
controlled.

var supportingPlayer:Transform;

// The closest player to the Ball.

var playerClosestToBall:Transform;

// The player that will receive the pass.

var receivingPlayer:Transform;

// The opposing goal, it should be a GameObject.

var targetGoal:Transform;

// The team's goal, also a GameObject.

var homeGoal:Transform;

// True for Team controlled by the pc, false for controlling team for
the user.

var isPC:boolean = true;

// Is the team with the ball?

var hasTheBall:boolean;

// Pointer for the opposing team's GameObject.

var opponentTeam:Transform;

// Arrays of empty GameObjects representing the attack positions


and defense.

var defendingTargets:Transform[];

var attackingTargets:Transform[];

// Pointer to the ball.

var soccerBall:Transform;

18
// Is the team in attacking?

var isAttacking:boolean;

// Is the team defending?

var isDefending:boolean;

// Should the ball be in the middle of the field?

var prepareForKickOff:boolean;

// The ball is in the lateral.

var prepareForThrowIn:boolean = false;

// Pointer to the team's players.

var players:Transform[];

function Awake(){

// it looks for the object with the tag " SoccerBall " and
associates the variable soccerBall to the returned object.

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

// When the game is begeining, the team is in the defense


position.

isAttacking = false;

isDefending=true;

// In the begining of the game, the players should goes to the


kick off position.

prepareForKickOff = true;

// Function that adds the script PCThirdPersonController to all


players.

setUpPlayers();

// The game begins with RedTeam with the ball ownership.

if(transform.tag == "RedTeam"){

19
opponentTeam = GameObject.FindWithTag
("BlueTeam").transform;

hasTheBall = true;

else opponentTeam = GameObject.FindWithTag


("RedTeam").transform;

// find the closest player to the ball and associates him with the
variable playerClosestToBall

findClosestToBall();

controllingPlayer = playerClosestToBall;

// If the team is controlled by the user, controllingPlayer is


controlled by the user.

if (!isPC) switchController(controllingPlayer);

// Players assumes the defense position.

defendingFormation();

function setUpPlayers(){

for (var child : Transform in players) {

child.gameObject.AddComponent(PCThirdPersonController);

function defendingFormation(){

var x = 0;

for (var child : Transform in players) {

20
if( child != controllingPlayer )
child.GetComponent(PCThirdPersonController).targetPoint =
defendingTargets[x];

else
child.GetComponent(PCThirdPersonController).targetPoint =
soccerBall;

x++;

function preparingFormation(){

var x = 0;

var script =
controllingPlayer.GetComponent(ThirdPersonController);

if ( script != null ){

controllingPlayer.Destroy(script);

controllingPlayer.GetComponent(PCThirdPersonController).canM
ove = true;

for (var child : Transform in players) {

child.GetComponent(PCThirdPersonController).targetPoint
= defendingTargets[x];

x++;

function attackingFormation(){

var x = 0;

for (var child : Transform in players) {

21
if( child != controllingPlayer)
child.GetComponent(PCThirdPersonController).targetPoint =
attackingTargets[x];

else if (
!controllingPlayer.GetComponent(PCThirdPersonController).playerHas
TheBall() )

child.GetComponent(PCThirdPersonController).targetPoint =
soccerBall;

else
child.GetComponent(PCThirdPersonController).targetPoint =
targetGoal;

x++;

// Are all the players in their initial position?

function allPlayersAtHome():boolean{

var x = 0;

for (var child : Transform in players) {

if ( ( child.position - defendingTargets[x].position
).sqrMagnitude > 3 ) return false;

x++;

return true;

function Update () {

findClosestToBall();

// Verifies if it is in the kickOff state

if (prepareForKickOff){

22
// If it is the kick off state, it executes the actions of the
state.

// Send all players to preparing formation positions.

preparingFormation();

// If all the players are in their initial positions

if ( allPlayersAtHome() )

// If all the players of the opposing team are in their


initial positions and the team is with the ball ownership, leaves the
state

// If some player of the opponent's team is with the


ball, leaves the state

if(
(opponentTeam.GetComponent(SoccerTeam).allPlayersAtHome() &&
hasTheBall ) || soccerBall.GetComponent(BallBehavior).myOwner !=
null )

prepareForKickOff = false;

controllingPlayer = playerClosestToBall;

if (!isPC) switchController(controllingPlayer);

soccerBall.GetComponent(BallBehavior).canMove = true;

else

return;

else

return;

23
// Verifies if it is in the throw in state

if(prepareForThrowIn){

// If it is the throw in state, it executes the actions of the


state.

// Send all players to preparing formation positions.

preparingFormation();

// If the opponent is with the ball, leaves the state.

if ( soccerBall.GetComponent(BallBehavior).myOwner !=
null )

prepareForThrowIn=false;

//findClosestToBall();

controllingPlayer = playerClosestToBall;

if (!isPC) switchController(controllingPlayer);

else

return;

if ( controllingPlayer != playerClosestToBall ){

var newDistance = (playerClosestToBall.position -


soccerBall.position).sqrMagnitude;

var oldDistance = (controllingPlayer.position -


soccerBall.position).sqrMagnitude;

if (isPC || newDistance < oldDistance*0.7)

switchControllingPlayer(playerClosestToBall);

24
if ( isDefending ){

//defending

// If is in the defense state and the team catches the ball,


it leaves the defense and it begins the attack state

if(hasTheBall){

isDefending=false;

isAttacking=true;

attackingFormation();

defendingFormation();

} else {

//atacking

// if in the attack state and the team loses the ball, it


leaves the attack and it begins the defense

if(!hasTheBall){

isDefending=true;

isAttacking=false;

defendingFormation();

attackingFormation();

if (isPC){

direction = targetGoal.position -
controllingPlayer.position;

if (direction.sqrMagnitude < 400)


controllingPlayer.GetComponent(PCThirdPersonController).kick(target
Goal);

25
}

function findClosestToBall(){

var ballSqrDistance= Mathf.Infinity;

for (var child : Transform in players) {

newDistance = (child.position -
soccerBall.position).sqrMagnitude;

if (newDistance < ballSqrDistance){

playerClosestToBall = child;

ballSqrDistance = newDistance;

function switchControllingPlayer(newControllingPlayer:Transform){

if (!isPC){

switchController(controllingPlayer);

switchController(newControllingPlayer);

controllingPlayer = newControllingPlayer;

function switchController( soccerPlayer:Transform ){

var newScript;

var oldScript;

if (!soccerPlayer.GetComponent(ThirdPersonController)){

newScript =
soccerPlayer.gameObject.AddComponent(ThirdPersonController);

26
soccerPlayer.GetComponent(PCThirdPersonController).canMove
= false;

else

soccerPlayer.GetComponent(PCThirdPersonController).canMove
= true;

oldScript =
soccerPlayer.GetComponent(ThirdPersonController);

soccerPlayer.Destroy(oldScript);

Script 2 - SoccerTeam.js

Image 11 - The invisible box for the goal trigger

// goalTrigger.js

27
// The name of the team owning this goal, “TeamA” or “TeamB”, it
has to be defined in the Unity Editor inspector area

var goalTeam:String;

var soccerBall:Transform;

var teamA:Transform;

var teamB:Transform;

function Awake(){

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

teamA = GameObject.FindWithTag ("BlueTeam").transform;

teamB = GameObject.FindWithTag ("RedTeam").transform;

function OnTriggerEnter (other : Collider) {

if(other.gameObject.layer==9){

if ( goalTeam=="TeamA" ){

Camera.main.GetComponent(SGUI).teamBScore=Camera.main
.GetComponent(SGUI).teamBScore+1;

teamA.GetComponent(SoccerTeam).hasTheBall =
true;

teamB.GetComponent(SoccerTeam).hasTheBall =
false;

} else {

Camera.main.GetComponent(SGUI).teamAScore=Camera.main
.GetComponent(SGUI).teamAScore+1;

28
teamA.GetComponent(SoccerTeam).hasTheBall =
false;

teamB.GetComponent(SoccerTeam).hasTheBall =
true;

soccerBall.GetComponent (BallBehavior).OnGoal();

teamA.GetComponent(SoccerTeam).prepareForKickOff =
true;

teamB.GetComponent(SoccerTeam).prepareForKickOff =
true;

Script 3 - goalTrigger.js

Image 12 - The invisible boxes for the free kick trigger

// FreeKickTrigger.js

var soccerBall:Transform;

var teamA:Transform;

29
var teamB:Transform;

function Awake(){

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

teamA = GameObject.FindWithTag ("BlueTeam").transform;

teamB = GameObject.FindWithTag ("RedTeam").transform;

function OnTriggerEnter (other : Collider) {

if(other.gameObject.layer==9){

if ( !teamA.GetComponent(SoccerTeam).hasTheBall ){

teamA.GetComponent(SoccerTeam).hasTheBall =
true;

teamB.GetComponent(SoccerTeam).hasTheBall =
false;

} else {

teamA.GetComponent(SoccerTeam).hasTheBall =
false;

teamB.GetComponent(SoccerTeam).hasTheBall =
true;

soccerBall.GetComponent (BallBehavior).OnGoal();

teamA.GetComponent(SoccerTeam).prepareForKickOff =
true;

teamB.GetComponent(SoccerTeam).prepareForKickOff =
true;

Script 4 - FreeKickTrigger.js

30
Image 13 - The invisible box for the throw in trigger

// throwInTrigger.js

var soccerBall:Transform;

var teamA:Transform;

var teamB:Transform;

function Awake(){

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

teamA = GameObject.FindWithTag ("BlueTeam").transform;

teamB = GameObject.FindWithTag ("RedTeam").transform;

function OnTriggerEnter (other : Collider) {

if(other.gameObject.layer==9){

soccerBall.GetComponent (BallBehavior).OnThrowIn();

if ( teamA.GetComponent(SoccerTeam).hasTheBall ==
true ){

teamA.GetComponent(SoccerTeam).hasTheBall =
false;

31
teamB.GetComponent(SoccerTeam).hasTheBall =
true;

teamA.GetComponent(SoccerTeam).prepareForThrowIn= true;

} else {

teamA.GetComponent(SoccerTeam).hasTheBall =
true;

teamB.GetComponent(SoccerTeam).hasTheBall =
false;

teamB.GetComponent(SoccerTeam).prepareForThrowIn = true;

Script 5 - throwInTrigger.js

// PCThirdPersonController.js

var soccerBall:Transform;

// The speed when walking

var walkSpeed = 3.0;

// when pressing "Fire3" button (cmd) we start running

var runSpeed = 6.0;

var kickSpeed = 40;

var passSpeed = 20;

var rotateSpeed = 500.0;

var targetPoint:Transform;

32
var canMove:boolean = true;

// The last collision flags returned from controller.Move

private var collisionFlags : CollisionFlags;

private var isControllable = true;

function Awake ()

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

//targetPoint = soccerBall;

// This next function responds to the "HidePlayer" message by hiding


the player.

// The message is also 'replied to' by identically-named functions in


the collision-handling scripts.

// - Used by the LevelStatus script when the level completed


animation is triggered.

function HidePlayer()

GameObject.Find("rootJoint").GetComponent(SkinnedMeshRend
erer).enabled = false; // stop rendering the player.

isControllable = false; // disable player controls.

// This is a complementary function to the above. We don't use it in


the tutorial, but it's included for

// the sake of completeness. (I like orthogonal APIs; so sue me!)

function ShowPlayer()

GameObject.Find("rootJoint").GetComponent(SkinnedMeshRend
erer).enabled = true; // start rendering the player again.

33
isControllable = true; // allow player to control the character
again.

function Update() {

if (canMove){

direction = targetPoint.position - transform.position;

direction.y = 0;

if (direction.sqrMagnitude > 2){

// Rotate towards the target

transform.rotation = Quaternion.Slerp
(transform.rotation, Quaternion.LookRotation(direction), rotateSpeed
* Time.deltaTime);

transform.eulerAngles = Vector3(0,
transform.eulerAngles.y, 0);

// Modify speed so we slow down when we are not


facing the target

var forward =
transform.TransformDirection(Vector3.forward);

var speedModifier = Vector3.Dot(forward,


direction.normalized);

speedModifier = Mathf.Clamp01(speedModifier);

// Move the character

direction = forward * runSpeed * speedModifier;

34
GetComponent
(CharacterController).SimpleMove(direction);

function OnControllerColliderHit (hit : ControllerColliderHit )

if (hit.rigidbody == soccerBall.rigidbody){

if (!playerHasTheBall() ||
soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
null){

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
transform;

transform.parent.GetComponent(SoccerTeam).hasTheBall =
true;

transform.parent.GetComponent(SoccerTeam).opponentTeam.
GetComponent(SoccerTeam).hasTheBall = false;

function playerHasTheBall():boolean{

return
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform);

function Reset ()

35
{

gameObject.tag = "Player";

function kick(kickTarget:Transform){

var targetDir = kickTarget.position - transform.position;

if
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform ){

if( Vector3.Angle (transform.forward, targetDir)


<130 ){

soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.v
elocity =targetDir.normalized*kickSpeed;

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

function pass(receiver:Transform){

var targetDir = receiver.position - transform.position;

if
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform ){

if( Vector3.Angle (transform.forward,


targetDir) <130 ){

36
soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.v
elocity = targetDir.normalized*passSpeed;

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

else
soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.velocity
= transform.TransformDirection(Vector3(0,0,passSpeed));

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

function teamHasTheBall():boolean{

return
transform.parent.GetComponent(SoccerTeam).hasTheBall;

function isPC():boolean{

return transform.parent.GetComponent(SoccerTeam).isPC;

// Require a character controller to be attached to the same game


object

@script RequireComponent(CharacterController)

@script AddComponentMenu("Third Person Player/PCThird Person


Controller")

Script 6 - PCThirdPersonController.js

37
// ThirdPersonController.js

var soccerBall:Transform;

var targetGoal:Transform;

// The speed when walking

var walkSpeed = 9.0;

// after trotAfterSeconds of walking we trot with trotSpeed

var trotSpeed = 10.0;

var kickSpeed = 40;

var passSpeed = 20;

// The gravity for the character

var gravity = 20.0;

var speedSmoothing = 10.0;

var rotateSpeed = 500.0;

var trotAfterSeconds = 3.0;

// The camera doesnt start following the target immediately but waits
for a split second to avoid too much waving around.

private var lockCameraTimer = 0.0;

// The current move direction in x-z

private var moveDirection = Vector3.zero;

// The current vertical speed

38
private var verticalSpeed = 0.0;

// The current x-z move speed

private var moveSpeed = 0.0;

// The last collision flags returned from controller.Move

private var collisionFlags : CollisionFlags;

// Is the user pressing any keys?

private var isMoving = false;

// When did the user start walking (Used for going into trot after a
while)

private var walkTimeStart = 0.0;

private var isControllable = true;

function Awake ()

moveDirection =
transform.TransformDirection(Vector3.forward);

targetGoal =
transform.parent.GetComponent(SoccerTeam).targetGoal;

soccerBall = GameObject.FindWithTag ("SoccerBall").transform;

// This next function responds to the "HidePlayer" message by hiding


the player.

39
// The message is also 'replied to' by identically-named functions in
the collision-handling scripts.

// - Used by the LevelStatus script when the level completed


animation is triggered.

function HidePlayer()

GameObject.Find("rootJoint").GetComponent(SkinnedMeshRend
erer).enabled = false; // stop rendering the player.

isControllable = false; // disable player controls.

// This is a complementary function to the above. We don't use it in


the tutorial, but it's included for

// the sake of completeness. (I like orthogonal APIs; so sue me!)

function ShowPlayer()

GameObject.Find("rootJoint").GetComponent(SkinnedMeshRend
erer).enabled = true; // start rendering the player again.

isControllable = true; // allow player to control the character


again.

function UpdateSmoothedMovementDirection ()

var cameraTransform = Camera.main.transform;

var grounded = IsGrounded();

// Forward vector relative to the camera along the x-z plane

var forward =
cameraTransform.TransformDirection(Vector3.forward);

forward.y = 0;

40
forward = forward.normalized;

// Right vector relative to the camera

// Always orthogonal to the forward vector

var right = Vector3(forward.z, 0, -forward.x);

var v = Input.GetAxisRaw("Vertical");

var h = Input.GetAxisRaw("Horizontal");

// Are we moving backwards or looking backwards

if (v < -0.2)

movingBack = true;

else

movingBack = false;

var wasMoving = isMoving;

isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;

// Target direction relative to the camera

var targetDirection = h * right + v * forward;

// Grounded controls

if (grounded)

// Lock camera for short period when transitioning moving


& standing still

lockCameraTimer += Time.deltaTime;

if (isMoving != wasMoving)

lockCameraTimer = 0.0;

41
// We store speed and direction seperately,

// so that when the character stands still we still have a


valid forward direction

// moveDirection is always normalized, and we only


update it if there is user input.

if (targetDirection != Vector3.zero)

// If we are really slow, just snap to the target


direction

if (moveSpeed < walkSpeed * 0.9 && grounded)

moveDirection = targetDirection.normalized;

// Otherwise smoothly turn towards it

else

moveDirection =
Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed
* Mathf.Deg2Rad * Time.deltaTime, 1000);

moveDirection = moveDirection.normalized;

// Smooth the speed based on the current target direction

var curSmooth = speedSmoothing * Time.deltaTime;

// Choose target speed

42
//* We want to support analog input but make sure you
cant walk faster diagonally than just forward or sideways

var targetSpeed = Mathf.Min(targetDirection.magnitude,


1.0);

// Pick speed modifier

if (Time.time - trotAfterSeconds > walkTimeStart)

targetSpeed *= trotSpeed;

else

targetSpeed *= walkSpeed;

moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed,


curSmooth);

// Reset walk time start when we slow down

if (moveSpeed < walkSpeed * 0.3)

walkTimeStart = Time.time;

function ApplyGravity ()

if (isControllable) // don't move player at all if not controllable.

if (IsGrounded ())

verticalSpeed = 0.0;

else

43
verticalSpeed -= gravity * Time.deltaTime;

function Update() {

if (!isControllable)

// kill all inputs if not controllable.

Input.ResetInputAxes();

if (Input.GetButton ("Fire1"))

kick();

if (Input.GetButton ("Fire2"))

pass(targetGoal);

UpdateSmoothedMovementDirection();

// Apply gravity

// - extra power jump modifies gravity

// - controlledDescent mode modifies gravity

ApplyGravity ();

// Calculate actual motion

var movement = moveDirection * moveSpeed + Vector3 (0,


verticalSpeed, 0);

44
movement *= Time.deltaTime;

// Move the controller

var controller : CharacterController =


GetComponent(CharacterController);

collisionFlags = controller.Move(movement);

transform.rotation = Quaternion.LookRotation(moveDirection);

function OnControllerColliderHit (hit : ControllerColliderHit )

if (hit.moveDirection.y > 0.01)

return;

wallJumpContactNormal = hit.normal;

if (hit.rigidbody == soccerBall.rigidbody){

if (!playerHasTheBall()){

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
transform;

transform.parent.GetComponent(SoccerTeam).hasTheBall =
true;

transform.parent.GetComponent(SoccerTeam).opponentTeam.
GetComponent(SoccerTeam).hasTheBall = false;

function kick(){

var targetDir = targetGoal.position - transform.position;

45
if
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform ){

if( Vector3.Angle (transform.forward, targetDir)


<150 )

soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.v
elocity = (targetGoal.position -
transform.position).normalized*kickSpeed;

else

soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.v
elocity = transform.TransformDirection(Vector3(0,0,kickSpeed));

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

function pass(receiver:Transform){

var targetDir = receiver.position - transform.position;

if
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform ){

if( Vector3.Angle (transform.forward,


targetDir) <130 ){

soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.v
elocity = targetDir.normalized*passSpeed;

46
soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

else
soccerBall.rigidbody.GetComponent("BallBehavior").rigidbody.velocity
= transform.TransformDirection(Vector3(0,0,passSpeed));

soccerBall.rigidbody.GetComponent("BallBehavior").myOwner =
null;

function IsGrounded () {

return (collisionFlags & CollisionFlags.CollidedBelow) != 0;

function playerHasTheBall():boolean{

return
(soccerBall.rigidbody.GetComponent("BallBehavior").myOwner ==
transform);

function Reset ()

gameObject.tag = "Player";

// Require a character controller to be attached to the same game


object

@script RequireComponent(CharacterController)

@script AddComponentMenu("Third Person Player/Third Person


Controller")

Script 7 - ThirdPersonController.js

47
1.6 Next steps
As you noticed, it has a lot of things to do in this game, the
main is a script to control the goalkeeper.

In the next tutorial we will make the script to control the


goalkeeper, we will also create the scripts to control the animations,
sounds and much more. See you in the next tutorial.

48

You might also like