位置: 编程技术 - 正文

Intermediate Unity 3D for iOS: Part 2/3

编辑:rootadmin

推荐整理分享Intermediate Unity 3D for iOS: Part 2/3,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

This is a tutorial by Joshua Newnham, the founder of We Make Play, an independent studio crafting creative digital play for emerging platforms.

Welcome back to our Intermediate Unity 3D for iOS tutorial series!

In this tutorial series, you are learning how to create a simple 3D game in Unity called “Nothing but Net”. In the first part of the tutorial, you learned about the following Unity concepts:

The Unity3D InterfaceAssetsMaterials and TexturesScene PositioningLightingCamera PositioningPhysics and CollidersPrefabs

Everything in your scene looks pretty sharp, but so far everything you’ve done has been through Unity’s visual scene designer. In other words, you haven’t written any code yet!

Well, that’s about to change :] In this part of the tutorial, you’ll start to breathe some life into your game through code, and add some interaction and animation into the scene!

This tutorial picks up where the previous tutorial left off. If you want to start at a “known good” state, you can use the project where we left it off in the previous tutorial. To open it in Unity, go to FileOpen Project, click Open Other, and browse to the folder. Note that the scene won’t load by default – to open it, select ScenesGameScene.

Let’s get started!

Making Sure Everybody Plays Together Nicely

Before you get too deep into code, take a quick look at the diagram below, which shows the functionality and responsibility of each component you’ll be adding to the game, as well as the relationships between the components:

At the center is the GameController. This is an abstract GameObject meaning that it is not associated to any physical element on the stage, but rather used to manage the scene. In this instance theGameController is responsible for coordinating the various states of the game activities providing access to the input from the user.

The next Component is the ScoreBoard. This encapsulates methods to update the points and time 3D Text GameObjects in the scene.

Next is the Player who is responsible for responding to user input, and managing the various properties of the ball, including the ball’s position.

Finally, what would your game be without the Ball? This object is responsible for triggering specific events that indicate when the Ball has gone through the hoop, and when the Ball has landed on the ground, signifying that the player’s turn is over.

Scripting, Scripting, Scripting

Unity provides a choice of several different scripting languages; these include Boo (no, I’m not trying to scare you, it’s actually a language!), Javascript (a.k.a. UnityScript), and C#. In general, if you’re coming from a front-end web development background, then UnityScript is probably the best choice.

However, if you are more comfortable with C&#;&#;, Java, Objective-C, or C#, then C# is a better choice for your scripting tasks. Since most of the readers of this site have an Objective-C background, in this tutorial you’ll be writing your scripts in C#.

Each script will be a Component unto itself, which will be attached to a GameObject. The base class you will be extending is the MonoBehaviour and includes a whole set of pre-defined properties, methods, and hooks.

Note: Are you wondering what “hooks” are? Hooks are callbacks or messages that are propagated to all Components for certain events, one example that we’ll be using is the OnTriggerEnter method which is called when two Colliders intersect each other (where on has the Is Trigger flag set to true but more on this later).

Let’s try this out! In the Project panel, select the Scripts folder, click Create, and click C# Script:

In the Inspector, you will see that it has created a default script for you that looks similar to the following:

The Start() and Update() methods above are known as hook methods; they are called by the engine during each frame update, also known as a “tick”. One of the core behaviors of a game engine is the continuous update and render cycle. An object is moved, then the scene is re-rendered. The object is moved again, and the scene is rendered once more. Lather, rinse, repeat! :]

When a Component is first instantiated, the Awake() method (which isn’t listed here, but you can override it) will be called. Once the Awake() method has been called on all active Components, then the Start() method will be called. The Update() method is called next, and will be called during each frame update or “tick”.

Note: MonoBehaviour has another update method called FixedUpdate(). This method is called by the physics engine and should only be used to update Rigidbody or other physics-based properties. It’s called FixedUpdate() as it’s guaranteed to be called at fixed intervals, unlike the Update() method which is called every “tick”, where the amount of time between ticks can be variable.

ScoreBoard

Start off with the ScoreBoard script, which is fairly straightforward. You’ve already created a the script, so just rename it to Scoreboard, then double-click it to open it.

Aha! Bet you didn’t know Unity included MonoDevelop!

