UNITY 3D –游戏编程–第7部分(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/unity-d-game-programming-part-6-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 20 分钟阅读 - 9879 个词 阅读量 0UNITY 3D –游戏编程–第7部分(译文)
原文地址:https://www.codeproject.com/Articles/884656/UNITY-D-Game-Programming-Part-6
原文作者:Vahe Karamian
译文由本站 robot-v1.0 翻译
前言
The seventh article in a series to discuss Unity 3D and how to get started with your own 3D projects.
本系列的第七篇文章讨论Unity 3D以及如何开始自己的3D项目.
介绍(Introduction)
在本系列的第七部分中,我们将从(In part seven of the series, we will be expanding on our game idea from) 第5部分(Part 5) 和(and) 第6部分(Part 6.) 如果您尚未这样做,请花一点时间阅读:(If you have not already done so, please take a moment and read:)
-
Unity 3D –游戏编程–第7部分(Unity 3D – Game Programming – Part 7)
Unity 3D网络文章:(Unity 3D Networking Article(s):)
-
Unity 3D-网络游戏编程(Unity 3D - Network Game Programming) Unity 3D Leap Motion和Oculus Rift文章:(Unity 3D Leap Motion and Oculus Rift Article(s):)
-
Unity 3D-Leap Motion集成(Unity 3D - Leap Motion Integration) 在本系列的第一部分中,我们从Unity 3D环境的基础知识入手.感受一下IDE以及将在整个项目中使用的不同部分.我们还介绍了如何使用设计器中的工具将不同的变换应用于选定的游戏对象:定位,旋转和缩放.最后,我们研究了如何创建第一个脚本,并使用该脚本在多维数据集的Y轴上应用了旋转变换.(In the first part of the series we started by the very basics of the Unity 3D environment. Getting a feel of the IDE and the different sections which you will be working with throughout your project. We also covered how to use the tools in the designer to apply different transformation to a selected Game Object: positioning, rotation and scaling. We finally looked at how to create our first script and using the script apply a rotation transform on the Y-Axis of our cube.) 在本系列的第二部分中,我们研究了通过编码对给定对象进行的更多转换.我们还研究了如何创建对于场景中的对象渲染至关重要的光源.(In the second part of the series, we looked at more of the transformation of a given object through coding. We also looked at how to create light sources that are crucial for the rendering of your objects in the scene.) 在本系列的第三部分中,我们研究了如何通过键盘处理用户输入,并根据键码采取了特定的操作.(In the third part of the series we looked at how to process user input through the keyboard and based on the key code take particular actions.) 在本系列的第四部分中,我们着眼于创建一个简单的用户界面.我们开发的用户界面为我们提供了一种向用户反馈的方式,并且为用户提供了输入我们的游戏或模拟游戏的另一种方法.(In the fourth part of the series, we looked at creating a simple user interface. The user interface that we developed provided us a means to feedback to the user, and also another method for the user to input to our game or simulation.) 在第五部分,我们开始了一个简单游戏的想法.我们还研究了如何将3D模型导入游戏引擎.(In the fifth part, we started the idea of a simple game. We also looked at how to import 3D models into the game engine.) 在第六部分中,我们扩展了我们的游戏构想,使其更加有趣和完整.我们介绍了有关游戏和游戏设计的几个概念,并为我们的游戏创建了一个简单的用户界面.(In the sixth part, we expanded on our game idea and making it more interesting and more complete. We introduced several concepts regarding game play and game design as well as created a simple user interface for our game.) 在第七部分中,我们将回答在此提出的一些问题(In part seven, we will be answering some of the questions that got raised in) 第6部分(Part 6) .(.)
游戏编程简介:使用C#和Unity 3D(Introduction to Game Programing: Using C# and Unity 3D*) (Paperback)*)(平装)( 要么(or*) (eBook)*)(电子书)( 是为帮助对计算机科学和游戏编程领域感兴趣的个人而设计和开发的.它旨在说明计算机编程的概念和基础.它使用简单游戏的设计和开发来说明和应用这些概念.(is designed and developed to help individuals that are interested in the field of computer science and game programming. It is intended to illustrate the concepts and fundamentals of computer programming. It uses the design and development of simple games to illustrate and apply the concepts.) [ ](http://www.lulu.com/commerce/index.php?fBuyContent=18159441) 书号:9780997148404(ISBN: 9780997148404) 版本:第一版(Edition: First Edition) 发行人:Noorcon Inc.(Publisher: Noorcon Inc.) 英语语言(Language: English) 274页(Pages: 274) 装订:装订完美的平装本(彩色)(Binding: Perfect-bound Paperback (Full Color)) 尺寸(英寸):6宽x 9高(Dimensions (inches): 6 wide x 9 tall) -
|
||电子书(ePUB)(eBook (ePUB))
书号(ISBN):9780997148428(ISBN: 9780997148428)
版本:第一版(Edition: First Edition)
发行人:Noorcon Inc.(Publisher: Noorcon Inc.)
英语语言(Language: English)
大小:9.98 MB(Size: 9.98 MB) |
---|
Windows Phone 8.x演示(Windows Phone 8.x Demo):(:)
我提供了一个免费的电话应用程序,您可以在Windows Phone上下载和预览演示.要下载移动应用程序,请点击以下链接:(I have provided a free phone application that you can download and preview the demos on your Windows Phone. To download the mobile application, follow the link:) CodeProjectArticleSample(CodeProjectArticleSample)
代码项目文章示例移动应用(Code Project Articles Sample Mobile App)
文章代码和视觉效果的实时预览:(Live Preview of Article Code and Visuals:)
链接到实时预览:(Link to live preview:) http://www.noorcon.com/CodeProject/CodeProjectArticlePreview.html(http://www.noorcon.com/CodeProject/CodeProjectArticlePreview.html)
背景(Background)
**注意:(NOTE:)**对于这个粒子,我将使用SketchUp创建一些简单的构建基块,并将其导入到Unity中!我不是3D建模者或设计师,因此请耐心等待,请原谅!(For this particle, I will be using SketchUp to create some simple building blocks, which I will use to import into Unity! I am not a 3D Modeler or Designer, so please be patient and excuse the mess!) 假定本文的读者通常熟悉编程概念.还假定读者具有C#语言的理解和经验.还建议本文的读者也熟悉面向对象的编程和设计概念.我们将根据需要在本文中简要介绍它们,但是由于它们完全是单独的主题,因此我们将不对其进行详细介绍.我们还假设您有学习3D编程的热情,并且具有3D图形和矢量数学的基本理论概念.(It is assumed that the reader of this article is familiar with programming concepts in general. It is also assumed that the reader has an understanding and experience of the C# language. It is also recommended that the reader of the article is familiar with Object-Oriented Programming and Design Concepts as well. We will be covering them briefly throughout the article as needed, but we will not get into the details as they are separate topics altogether. We also assume that you have a passion to learn 3D programming and have the basic theoretical concepts for 3D Graphics and Vector Math.) 最后,本文使用Unity 3D版本4.6.1,这是截至初始发布日期的最新公共发行版.该系列中讨论的大多数主题都将与旧版本的游戏引擎兼容,也许还与应该在今年某个时候发布的新版本兼容.但是,有一个主题与当前版本的游戏引擎相比在当前4.6.1版本中有显着差异,那就是UI(用户界面)管道.这是由于引擎中的新UI架构远远优于我们在此版本之前所拥有的.首先,我对新的UI架构感到非常满意.(Lastly, the article uses Unity 3D version 4.6.1 which is the latest public release as of the initial publication date. Most of the topics discussed in the series will be compatible with older versions of the game engine, and perhaps also the new version which is supposed to be release sometime this year. There is however, one topics which is significantly different in the current 4.6.1 version compared to the older version of the game engine, and that is the UI (User Interface) pipeline. This is due to the new UI architecture in the engine which is far superior to what we had prior to this release. I for one, am very happy with the new UI architecture.)
使用代码(Using the code)
下载文章系列的项目/源代码:(Downloading the project/source code for article series:) 下载源(Download source) .(.) 随着每篇连续的文章的提交,项目/源代码也将不断扩展.新的项目文件和源文件将包括该系列中的较早部分.(With each consecutive article that is submitted, the project/source code will be also expanding. The new project files and source files will be inclusive of older parts in the series.) **注意:(NOTE:)**要获取最新代码,请转至该系列中最新发布的部分并下载代码.(To get the latest code, go to the most recent published part in the series and download the code.)
改善设计(Improving Our Design)
到目前为止,我们将继续我们的工作,让我们来看看到目前为止在我们的设计中存在的一些缺点.(Continuing on our work so far, let’s go ahead and take a look at some of the drawbacks that we have in our design so far.) 当前设计的主要缺点之一是:当给定游戏结束时,玩家可以选择再次玩.如果您遵循了先前文章中的结构和逻辑,那么您可能已经注意到这里存在一个很大的缺陷.我们当前的设计无法正确重置游戏以进行新的会话.为此,我们需要进行一些设计更改,以便我们可以处理此问题.(One of the main drawbacks in the current design is the following; when a given game is completed, and the player is given the option to Play Again. If you have followed the structure and the logic in the previous articles, you might have noticed that there is a big flaw here. Our current design, does not reset our game for a new session correctly. In order to do so there are several design changes we would need to do so that we can handle this issue.) 由于我们是在设计时创建硬币的,因此当我们在运行时收集硬币时,实际上是从内存中删除了硬币,并且没有其他方法可以为新的游戏会话/玩法重新生成它们.这是一个问题,因为当前的游戏逻辑根据两个条件结束游戏:(Since, we are creating our coins at design time, when we collect the coins at runtime, we are actually removing the coins from memory, and we have no other means to regenerate them for a new game session/play. This is a problem because, the current game logic ends the game based on two conditions:)
-
如果时间到了,游戏将结束.(The game will end if the time is up.)
-
如果玩家在时间到之前收集了所有硬币,游戏将结束.(The game will end if the player has collected all coins before the time is up.)
在第一种情况下,假设时间已到,玩家已从八个硬币中收集了五个.当他或她选择"再次玩"选项时,游戏将以一组新的计时器开始,但是要收集的总硬币数将是原始游戏与新游戏之间的差,因此为新游戏会话将开始收集三个硬币.依此类推.(In the first scenario, assuming the time is up and the player has collected five out of the eight coins. When he or she selects the Play Again option, the game will start with a new set of timer, but the number of total coins to be collected will be the difference between the original game play and the new game play, therefore the new game session will start with three coins to be collected. And so forth.) 在第二种情况下,当玩家收集所有硬币时,游戏结束.当玩家根据当前实现选择"再次播放"选项时,游戏将立即结束,因为硬币数为零!(In the second scenario, when the player collects all of the coins, the game ends. When the player select the Play Again option, based on the current implementation, the game will immediately end, because there are zero coins!) 要解决此问题,我们需要重新考虑和重新设计游戏逻辑:(To solve this issue, we need to re-think and redesign our game logic:)
- 我们需要一种机制来动态创建我们的硬币.(We need to have a mechanism to create our coins dynamically.)
同样,有多种设计选择和方法可用于处理此标准.我们可以:(Again, there are more than one design choices and approaches available to handle this criteria. We can either:)
-
预先确定级别中所有可用硬币的位置.(Pre-define the locations of all of the coins available in the level as fixed.)
-
或者让它们随机放置在水平仪上.(Or have them be randomly placed on the level.)
从编码的角度来看,选项一会更简单.您将在设计时预定义硬币的位置,并使用这些转换数据来一遍又一遍地动态实例化同一位置的硬币.不利的一面是,对于所有游戏阶段,硬币将始终位于同一位置.(From a coding perspective, option one would be simpler. You will pre-define the locations of the coins at design time, and use these transform data to dynamically instantiate coins in the same spot over and over again. Down side, is that the coins will always be in the same location for all game sessions.) 第二个选项将涉及更多的计划和编码,因为您需要将硬币随机放置在关卡中,但是,您必须小心,将它们放置在一定的约束下,以免在给定的墙和墙内生成它们.等等…(Option number two will involve more planning and coding, because you will need to randomly place the coins within the level, but, you have to be careful that you place them with certain constraints, so that they do not be generated within a given wall and etc…) 让我们继续实施第二个选项.这种方法将使游戏者每次玩游戏时更加随机,并且,实施第二个选项将涵盖两个选项的概念.(Let’s go ahead and implement option number two. This approach will make the game more random each time the player plays it, and also, implementing option number two, will cover the concepts for both options.)
随机化我们的硬币(Randomizing Our Coins)
首先,我们需要弄清楚放置硬币的边界.在水准仪设计中,我们知道水准仪是10米x 10米的平台.我们还知道该级别在定义的区域内定义了墙.(First, we need to figure out our boundary for placing the coins in. In our level design, we know that our level is a 10 meter by 10 meter platform. We also know that the level has defined walls within the defined area.)
如果我们的水平线位于原点(0,0,0),则我们的水平线将覆盖世界中Z轴正方向的以下角点:(5,0,5)和(-5,0,5),并且负Z方向将是(5,0,-5)和(-5,0,-5).这四个点是我们在场景中定义的水平边界.(If our level is placed at the origin (0,0,0), then our level cover the following corners in the world for the positive Z direction: (5,0,5) and (-5,0,5) and for the negative Z direction it will be (5,0,-5) and (-5,0,-5). These four points are our level boundaries as defined in the scene.)
因此,我们生成的任何硬币都必须在我们空间的这四个坐标内.但是,我们在级别中也有预定义的墙,我们也需要考虑到这一点.同样,这不是一项艰巨的任务,因为作为关卡设计师,您确切地知道如何细分迷宫,至少您应该这样做!(So whatever coins we generate have to be within these four coordinates in our space. However, we also have pre-defined walls in our level, and we need to take that into consideration as well. Again, this is not a hard task, because you as the designer of the level know exactly how you have subdivided your maze, you at least you should!)
图1-显示重要级别尺寸(Figure 1-Displaying Important Level Dimensions)
在上图中,请注意,我已指出了内壁偏移量的尺寸.使用此信息,您将能够编写代码以根据关卡设计有效地放置硬币.分解它的最简单方法是将内部区域分解为多个区域.我将区域分为四个主要区域:(In the figure above, notice that I have indicated the dimensions of the internal wall offsets. Using this information, you will be able to write code to place the coins according to the level design effectively. The easiest way to break it down, would be to dissect the internal area into regions. I would divide the area into four main regions:)
图2-突出显示定义的区域(Figure 2-Highlighting Defined Regions) 如图2所示,我标记了可用于放置硬币的四个区域.最大的区域是1区,可以通过以下几点进行定义:(As you can see in Figure 2, I have labeled the four regions which are available for coin placement. The largest one is Region 1 which can be defined by the following points:)
-
1区,外边界:(Region 1, Outer Bound:)(4.5,0,4.5)(-4.5,0,4.5)(4.5,0,-4.5)(-4.5,0,-4.5)((4.5,0,4.5) (-4.5,0,4.5) (4.5,0,-4.5) (-4.5,0,-4.5))
-
1区,内界:(Region 1, Inner Bound:)(3,0,3)(-3,0,3)(3,0,-3)(-3,0,-3)((3,0,3) (-3,0,3) (3,0,-3) (-3,0,-3))
可以使用以下几点来定义区域2\3和4:(Region 2, 3 and 4 can be defined with the following points:)
-
区域2:(Region 2:)(2,0,2)(-2,0,2)(2,0,1.5)(-2,0,1.5)((2,0,2) (-2,0,2) (2,0,1.5) (-2,0,1.5))
-
区域3:(Region 3:)(2,0,0.5)(-2,0,0.5)(2,0,-0.5)(-2,0,-0.5)((2,0,0.5) (-2,0,0.5) (2,0,-0.5) (-2,0,-0.5))
-
区域4:(Region 4:)(2,0,-2)(-2,0,-2)(2,0,-1.5)(-2,0,-1.5)((2,0,-2) (-2,0,-2) (2,0,-1.5) (-2,0,-1.5))
**注意:(NOTE:)**由于壁的厚度为0.5,因此您需要将其边界考虑在内.(Since the walls have a thickness of 0.5, you need to take that into consideration with your boundaries.) 下一个问题是,每个区域我们要生成多少个硬币.查看我们定义的区域,区域一是最大的区域,因此可以容纳最多的硬币.我们为区域1分配8个硬币.区域2\3和4具有相同的正方形面积,并且相对较小,因此让我们为其余每个区域分配2个硬币.(The next question, is how many coins per region we would like to generate. Looking at the regions that we have defined, region one is the largest, and therefore can hold the most coins. Let’s assign eight coins to Region 1. Region 2, 3 and 4 have the same square area, and are relatively smaller, therefore let’s assign two coins to each of the remaining regions.) 现在,让我们看看脚本将如何根据新规则进行更改.我们将更新我们的(Let’s now look at how our script will change based on the new rules. We will be updating our)**inputPlayer.cs(inputPlayer.cs)**脚本如下:(script to the following:)
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class playerInput : MonoBehaviour {
...
public GameObject coinPrefab; // variable used to store the coin prefab
...
// Use this for initialization
void Start () {
#region COIN CREATION
// we need to create the coins dynamically per region
// Coins for Region 1
for (int i=0; i<16; i++) {
// Fill the Top part of Region 1
if(i<4){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(3.0f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1TopC"+i;
}
// Fill the Bottom part of Region 1
if(i>3 && i<8){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(-4.5f, -3.0f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1BottomC"+i;
}
// Fill the Left part of Region 1
if(i>7 && i<12){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, -3.0f), 0.25f, Random.Range(-4.5f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1LeftC"+i;
}
if(i>11 & i<16){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(3.0f, 4.5f), 0.25f, Random.Range(-4.5f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1RightC"+i;
}
}
// Coins for Region 2
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(1.5f, 2.0f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R2C"+i;
}
// Coins for Region 3
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-0.5f, 0.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R3C"+i;
}
// Coins for Region 4
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-2.0f, -1.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R4C"+i;
}
#endregion
...
}
...
}
我们引入了一个名为(We have introduced a new variable called)coinPrefab(coinPrefab)作为一个GameObject,您可以猜到它用来存储我们在上一篇文章中已经定义的硬币预制件.该变量是公共变量,因此您可以拖放预制件以将其分配给脚本.(as a GameObject, that is used to store the, you guessed it, coin prefab we already defined in our previous article. The variable is public so that you can drag and drop the prefab to assign it to the script.)
下一个重大变化是我们的(The next major change is in our)开始()(Start())功能.我们为每个区域定义了一个循环.区域2\3和4的循环非常简单,但是区域1的循环稍微复杂一些.这是因为从技术上讲,我们的Region 1本身由4个虚拟区域组成:(function. We have defined a loop for each region. The loop for Region 2, 3 and 4 are pretty straight forward, but the loop for Region 1 is a little more complex. That is because our Region 1 itself technically is composed of 4 virtual regions:)上,下,左和右(Top, Bottom, Left and Right).(.)
对于区域2\3和4,我们分别为每个区域分配4个硬币.对于区域1,我们分配16个硬币,每个虚拟区域分为4个硬币:顶部,底部,左侧和右侧.(For Regions 2, 3 and 4, we assign 4 coins per region respectively. For Region 1, we assign 16 coins, broken down to 4 coins per virtual region: Top, Bottom, Left and Right.)
所以总共有(So there are a total of)12 + 16 =28(12 + 16 = 28)现在游戏中的硬币会随机放置在关卡中.您现在可以从您的设计中删除设计时硬币(coins in the game now that are randomly placed within the level. You can now remove the design time coins from your)层次窗口(Hierarchy Window).除去设计时间硬币后,您的等级应类似于以下内容:(. After the removal of your design time coins, your level should look something like the following:)
图3-没有设计时币的等级(Figure 3-Level without Design Time Coins)
运行游戏时,您的关卡将充满代码逻辑中定义的28个随机放置的硬币:(When you run the game, your level will be filled with the 28 randomly placed coins as defined in your code logic:)
图4:在运行时动态生成的硬币(Figure 4-Coins Dynamically Generated at Runtime) 因此,在这一点上,我们已经解决了在运行时随机创建和放置硬币的问题.一切都很好,但在让您兴奋不已之前,您还需要做更多的场景和改进才能真正庆祝!(So at this point, we have solved our issue of creating and placing our coins randomly at runtime. It is all good and dandy, but, before you get too excited, there are few more scenarios and improvements that you need to do before you can really celebrate!)
真正的重置(A True Reset)
如果您已经走了那么远,那么在继续前进之前,请先运行游戏.玩几次游戏,并注意您的设计时环境.你注意到什么?(If you have come so far, before you move forward, go ahead and run the game. Play the game a few times, and pay attention to your design time environment. What do you notice?) 好了,每次您创建新会话时,前一个会话中的硬币都会被带到新会话中.因此,您最终将获得更多硬币.在这种情况下,这并不是我们游戏真正想要的.当我们休息游戏时,即开始一个新的会话,我们希望它从头开始!因此,我们需要在开始新会话之前进行一些清理.(Well, each time you create a new session, the coins from the previous session get carried over to the new session. Therefore you end up with more coins. This is not what we actually want in this case for our game play. When we rest our game, i.e., start a new session, we want it to start from scratch! Therefore, we need to do some cleanup before we start a new session.) 因此,要处理这种情况,我们需要以某种方式检测场景中现有的硬币对象,并在开始新游戏会话之前将其从场景中删除.为此,我们需要再更新一次脚本来处理这种情况.您可以在两个地方处理此问题,(So to handle this scenario, we need to somehow detect the existing coins object in the scene, and remove them from the scene before we start our new game session. To do so, we would need to update our script one more time to handle that situation. You can handle this in two places, either in the)开始()(Start())功能或(function or the)butPlayAgain_Click()(butPlayAgain_Click())功能.我将在其中放置处理这种情况的逻辑(function. I will be placing the logic to handle this scenario in the)butPlayAgain_Click()(butPlayAgain_Click())功能,列表将进行如下修改:(function, and the listing will be modified as follows:)
...
public void butPlayAgain_Click(){
// get all object of type coin
GameObject[] coins = GameObject.FindGameObjectsWithTag ("coin");
// remove eahc object from the scene
foreach (GameObject coin in coins){
Destroy(coin);
}
Start ();
}
...
此更新将确保我们始终在开始新会话之前从场景中删除以前创建的硬币.(This update will ensure that we always remove previously created coins from the scene before starting a new session.) 完整的清单如下:(The full listing will be as follows:)
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class playerInput : MonoBehaviour {
public Text lblScore; // text UI element for displaying score
public Text lblTimer; // text UI element for displaying timer
public Canvas endGameCanvas; // Canvas holding UI elements for End of Game
public Text lblEndOfGameScore;
public Text lblEndOfGameTime;
public Text lblEndOfGameCoinCont;
public GameObject coinPrefab; // variable used to store the coin prefab
private int score; // internal score variable
public int SCORE
{
get{ return this.score; }
}
private float levelTime; // variable holing time to complete level
private float timeLeft; // variable for the actual timer count down
public bool END_GAME; // variable indicating end of game
public int numOfCoinsInLevel; // will be initialized at the Start of the game
public int numOfCoinsCollected; // will be incremented each time we collect a coin
// Use this for initialization
void Start () {
#region COIN CREATION
// we need to create the coins dynamically per region
// Coins for Region 1
for (int i=0; i<16; i++) {
// Fill the Top part of Region 1
if(i<4){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(3.0f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1TopC"+i;
}
// Fill the Bottom part of Region 1
if(i>3 && i<8){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(-4.5f, -3.0f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1BottomC"+i;
}
// Fill the Left part of Region 1
if(i>7 && i<12){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-4.5f, -3.0f), 0.25f, Random.Range(-4.5f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1LeftC"+i;
}
if(i>11 & i<16){
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(3.0f, 4.5f), 0.25f, Random.Range(-4.5f, 4.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R1RightC"+i;
}
}
// Coins for Region 2
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(1.5f, 2.0f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R2C"+i;
}
// Coins for Region 3
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-0.5f, 0.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R3C"+i;
}
// Coins for Region 4
for (int i=0; i<4; i++) {
GameObject coin = GameObject.Instantiate(this.coinPrefab,
new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-2.0f, -1.5f)),
this.coinPrefab.transform.rotation) as GameObject;
coin.name = "R4C"+i;
}
#endregion
this.score = 0;
this.levelTime = Time.time + 30.00f;
this.numOfCoinsCollected = 0;
this.END_GAME = false;
if (this.endGameCanvas != null) {
this.endGameCanvas.gameObject.SetActive (false);
}
// check to make sure labels are defined before updating
if (this.lblScore != null)
this.lblScore.text = this.score.ToString();
if (this.lblTimer != null)
this.lblTimer.text = string.Format("{0:F2}", this.levelTime - Time.time);
// get number of coins in the scene at the start of the game
this.numOfCoinsInLevel = GameObject.FindGameObjectsWithTag ("coin").Length;
}
// Update is called once per frame
void Update () {
if (!this.END_GAME) {
// compute time left
this.timeLeft = this.levelTime - Time.time;
// update UI label for timer
if (this.lblTimer != null){
this.lblTimer.text = string.Format("{0:F2}", this.timeLeft);
}
// check to see if we need to end the game based on the timer
if(this.timeLeft<=0.00f || this.numOfCoinsInLevel<=this.numOfCoinsCollected){
this.END_GAME = true;
if (this.lblTimer != null && this.lblEndOfGameTime != null){
if(this.timeLeft>=0.00f){
this.lblTimer.text = string.Format("{0:F2}", this.timeLeft);
this.lblEndOfGameTime.text = string.Format("{0:F2}", this.timeLeft);
}else{
// this else block is written to ensure that if the timer is up, we always get 0.00
// and not positive or negative values, i.e. 0.01, or -0.01 and etc...
this.lblTimer.text = string.Format("{0:F2}", 0.00f);
this.lblEndOfGameTime.text = string.Format("{0:F2}", 0.00f);
}
}
if(this.lblEndOfGameScore != null && this.lblEndOfGameCoinCont != null){
this.lblEndOfGameScore.text = this.SCORE.ToString();
this.lblEndOfGameCoinCont.text = this.numOfCoinsCollected.ToString();
}
}
// code for the movement of player (CP) forward
if(Input.GetKey(KeyCode.UpArrow)){
this.transform.Translate(Vector3.forward * Time.deltaTime);
}
// code for the movement of player (CP) backward
if(Input.GetKey(KeyCode.DownArrow)){
this.transform.Translate(Vector3.back * Time.deltaTime);
}
// code for the movement of player (CP) left
if(Input.GetKey(KeyCode.LeftArrow)){
this.transform.Rotate(Vector3.up, -5);
}
// code for the movement of player (CP) right
if(Input.GetKey(KeyCode.RightArrow)){
this.transform.Rotate(Vector3.up, 5);
}
}else{
if(this.endGameCanvas != null){
this.endGameCanvas.gameObject.SetActive(true);
}
}
}
// This event will be raised by object that have their Is Trigger attributed enabled.
// In our case, the coin GameObject has Is Trigger set to true on its collider.
void OnTriggerEnter(Collider c){
if(c.tag.Equals("coin")){
Coin coin = c.GetComponent<Coin>();
// increase score
this.score += coin.VALUE;
this.numOfCoinsCollected += 1;
// update score on the UI
if (this.lblScore != null)
this.lblScore.text = this.score.ToString();
// remove the Coin object from the scene
Destroy(c.gameObject);
}
}
public void butPlayAgain_Click(){
// get all object of type coin
GameObject[] coins = GameObject.FindGameObjectsWithTag ("coin");
// remove eahc object from the scene
foreach (GameObject coin in coins){
Destroy(coin);
}
Start ();
}
}
每个人都喜欢金币!(Everybody Loves Gold Coins!)
因此,既然我们已经解决了硬币的动态创建以及游戏的其余部分,那么现在让我们看一下如何改善游戏的外观.我想做的第一件事是使硬币看起来和感觉像金币.(So now that we have addressed the dynamic creation of the coins and also the rest of the game, let’s now look at how to improve the look and feel of the game a little bit. The first thing I would like to do is to make my coins to look and feel like gold coins.) 为了实现这一点,我将需要创建一种具有代表金色纹理的材质.让我们看看如何实现这一目标.(In order to achieve this, I will need to create a material that would have the texture of representing gold. Let’s see how we can achieve this.) 步骤:(The steps:)
-
在项目内创建一个Material文件夹,以进行组织和管理.(Create a Materials folder within the project, for organization and management purposes.)
-
在文件夹中,右键单击并选择(Within the folder, right-click and select)创建->材料(Create->Material)来自(from the)上下文菜单(Context Menu).命名新的材质对象:gold_coin(. Name the new material object: gold_coin)
-
指定代表金色表面的纹理,或选择要应用于材质的颜色.(Assign a texture representing golden surface, or choose a color to be applied to the material.)
-
将新材料分配给硬币预制件!(Assign the new material to the coin prefab!)
**注意:(NOTE:)**材质用于为GameObjects分配纹理和/或颜色.(materials are used to assign textures and or colors to GameObjects.)
在这种情况下,由于我们已经有一个用来表示收集的硬币的纹理,因此我们可以使用相同的纹理来应用于我们的材料.如果应用相同的纹理,则将具有以下内容:(In this case, since we already have a texture we using to represent our coins collected, we can use the same texture to apply to our material. If you apply the same texture, you will have something like the following:)
图5-创建的新材料(Figure 5-New Material Created)
定义好材料后,您需要选择(Once, you have the material defined, you will need to select the)硬币(coin)预制下列出(prefab listed under the)预制件(prefabs)夹.然后将新材料拖放到(folder. Then drag and drop the new material in the)检查器窗口(Inspector Window)将材料分配给硬币预制件.(to assign the material to the coin prefab.)
**注意:(NOTE:)**本文不涉及纹理等问题,因此纹理看起来不会很漂亮!只是演示概念.(This article does not cover texturing and etc… so the texture will not look pretty! Just demoing the concept.)
图6硬币与新材料(Figure 6-Coins with New Material)
运行该程序时,您现在将看到硬币正在使用新创建的材料.由于我不是图形设计师,因此您可以看到硬币看上去不尽如人意.但是,尽管如此,您应该明白这一点.(When you run the program, you will now see that the coins are now using the newly created material. Since, I am not a graphics designer, you can see that the coin does not look as good as it could. But nevertheless you should get the idea.)
如果您到目前为止已完成所有工作,则将获得如下游戏体验:(If you have done everything up to this point, you will have a game play experience that look like the following:)
兴趣点(Points of Interest)
我们的游戏发展缓慢.到目前为止,我们在定义和微调小游戏方面已经走了很长一段路.随着系列的进行,您会注意到我花了更少的时间来解释基础知识,而花了更多的时间来学习新概念.(Our game is taking shape slowly. We have come a long way with defining and fine tuning our small little game thus far. As the series progresses, you notice that I spent less time explaining the basics and more time on the newer concepts.) 仍有很大的空间可以改善我们的游戏.在下一部分中,我们将研究如何创建起跑球,如何将数据保存并加载到我们的游戏中,甚至可能通过为玩家带来更多挑战来改善我们的游戏玩法.(There is still room to significantly improve our game. In our next part, we will look at how to create a start scree, be able to save and load data into our game, and perhaps even improve our game play by introducing more challenges for the player.)
历史(History)
这是系列文章的第七篇,我将慢慢为Code Project社区做出贡献.(This is the seventh article of a series which I would slowly contribute to the Code Project community.)
-
Unity 3D –游戏编程–第7部分(Unity 3D – Game Programming – Part 7)
Unity 3D网络文章:(Unity 3D Networking Article(s):)
-
Unity 3D-网络游戏编程(Unity 3D - Network Game Programming) Unity 3D Leap Motion和Oculus Rift文章:(Unity 3D Leap Motion and Oculus Rift Article(s):)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# .NET Mobile iPhone Android Windows Design Dev 新闻 翻译