Note: MonoDevelop is a full IDE for C# development and discussing all of the features and functionality is out of scope for this tutorial. However, if you limit what you do to editing and saving files, you’ll do just fine. If you want to use more advanced features, you can find out more about MonoDevelop atMonoDevelop.

Insert the code below into the new script:

The script above introduces the concept of publicly accessible properties. In this case, those properties are the Points and Time 3D Text objects that are children of your ScoreBoard object.

Making these properties public means they will become visible in the Inspector panel, which will allow you to assign them at design time via the editor. Once the properties have been assigned, you’ll be able to modify their text properties via the setter methods SetTime() and SetPoints().

Once you’ve created the script above, switch back to Unity and attach it to the ScoreBoard object. To do this, simply drag the script object and drop it on top of the Scoreboard object.

Next, drag and drop each of the 3D Text child objects from Part 1 of this tutorial onto the appropriate property in the right hand column as shown below:

This associates the 3DText child objects with the script property. Pretty simple, eh?

Time to test

Before continuing, lets make sure everything is functioning as expected. To do this we’ll create a new script that will update the time and score of your scoreboard. Create a new script called ScoreboardTest and copy the following code into the script:

Next click GameObjectCreate Empty, rename the object to ScoreboardTest, and attach your ScoreBoardTest script to it (again by dragging it on top). Then link up the scene’s scoreboard GameObject with the ScoreBoardTest scoreboard variable and press play.

wt it works – you should see the text on the scoreboard change as in the above screenshot! If not, trace back your steps to see what might have gone wrong.

Controlling Collisions

Now it’s time to take a look at how Unity handles object collisions.

Recall that the Ball object is responsible for notifying the GameController when it goes through the net and/or hits the ground. The Ball object is attached to a Sphere Collider and Rigidbody , which allows you to detect and react to collisions. In your script, you can listen for those collisions and notify the Game Controller appropriately.

Like you did before, create a new script and name it Ball. Then edit it in MonoDevelop as follows:

Note: Because of dependences between objects and the GameController, several required methods need to be stubbed out with an empty method signature that will be implemented later. In this case, the OnBallCollision() instance method and SharedInstance() class method have been stubbed out.

Here’s an overview of the new concepts introduced in this script, code block by code block:

Unity provides class attributes that allow you to add design time logic to your classes. In this case you’re telling Unity that this script is dependent on a SphereCollider and RigidBody Components being attached to this script.

This is a good habit to get into, especially when your projects start growing in size as it provides a way of automatically adding dependent Components to your script thus avoiding unnecessary bugs.

The GetComponent() method is inherited by the MonoBehaviour class and provides a way of searching the local GameObject for a specific type of Component. If none exists then null is returned otherwise the Component is returned. Because it requires traversing through the GameObject’s components is always a good idea to cache them locally when frequent access is required (such as when you need them in either the Update() or FixedUpdate() methods).

This object needs a reference to the Game Controller, so it can notify it of events such as collisions. The Game Controller will be a singleton, and you’ll be able to access it via the SharedInstance static property.

If you haven’t worked with C# before, the delegate and event may look a little foreign. Essentially, they provide a method of communication between Components. In this case, the external Component would register interest in the OnNet event, and in doing so, will be updated when an OnNet event is raised by the Ball script (implementation of the Observer pattern). This is a very similar concept to the delegate pattern used in iOS programming.

The main task of the Ball is to notify GameController each time the Ball goes through the net and/or hits the ground. Since the Ball has a Rigidbody attached, when it collides with the BoxCollider Component of the Ground object, the Physics engine will send notification via the OnCollisionEnter() method.

The Collision parameter passed in gives details about the collision, including which object the Ball collided with. In this case, just pass the details onto the GameController to figure out what to do with it. :]

Note: along with OnCollisionEnter(), there are also OnCollisionStay() and OnCollisionExit() methods, which are called each frame as an object is colliding with something else, and when it stops colliding, respectively. For more details, check out the official Unity documentation above code detects when the ball passes through the net. Remember how in the last tutorial you set up a special box collider right below the net and saved it as a trigger?

Well, since this is not technically a “collision”, there is a separate callback named OnTriggerEnter() (as well as OnTriggerStay() and OnTriggerExit()) that gets called when a collision with a trigger occurs.

Here, you check which object is involved with the collision event. If it happens to be the hoop’s trigger, then you let the GameController know about it via the OnNet method discussed above.

And that’s it! Note you can’t attach the script to the basketball object in Unity yet, because this script depends on the GameController object, which you haven’t created yet.

That takes care of the ball — but now the Player needs to play a part in this game! :] But before we do lets make sure everything is working as expected.

Time to test

First things first, you need to create a stub for the GameController script that the Ball script depends on so you can test everything out. So create a new script called GameController and replace the contents with the following:

This is known as a Singleton. A Singleton is a design pattern which ensures that only a single instance of this object exists in your system, much like a global variable or Highlander — there can be only one. :]

The is done so that the GameController is easily accessible by other classes. As a well-connected object, it provides a central way for other objects to communicate with each other and check what state the system is in.

Note: if you’re curious about using the Singleton pattern in other iOS projects, a discussion of implementing singletons in iOS 4.1 and above can be found on Stack Overflow.

To implement the Singleton, provide a static method that returns the shared instance. If the shared instance has not been set, then look for it using the GameObjects static method FindObjectOfType() which will return the first active object of the type you’ve requested in the scene.

Note: When implementing a Singleton you would normally set its constructor to private such that the Singleton accessor controlled the instantiation. Since we are inheriting from a Unity MonoBehaviour class we are unable to make the constructor private. So it’s an implied Singleton and must be enforced explicitly by the programmer.

Next, you’ll add a test script to test out the ball’s collision behavior, similar to how you tested the scoreboard earlier.

To do this, ceate a new script called BallTest and copy the following code:

Then hook everything up by doing the following:

Drag the Ball script on top of the basketball object.Create a new empty GameObject called GameController and drag the GameController script on it.Create a new empty GameObject and rename it to BallTest and drag the BallTest script on it.Click the BallTest object, and drag the basketball onto the Ball variable.

Finally, position the basketball GameObject over the net as shown below:

Then click play, and you should see the output “NOTHING BUT NET!!!” into your console (WindowConsole), along with a few other debug messages!

Here you have tested that the ball script correctly detects normal collisions or trigger collisions, and can forward those events on to an OnNet handler or the GameController, respectively.

Now you know that collisions are working properly, you can proceed to setting up the player!

Player Framework

For now, you’ll just implement the Player code as a stub. You’ll return to this later on, once theGameController has been completed.

Create a new script named Player and edit it in MonoDevelop as follows:

The GameController is dependent on knowing when an animation has finished and is able to set and get the current state of the Player. To handle animation events, there is an OnPlayerAnimationFinished() event.

There is also an enumerator for each possible state of the Player: Idle, BouncingBall, PreparingToThrow, Throwing, Score, Miss, and Walking, and there is a property to get the current state.

Note that properties in C# are created with the following format:

This provides a nice, clean way of managing Getters and Setters.

Before you forget, drag the Player script on top of the player object in the Hierarchy panel to attach it.

That’s it for the Player object is now – this stub implementation is so simple that we could nickname the basketball player “Stubby” :] Let’s move onto implementing more of the GameController!

GameController

The GameController is responsible for coordinating the activities of the game, as well as accepting user input.

What does “coordinating the activities” mean? Games normally function as a state machine. The current state of the game will determine what section of code runs, how user input is interrupted, and what happens on-screen and behind the scenes.

In a complex game, you’d normally encapsulate each state in its own entity, but given the simplicity of this game, it will be sufficient to use an enumeration and switch statement to handle the various game states.

You already created a starter script for the GameController – let’s start building it up.

Variables

You’ll start by declaring the variables you need. Since the GameController’s main job is to act as a co-ordinator between all game entities, you need reference to the majority of them all along with variables used to manage the game statistics (e.g. current score, time remaining, etc).

Add the following code to declare the variables (comments embedded within the code snippet):

Exposing gameSessionTime (how long the player has to score) and throwRadius (how far your basketball player will potentially move either side of his current/starting position) as public means you can tweak them easily during play testing.

Game States

You’ve added some states for your Player object; now add some states for the game:

Here’s an explanation of the various game states:

Menu – display your main menu itemsPause – present a similar menu to the main menuPlay – when the user is actually playing the gameGame Over – when play is finished

States acts as gates deterring what path to take (in terms of code branching) based on the current state. The state logic (in this project) is used through-out the methods of this class but exposes itself as a public property which is used to manage the switching of the states.

Next add a getter and setter for the game state, as follows:

Encapsulating the state within a property allows you to easily intercept changes to states and perform necessary logic as required (as you can see above).

Support methods and properties

Next you’ll add some supporting methods and properties.

First add the StartNewGame method as follows:

This method is responsible for resetting the game statistics (variables declared above) and preparing the game entities on your scene for a new game.

Next add the ResumeGame method:

This is similar to the StartNewGame but performs additional checks. If the game is considered over (time has ran out) then StartNewGame, will be called. Otherwise you switch the GameController state back to Play to resume game play.

Next, define a new property for GamePoints:

This will be responsible for keeping your scoreboard update-to-date with the latest current score.

Finally, add a TimeRemaining property:

This is responsible for keeping the scoreboard update-to-date with the current amount of time remaining.

Done with support methods and properties – time for the big guy, Update!

Keeping everything up to date

Now you’ll shift your focus to what makes the GameController tick, the Update method and accompanying methods. Add the following code to GameController:

The Update method delegates the task to a specific method based on what the current state is. As you can see the bulk of the code in this code snippet belongs to the UpdateStatePlay method, let’s go through it bit by bit.

The first part is responsible for updating the elapsed game time (or time remaining). You track the last time you updated the TimeRemaining property using the variable _timeUpdateElapsedTime, throttling updates to every second as updating your scoreboard any quicker (which is done via the TimeReamining property) is not necessary (we are not showing milliseconds) and could potentially affect performance.

The next section is responsible for checking for when the basketball player has finished a throw and checking if the game is finished. The basketball player is considered having finished a throw when he has been in either the Miss or Score state for 3 or more seconds. The reason for the delay is that you want an animation to finish before moving onto the next throw.

You then check if there is any time remaining. If not, you update the state to GameOver, otherwise you ask the basketball player to move into a new position for another shot.

Time to test

You already created a GameController object in the Hierarchy earlier and attached the GameController script to it, so you’re all set there.

Select the GameController object in the Hierarchy panel, and you’ll notice the GameController now has public properties for the player, scoreboard, and basketball. Set those to the appropriate objects in the Inspector by dragging and dropping.

Intermediate Unity 3D for iOS: Part 2/3

Now when you click on the play button you will see the time update as the GameController reduces the time every second!

Handling User Input

In many cases you’ll find yourself developing on your desktop machine, and porting over to an actual device with greater frequency as the project nears completion. Therefore you need to handle input in both contexts: from the device touchscreen, as well as the keyboard and mouse.

To do this, first add a helper method into GameController to detect whether the app is running on a mobile device or not:

Luckily your design requires minimal interaction; all that is required is determining if a finger is down or not, the following snippet does just that.

To determine if the user is touching the screen or not you use the TocuhCount and TouchDownCount properties that branch depending on what platform the app is running on.

If it’s running on the mobile platform then you query (and return) the Input class for the number of touches that have been detected, otherwise you assume we are running on your desktop and query the Input class if the MouseButton is down (returning 1) or not (returning 0).

The only difference between TouchCount and TouchDownCount is that TouchCount counts the number of fingers present on the screen regardless of their phase while TouchDownCount only counts those fingers whose phase is set to Began.

Node:The Touch class has an enumeration called TouchPhase, a touch phase is essentially the current state of the touch e.g. when first detected (when the finger first touches the screen) the touch will be assigned a Began phase, once moving the touch will be assigned the Moved phase, and when finally lifted off the touch will be assigned the Ended phase.

For a full overview of Unity’s Input class, please refer to the official Unity site ( Handling: Dealing With Messages

Recall that the Ball object sends messages to GameController in the case of two events: when the ball goes through the net, and when it hits the ground.

Replace the OnBallCollisionEnter method to handle the case when the ball collides with the ground:

OnBallCollisionEnter() checks to see if the player is holding the ball. If not, then it’s assumed the ball has been thrown. Therefore, if the ball collides with the ground or the sides of the court, then the turn is over. If the ball hits the ground or the court and the player missed the hoop, then set the player state to Miss.

OnBallCollisionEnter() is called explicitly by the Ball Component and its HandleBasketBallOnNet event. How do you associate OnBallCollisionEnter() with the event from HandleBasketBallOnNet? You do this in the Start() method by registering ‘interest’ in the OnNet event.

You should add this in a new method called Start(), which is a good place to put initialization code like this:

This is how you assign a callback to the event delegates. When the Ball raises the Net event, the HandleBasketBallOnNet method will be called.

Then add the implementation for HandleBasketBallOnNet as follows:

Handling Messages from the Player Component

The other Component that communicates with the GameController is the Player. At this point the Player is only stubbed out, but here you’ll implement the handling of messages and events in the GameController. The Player raises an event when an animation is finished playing, which in turn triggers an update in the GameController’s game state.

Add the following code to the end of the Start() method to register for the event:

Along with its accompanying method:

This code updates the state of the Player to BouncingBall once he has finished walking.

The next portion of this tutorial will tie all of these events together and allow you to finally shoot a few hoops! :]

The Player: “Stubby” No More!

Here’s a quick review of what the Player is responsible for and what functionality will be required:

During idle time, the Player should bounce the ball.When in the Play game state, the Player should react to user input; in this case when the user holds their finger on the screen, the Player will ‘wind’ up for the throw.The Player should affect the position of the Ball and influence its behavior.The Player should move around the court after each turn.The Player should animate based on the current state, e.g. show a winning animation when the ball goes through the hoop and a disappointed animation when the ball misses.The Player should notify the GameController when each of the above animations completes.

Head back and open up the Player script, and lets slowly make your way through the code.

Character animation

Unity provides a rich set of classes that handle the importing and use of animations from 3D packages. When you imported the player that was created in Blender, it came packaged with a set of animations. If you select the Animation Component of the Player object in the editor you’ll see the following:

The Animation Component has slots, each containing a separate Animation Clip. You can play any of these animations in script by asking the Animation Component to play a specific Animation Clip.

Note: To find out more about the Animation Component, check out the official Unity documentation here: the Player script, add some variables to manage the current animation and AnimationClips that will reference the various animations:

Referencing the animations via a variable provides the flexibility to easily update the animations without having to rely on a specific animation file or index/name.

Of course, for this to work you have to connect the appropriate animation to each public property on the script component, so go ahead and do that now:

The next step is to set up each of the animations. You do this by calling a dedicated method from the Player Start method (along with getting reference to the attached animation Component. Add the following code to do this:

The Animation Component acts as a controller and repository for your animations. Each animation is wrapped in a class called AnimationState. You can access each one by index position or key, where key is the name of the animation. This is shown visually in the editor screenshot above.

Take a look at two properties in each animation: wrapMode and speed. Speed determines the playback speed for the specific animation, whereas wrapMode determines how the animation is ‘wrapped’; in other words, what the animation does once it has come to the end. Here the animations are either being played just once, or are looping.

The only thing left to do is to play the animations! :] Add the following code to the Player class:

The above code shows all the methods associated with handling animation. The main method is SetCurrentAnimation().

Here the current animation time is reset to 0 (i.e. back to the start) and then the Animation Component is requested to crossFade the specified animation. Cross fading permits fading in an animation over the currently playing animation over the specified time. This means the current animation will be slowly ‘blended’ out to give a smooth transition between the current and new animation.

After requesting the animation to play via crossFade, check if the animation is a loop. If not, then request a delayed call to OnAnimationFinished() using the Invoke method. The call will be delayed by the time of the animation.

Finally, OnAnimationFinished() is responsible for raising the associated event, and thus notifying the GameController that an animation has finished so that it is aware of the current state and actions of the Player GameObject.

Time to test

Lets make sure your animations are all set up and running correctly. To do this, add the following line to the end of your Player’s start method:

Then disable the GameController script by unchecking the GameObjects component (as shown below):

And click on the play button; if all is well then you will see the basketball player play the “prepare to throw” animation! :]

Note: Before continuing remember to enable the GameController again and remove the test code snippet.

Managing state

Time to flesh out your State property (that you created previously); but before you do that lets stub out a method that you need.

This method will be explained when we talk through how the basketball player bounces the ball. For now, replace your previous State property with the follow code snippet:

Most of the code is related to setting up the appropriate animation based on the currently set state, using your SetCurrentAnimation method we created above. So lets concentrate on the less trivial code.

One of the first statements is:

This statement asks Unity to cancel any invoke that maybe queued up called OnAnimationFinished, which should look pretty familiar to you because we created this invoke when playing a non-looping animation.

The next interesting piece of code is for the state PlayerStateEnum.Walking; in this block you are determining the animation based on the target (shot) position compared to your current position to determine whether the basketball player is walking backwards or forwards.

Time to test

Similar to above, let’s perform a quick test to check that your states and animations are working correctly together. Add the following code to the Start method of your Player class:

As you did before, disable the GameController script by unchecking the GameObjects component so that it does not interfere with your test.

And click on the play button; if all is well then you will see your basketball player plays the “score” animation (the animation that will run when the user successfully gets a ball in the hoop).

Note:Before continuing remember to enable the GameController again and remove the test code snippet.

Bouncing the Ball

One responsibility of the basketball player is to bounce the ball while waiting for user input. In this section we will cover the code and setup required to make this happen.

Start by declaring the following variables at the top of your Player class:

The variable _handTransform will hold reference to the Transform Component of the bone that will be touching the ball and the bounceForce is used to determine how much force is applied to the ball when bouncing (the basketball variable should be pretty obvious).

One of the first problems to solve is how to position the ball in the player’s hand when the Player’s state changes to BouncingBall. Implement the AttachAndHoldBall method you stubbed out earlier to do that:

One of the publicly exposed variables (named basketball) holds a reference to the basketball object. This function needs a reference to the ball’s transform, collider, and rigid body, so the first part of this method gets those.

With respect to the Rigidbody, any current velocity is removed and the ball (to ensure it has stopped completely and won’t ‘bounce’ out of your hand) is then positioned to the player’s hand using the Ball’s Collider to offset based on the diameter of the ball.

You may be wondering where _handTransform comes from. Recall that you added a Box Collider to one of the Player’s hand when setting up the scene in Part 1.

To make use of this, add the following code to the end of Awake():

This grabs a reference to the appropriate component and attaches to the _transform variable. An alternative would have been to expose it as a public property and assign it via the editor like you’ve done so far, but this is a nice opportunity to demonstrate you how you can traverse a GameObject to obtain reference to one of its children.

Once the Player is holding the ball, he needs to start bouncing it! :]

You do this by holding the ball and playing the BounceUp animation. If, during Update(), the game is in the BouncingBall state, the Player is holding the ball, and the Bounce Down animation has finished playing, then push the ball down via the AddRelativeForce method of the Ball’s Rigidbody using your bounceForce variable. This will force the ball to the ground and make it bounce back up (hence why the force is so high).

Replace the Update method with the following code:

First you check if the _holdingBall has been set. If it is, you call the AttachAndHoldBall you just implemented above to position the ball in your basketball player’s hand.

The _holdingBall method is set to true within the AttachAndHoldBall method (which in turn is called when the state is changed to BouncingBall) and set to false during bouncing and once thrown the ball.

Next add the following to the end of Update():

The above block (embedded into your Update method) first checks if we’re currently holding the ball, if so asks the GameController if a touch is present. If so, it swaps to the PrepareToThrow state, otherwise checks what animation you’re current playing and if it has finished.

If the down animation has finished then you push the ball to the ground, and if the up animation has finished you start the down animation.

As the ball is bouncing back up, it will collide with the hand’s Box Collider trigger. Implement a method that will be called when this occurs:

This makes it re-start the bouncing sequence all over again when the ball bounces back up to the hand!

Note that trigger events don’t propagate up to the parent, whereas Collision events do. Therefore this OnTriggerEnter method of the Player Component that you just wrote will not be automatically called when the collision occurs.

However, you can write a helper script written to facilitate this. Create a new script named PlayerBallHandand enter the following code:

This Component is responsible for notifying the Player Component when the ball collides with the hand.

Next switch back to Unity and to attach this script to the Hand_R of the player object. Remember that you created a collider on this object in Part 1 of this tutorial.

Also, select the Player object and attach the basketball to the public variable for it.

And finally, select the BallPhyMat and set the bounciness to 1 so the basketball bounces up with enough force.

Time to test

You’ve written a bit of code so now would be a good time to test that everything is working as expected. As you did before, amend the Start method with the following state to test the bouncing of the ball:

Also as you did before, disable the GameController script by unchecking the GameObjects component so that it does not interfere with your test.

And click on the play button; if all is well then you will see the ball bounce up and down as shown below!

Note: Before continuing remember to enable the GameController again and remove the test code snippet.

Throwing the Ball

Start off by declaring the following variables at the top of your Player class:

The maxThrowForce is (as the name suggests) the maximum force you will apply to the ball when throwing it, the amount is relative to how long the user held their finger down (i.e. the longer they held their finger down the larger the proportion of this force will be used). The next variable, throwDirection, determine the angle that you will launch the ball when thrown.

Next add some code to the end of your Update() method to throw the ball at the appropriate time:

Earlier you added some code to your update method to set the Player’s state to “PreparingToThrow” when the ball is bouncing and the player taps the screen.

Now, you’ve added a check to see if you’re in this state and the player releases their finger. You calculate a force to throw the ball based on the time remaining of the associated animation.

normalizedTime is a property of an Animation State which indicates how far the animation has played; 0.0 means the animation is at the start, while 1.0 means the animation has played all the way through.

Next, add the logic to handle the Throwing state:

While in the Throwing state you poll to determine when the throw animation has finished and once done so you turn on your collider on to ensure that the ball doesn’t roll through your character.

After the ball is thrown, the Player waits for instructions from the GameController. Based on the result from GameController, a specified animation will play. For instance, if the ball goes through the hoop, a winning animation is played; otherwise, a disappointed animation is played.

Once the play has ended (either missing the hoop and landing on the ground or going through the hoop and landing on the ground), the GameController randomly selects a new shot position and notifies the player to move into position.

Positions Please

Add the following variable to the top of your Player class:

walkSpeed determines how fast your character will move into his new _shotPosition (set by the GameController).

Also, if you look inside the Player class you’ll see a parameter called shotPosition that you added earlier. This will determine where the Player is standing to perform his shot, and it is updated by the GameController after each shot.

You need to initially set the shot position, so add the following line to the bottom of Awake():

Next, override the ShotPosition getter/setter as follows:

As mentioned above, the ShotPosition is set by the GameController. This makes it so when the ShotPosition is changed, the Player class checks to see if it represents moving to a new position, and if so changes the state of your Player class to Walking (otherwise, reverts to bouncing ball).

Then for each Update(), you move the player closer, and once close enough, start bouncing the ball again (which means the user can now attempt another shot).

To do this, add the following code to the end of Update():

Make note of the way that object position and movement is calculated in Unity. If you’ve done game development before, you’re likely aware that in order to keep your game running consistently across all devices, you must update positions and movement relative to the elapsed time. You can access this via the Time static property deltaTime.

deltaTime is the time elapsed since the last update call. Why would this be used to calculate movement on-screen? If you have ever played an old game on a modern computer, you might have noticed that the characters in the game moved around so quickly that you couldn’t control them.

This is because the updates to the character positions were not relative to the elapsed time, but rather a constant. For instance, the distance to move an object pixels is dependent upon many things, including processor speed. However, moving pixels in 0.5 seconds will result in a constant, fluid movement on any platform or processor.

Note: You may be wondering what “lerp” is. lerp is a mathematical function that Linearly intERPolates one value to another. For instance, if you have a start value of 0 and an end value of , then by linearly interpolating by 0.5 you would end up with a value of 5. Get comfortable with using lerp; you’ll use it frequently!

And that’s it – you’re finally done, time to test this out! :]

Testing it out!

It’s finally time to test this out! Click the play button to start your game. There are a few things you might have to tweak based on how you have things set up:

You can shoot the ball by clicking and holding in the play area, then releasing. If it goes the wrong way, you can change the Player’s ThrowDirection variable – I had to change mine to X=1, Y=0., Z=0.Double check that all the public connections set up in the scripts attached to your Player, Scoreboard, and Game Controller objects are set up correctly.

If you’re still stuck, you can try using the debugger to see what’s wrong! To do this, right click the Inspector tab and choose Debug. Then you can set a breakpoint in MonoDevelop by clicking in the gutter.

Finally, in MonoDevelop go to RunAttach to Process and choose your Unity editor. Then when you play the app, it will pause there when the breakpoint is hit, and you can debug as usual!

If you got it working this far – huge congratulations! At this point, you have a fully functional 3D game to play around with!

Take some time looking over the code – the goal of this tutorial is to provide you with the background of scripting and event handling in Unity.

Where To Go From Here?

Here is a sample project where you have left it off in the tutorial so far. To open it in Unity, go to FileOpen Project, click Open Other, and browse to the folder. Note that the scene won’t load by default – to open it, select ScenesGameScene.

Stay tuned for the third part of this tutorial, you’ll see how to present a simple user interface for the main menu!

In the meantime, if you have any questions or comments on the material presented so far or Unity in general, please join the forum discussion below!

This is a tutorial by Joshua Newnham, the founder of We Make Play, an independent studio crafting creative digital play for emerging platforms.

From:

android优化 清除无效代码 UCDetector android下优化清除无效未被使用的代码UCDetector官方下载地址:

Android基础知识_Context的理解及使用 一、Context的作用1.API类的继承关系2.API类的概述一个关于应用程序环境的全局信息接口。这是一个抽象类,它的实现是由Android系统提供的。它允许访问

Universal ImageLoader 在ListView刷新时会闪动 com.nostra.universalimageloader.core.ImageLoader用ImageLoader加载图片的时候,会调用publicvoiddisplayImage(Stringuri,ImageViewimageView,DisplayImageOptionsoptions)用到一个options参

标签: Intermediate Unity 3D for iOS: Part 2/3

本文链接地址:https://www.jiuchutong.com/biancheng/376559.html 转载请保留说明!

上一篇:OKHttp源码解析-ConnectionPool对Connection重用机制&Http/Https/SPDY协议选择

下一篇:android优化 清除无效代码 UCDetector(安卓优化清理大师怎么样)

  • 一般纳税人开具的普票可以抵扣吗
  • 增值税附加税怎么填
  • 贴现怎么计算公式
  • 增值税征税范围中销售应税服务包括什么服务
  • 企业所得税低于多少不用交
  • 支付给客户的货款叫什么
  • 研发物资
  • 员工宿舍需要缴纳房产税么
  • 一般纳税人出租不动产增值税税率
  • 员工探亲路费报销交个税吗
  • 利润表的以前年度损益调整影响利润总额吗
  • 关闭系统保留空间
  • php文件类型码
  • shnlog.exe - shnlog是什么进程 有什么用
  • 年度企业所得税汇算清缴会计分录怎么做
  • 期间费用的含义
  • 二手车交易如何开票
  • 如果企业亏损要交企业所得税吗
  • 超过认证期的发票怎么办
  • 一头公牛和一头母牛,答五个字
  • 机器学习中的数学原理——对数似然函数
  • 工地扬尘检测仪防尘缸怎么安装
  • 红字发票进项转出当期
  • php删除数据
  • java 桥接模式
  • 以前年度漏记收入
  • python.mat
  • 如何用织梦在本地搭建网站
  • 循环语句例题及解析
  • 收到对方假发票可以索赔吗
  • 会计自制原始凭证有哪些
  • 现金科目的指定科目是什么
  • 工程类企业存货
  • 税金及附加怎么做分录
  • 资产负债表中利息收入填在哪
  • 年均复合增长率该怎么算?
  • 建设工程的材料质量检测由谁负责
  • sqlserver阻止保存要求重新
  • sqlserver2008数据库可疑
  • 口罩属于什么经济分类
  • 企业没收入也要交税吗
  • 什么时候贷主营业务成本
  • 还未摊销的房租怎么入账
  • 其他应收款和应收账款一样吗
  • 应付账款借方余额负数表示什么
  • 上月多出来的薪资怎么算
  • 总资产法怎么计算公式
  • 劳务派遣公司工资发放方式
  • 建筑工程社会实践报告
  • 公司盈利的钱怎么拿出来
  • 收到预付卡的发票是否可以报销呢?
  • 事业单位实收资本如何做账
  • 500万以下设备一次性扣除
  • 商业会计做账流程视频
  • 小规模纳税人开专票税率是多少?
  • 税金及附加科目余额在借方还是贷方
  • 股东增资有哪几种方法
  • 换工作时社保公积金怎么办
  • 哪些会计凭证可以抵扣进项税
  • mysql存储过程是什么意思
  • mysql 优化口诀
  • mysql新手视频教学
  • Windows Server 2008作为打印服务器排错
  • centos锁定屏幕命令
  • vc_mbcsmfc.exe是什么
  • 进程rundll32停止工作
  • ubuntu系统如何设置永不休眠
  • ttf字体怎么转itz
  • win7系统如何屏幕放满屏幕
  • node.js中module.exports与exports用法上的区别
  • dos命令可以做什么
  • js判断元素是否显示
  • js数组如何定义
  • 安卓状态栏宽度
  • python设计gui
  • 安卓音频分析软件
  • 个人所得税完税证明在哪里查询
  • 河北市国家税务局官网
  • 消费税申报详细流程图
  • 江苏省国税客服电话
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设