使用Unity做2.5D游戏教程(二)

 最近在研究Unity 3D,看了老外Marin Todorov写的教程很详细,就翻译过来以便自己参考,翻译不好的地方请多包涵。

 这是使用Unity 游戏开发工具制作一个简单的2.5D 游戏系列教程的第二部分。如果你没有看到第一部分的话请先看。

 在系列教程的第一部分,我们覆盖了一些怎样使用Unity的基础性知识 和使用 C#写一些脚本。我们创建了一个简单的游戏,一个飞机可以来回飞行同时轰炸鲨鱼,保护小鱼!

  在这个教程的第二部分也是最后一部分,我们将延长这个游戏添加一些收尾内容。我们将添加一个声音效果和音乐,完善游戏逻辑,并为游戏添加多个场景!

  如果你还没有这个项目,请下载我们在上个教程留下的 project,并使用Unity打开它。如果它不能启动和加载,确保点击Scenes\LevelScene选项,让它可见。

 好了,让我们学习更多有关Unity的知识,并完善这个游戏。

1. 添加iCandy到游戏中

 

 你已经注意到 ,当炸弹击中鲨鱼时,它只是静静地消失,你会想:“那不是非常酷!”

 好吧,我们要添加一个很酷的水下爆炸效果!

 从菜单栏中选择“GameObject/Create other/Particle System”,你会看到一个粒子系统出现在场景中,在“Hierarchy”面板中重命名这个Particle System”为 “Explosion”(爆炸),设置这个Explosion的position位置为[1, 1, 8].

 现在你如果是一个粒子系统的专家——前往“Inspector”面板自己设置 ,如果你不是,只需要跟随我们的指导是很容易的。覆盖这些值到”Inspector“中:

这里最重要的属性是“One shot”——当你检查它时,系统将只会发送一次粒子 ——正如爆炸那样。现在让我们设置动画值——只是尝试更多或更少的颜色相匹配(如果你不做,也并不重要):

 

 这里最重要的属性是“Autodestruct”(自毁)——当选中这个粒子系统时,当没有更多活动的粒子时将会把自己从场景中移出去。这正是我们想要的——它就像一个垃圾收集器。

 现在你有一个漂亮的小规模爆炸,你需要做一个像之前做炸弹的一样——做一个预制,在需要它的时候实例化,当它在场景中完成任务时让它自动销毁。

 在“Project”面板中“Prefabs”文件上右键单击,选择 “Create/Prefab”,重命名为 “ExplosionPrefab”.在“Hierarchy”面板中拖拽 “Explosion”对象到这个新建的“ExplosionPrefab”文件上。在“Hierarchy”面板中右键单击 “Explosion”并选择删除。

 在"Project"面板中右键单击,选择“Sync MonoDevelop Project”来打开MonoDevelop。打开BombClass.cs文件,并在里面添加如下代码:

//right under definition of "ySpeed"
public GameObject explosionPrefab;
 
//inside OnTriggerEnter, right after Destroy(this.gameObject)
Instantiate(explosionPrefab, transform.position, Quaternion.identity);


 现在切换回Unity并在“Project”面板中选中“BombPrefab”——在“Inspector”面板中你可以看到新的属性 “ExplosionPrefab”。只需要拖拽在“Project”面板中的“ExplosionPrefab”文件到这个新的属性文件上,你就设置好了。

  好了——点击Play按钮,观看你命中鲨鱼的爆炸效果。

 

2.添加earCandy到游戏中 

 不要告诉Steve,但是对于我们iCandy不够的,我们也需要一些earCandy!

 我们怎么能只有一个游戏而没有背景音乐?我们要拜访另一个伟大的人——Kevin Macleod。他是一个伟大的电影和游戏音乐作曲家,他的作品有在 CC license许可下。所以你要使用他的东西不要忘了署名。

 打开链接:http://incompetech.com/m/c/royalty-free/index.html?keywords=the%20cannery

 一旦你到达这个页面时,下载“The Cannery”文件到你的硬盘上,并拖拽下载好的“The Cannery.mp3″文件到你“Project”面板的 “Audio”文件夹下。

 我们想把音乐全时段的循环播放——但是我们应该把它附加到那个对象上呢?

 好吧,让我们把它附加到camera相机上!这个camera也是一个游戏对象,并可以有其他附加组件。

 从“Project”面板中把“The Cannery”拖拽到“Hierarchy”面板中的“Main Camera”上。 选中“Hierarchy”面板中的“Main Camera”,并在“Inspector”面板中找到 “Audio Source”选项 ——勾选住“Loop”选项框并设置Volume值为“0.20”.

 就是这样简单——运行这个场景并享受这个新的背景音乐吧!

3.使用Unity 创建一个GUI

 让我们进入一个新的领域——GUI。Unity为你提供一些标准的labels和buttons,但是这些都不是Unity强大的功能。然而,我们需要一个label来显示当前的得分;所以首先我们需要实现得分的逻辑。

 切换回MonoDevelop。 打开PlayerClass.cs文件并添加一个新的属性:

public static int score = 0;

  啊哈!又有了新的东西—— “static”。当类被加载和时这个属性将被创建,不管是否有这个类的实例。此外,这个属性可以被其他类访问——这就是为什么我们要保持这个得分计数为静态类型的原因。

 接下来添加更新得分的方法(现在没有太大的意义,但只管先创建它)——看比分属性是如何通过类名访问:

public void updateScoreBy(int deltaScore) {
	PlayerClass.score += deltaScore;
}

  再添加一个新方法到 PlayerClass——这将会在屏幕上绘制得分计数:

  

void OnGUI() {
	GUIStyle style = new GUIStyle();
	style.fontSize = 20;
	GUI.Label(new Rect(10,10,100,20), "Score:"+PlayerClass.score, style);
);
}

 "OnGUI"此事件在GUI layer(图形用户界面层)每一帧上被调用。

  GUIStyle是一个类,它类似一个CSS类——所以你可以使用fontSize,marginLeft这样的你所熟悉的CSS方法,否则现在只保留字体大小。GUI.Label()是个拥有3个参数的方法:一个矩形的Label,绘制的字符串,和text风格。这就是全部了。

 剩下的唯一的任务是:当我们有命中或没命中时更新比分。 打开BombClass.cs文件,并做如下代码修改:

 

//add a new property
public PlayerClass player;
 
//replace the existing OnTriggerMethod with
void OnTriggerEnter(Collider obj) {
	if (obj.gameObject.name == "Shark") {
		//reset shark
		obj.gameObject.transform.rotation = Quaternion.identity;
		obj.gameObject.transform.position = new Vector3(20f, -3f, 8f);
		player.updateScoreBy(+1);
		Destroy(gameObject);
		Instantiate(explosionPrefab, transform.position, Quaternion.identity);
	}
	if (obj.gameObject.name == "ClownFish") {
		//reset fish
		obj.gameObject.transform.rotation = Quaternion.identity;
		obj.gameObject.transform.position = new Vector3(-20f, -1f, 8f);
		player.updateScoreBy(-1);
		Destroy(gameObject);
		Instantiate(explosionPrefab, transform.position, Quaternion.identity);
	}
}

 这跟我们以前的非常相似, 但我们有了一个新的属性叫做“player”,并且当我们需要更新分数时我们只需要调用player.updateScoreBy()。

 也为了使游戏更加有趣,如果你打的是鲨鱼你将得到一个点,如果你打的是小鱼,那么你将失去一个点。下载呢,塑造一场艰难的比赛!

 最后一件事——设置这个player(玩家)属性上的炸弹。现在我们不能像之前那样创建,因为炸弹是动态创建的,但幸运的是炸弹是由玩家自己创建,这样他可以在创建时设置这个玩家属性。

 让我们开始做——打开PlayerClass.cs文件并在这一行“bombObject.transform.position = this.gameObject.transform.position;”下方添加如下代码:

BombClass bomb = (BombClass)bombObject.GetComponent("BombClass");
bomb.player = this;

 这又有了新的东西了!让我们分析下:bombObject是一个GameObject对象的实例化(实例化返回),所以我们称之为“GetComponent”,并且这样我们可以访问所有连接的游戏对象组件——结果我们映射到一个BombClass——所以最后我们得到连接到游戏对象的C#类的引用。接下来,我们只要设置“player”属性(PlayerClass 的实例)。

  运行这个场景,你将会看到分数显示!

 

4.Unity 对象和组件

 到这个地步,你对Untiy的游戏对象模型被引用已经有了足够的练习使用。更好地了解你实际上是在做什么,对不对?让我们做一个非常短的复习来看卡游戏中的涉及对象和组件是如何连接的。

 在“Inspector”面板中我们所看到的所有选项条目——这些事游戏对象中比较重视的组件。一个空的对象只有它的 transform选项条目——position, rotation, scale.这是所有的——一切附加组件。

  • Transform: provides position, rotation, and scale, as described above.(提供位置,旋转和缩放,如上所述。)
  • Mesh Filter: provides the geometry of the visible object.(提供可视对象的几何形状。)
  • Mesh Renderer: renders the geometry.(呈现几何。)
  • Rigidbody: handles physics.(处理物理。)
  • Audio Source: plays audio.(播放音频。)
  • Script: can programmatically update the object.(可以通过编程更新对象。)

 这些只是小数属性可以附加到一个对象上。为了更好的理解,让我们看卡这张图片:

 

 因此,脚本组件采用点视图方式。它会看起来更清楚一些,为什么我们不得不调用它:

Destroy(this.gameObject);

 为了销毁一切跟对象有关的实例。通过游戏对象的属性我们可以访问所有其他组件,所以我们可以physics物理化或调整音量,等等。

 

5.添加更多的场景

 现在我们的游戏是越来越好了,但是没有方式显示输和赢!

 所以让我们添加一个“you win”的场景,当玩家做出3点以上的成绩时。

 从菜单栏中选择“File/New Scene”,然后再次从菜单栏中选择“File/Save Scen”,弹出框中选择文件夹“【你的项目目录】/Assets/Scenes”,没有Scenes文件夹就创建一个,并以“WinScene”文件名保存。

 在“Hierarchy”面板中选中“Main Camera”并设置:Position [0, 0, 0],Projectio为“Orthographic”, Size 为 “10″, Near 为 “0.5″ and Far 为 “22″。从菜单栏中选择“GameObject/Create Other/Directional Light”并在“Inspector”面板中设置:Position [0, 0, 0].

 我们想要在场景中放一个平面(像在我们游戏中的背景),并放一个图片在它上面叫“you win”,所以让我们像在第一部分中所做一样:从菜单栏中选择“GameObject/Create Other/Plane”并在“Inspector”面板中设置:Position [0, 0, 8], Rotation 为 [90, 180, 0], Scale 为 [3, 1, 2].

 下一步下载并保存 Vicki Wenderlich所做的这个图片到你的硬盘上,浏览如下:

 拖拽下载的“gameover_youwin.png”到“Project”面板中的“Textures”文件夹中。这个纹理被导入后看起来有点脏——这是因为压缩的原因,只需要在“Project”面板中选中 “gameover_youwin”纹理,然后在“Inspector”面板中找到 “Format”并改变它的值为 “16bits”,并点击“Apply”。现在把“Project”面板中的“gameover_youwin”拖拽到“Hierarchy”面板中的“Plane”上。在你的“Game”面板中你应该看到“You win”——Vicki所绘制的这个邪恶的鲨鱼漂浮起来。

 我们需要让它活动起来——当场景被点击时,游戏应该重新启动:在“Project”面板中的“Class”文件夹下右键单击,并选择“Create/C Sharp Script”,然后重名为“GameOverClass”。在"Project"面板中右键单击并选择“Sync MonoDevelop Project”。在MonoDevelop中打开新建的 GameOverClass.cs文件,并替换如下代码:

using UnityEngine;
using System.Collections;
 
public class GameOverClass : MonoBehaviour {
	// Update is called once per frame
	void Update () {
		if (Input.anyKeyDown) {
			PlayerClass.score = 0;
			Application.LoadLevel("LevelScene");
		}
	}
}

 当玩家点击这个屏幕时候,比分重置和重新加载游戏场景。Application.LoadLevel()只需要加载场景的名字——很容易。

 切换回Unity:从“Project”面板中的“Class”文件夹下拖拽 “GameOverClass”脚本文件到“Main Camera”上。

 现在在项目中包括这个场景下 选择 “File/Build Settings”,并在弹出框中点击 “Add current”按钮,关掉框框。你已经添加这个场景到这个项目的建设中。

 然我们也快速添加“You loose”场景!像上次一样,制作一个“New scene”,然后保存这个新场景为“LooseScene”到这个“Scenes”文件夹下。

 在“Hierarchy”面板中选中 “Main Camera”并设置: Position [0, 0, 0], Projection to “Orthographic”, Size to “10″, Near to “0.5″ and Far to “22″。从菜单栏中选择“GameObject/Create Other/Directional Light”,并在"Inspector"面板中设置:Position [0, 0, 0]。从菜单栏中选择“GameObject/Create Other/Plane”,并在"Inspector"面板中设置: Position [0, 0, 8], Rotation to [90, 180, 0], Scale to [3, 1, 2]。

 下载这个“You Lose”图片保存在你的硬盘上面,预览如下:

 

 采取以下步骤包装这个场景:

  1.拖拽下载的“gameover_youlose.png”到“Project”面板中的“Textures”文件夹下。

  2.在“Project”面板中选中 “gameover_youlose”纹理,然后在“Inspector”面板中找到“Format”改变它为“16bits”,并点击 “Apply”。

  3.从“Project”面板中拖拽 “gameover_youlose”文件到“Hierarchy”面板中的“Plane”上。

  4.从“Project”面板中的“Class”文件夹下拖拽“GameOverClass”文件到这个“Main Camera”。

  5.从菜单栏选择“File/Build Settings”,在弹出框中,点击“File/Build Settings”按钮,关掉弹出框。

 这里——你有3个场景,但你需要把它们联系起来!

 进入到这个LevelScene场景——通过双击“Project”面板中的 “LevelScene”。切换到MonoDevelop并打开PlayerClass.cs文件。我们要去修改这个updateScoreBy方法来检测你是否赢得超过3点还是在负3点以下。

 

//replace the updateScoreBy method with this code
public void updateScoreBy(int deltaScore) {
	PlayerClass.score += deltaScore;	
	if (PlayerClass.score>3) {
		Application.LoadLevel("WinScene");
	} else if (PlayerClass.score<-3) {
		Application.LoadLevel("LooseScene");
    }
}

     

现在你的场景工作流程被设置。你可以在Unity中点击Play按钮运行游戏。其实——你为什么不点击“File/Build&Run”,当Xcode弹出框——点击“Run”,也就尝试在您的iPhone上运行游戏。

6.展望2.5D——最后

 是时候了,让你在本系列教程的第二部分看你一直期待的2.5D技术!

 我将提前爆料一个秘密——我打算把它几乎为3D展示,为您的开发增添乐趣!

 截止到现在,我们已经设置这个 cameras’ projection(摄像机的投影)为“Orthographic”(正面),这让场景看起来像一个普通的2D游戏—到此为止!

 在你的LevelScene场景中选中 “Main Camera”,并在“Inspector”面板中改变这个Projection为“Perspective”,和 “Field of View”为“100″(以Perspective的角度看).好了,点击这个Play按钮,在2.5D下观看你的游戏。是不是很酷呢?

 但是我们不能止步于此。

 这有个计划——使游戏变得更加困难写,并演示如何旋转和移动摄像机,每一次的得分增加,我们将按钮圆弧路径移动摄像机,并改变它的角度。这样你越在游戏中进步,你将不得从怪异的角度看目标和尝试轰炸鲨鱼!

 切换回MonoDevelop,并对 PlayerClass.cs文件做如下更改:

//add the properties
public GameObject mainCamera;
public GameObject gameBackground;
public float nextZ = 0;
 
//at the end of the updateScoreBy method
if (PlayerClass.score>0) {
	nextZ = PlayerClass.score*2.5f;
}
 
//at the end of the Update method
if (nextZ > mainCamera.transform.position.z) {
	mainCamera.gameObject.transform.Translate( 
		3* Mathf.Sin(transform.position.z/2 ) * Time.deltaTime, 
		0, 
		-Mathf.Sin(transform.position.z /2 ) * Time.deltaTime *0.3f
	);
	mainCamera.gameObject.transform.RotateAroundLocal( Vector3.up, Time.deltaTime*0.1f );
	gameBackground.gameObject.transform.RotateAroundLocal( Vector3.up, Time.deltaTime*0.1f );

}

 好吧——大量的代码,但是这正是我们需要的。让我们一点一点地分析它:

 首先,我们生命属性来引用Main Camera和Background plane(平面)。我们将移动和旋转摄像头,我们也要将背景旋转。

 这个摄像机从它当前Z轴为0的位置移动到朝着background 7.2Z的位置。所以每次玩家得分,这个nextZ被设置为2.5,然后5.0,然后7.5——通过这些值Main Camera转换到用sin函数的圆弧状的东西。

 所有的数学函数通过Mathf类——正如这个sin函数为 Mathf.Sin()。所以我们旋转摄像机使用transform.RotateAroundLocal,我传递一个值(Vector3.up)绕轴,通过角度旋转。我们使摄像机和背景一起旋转,这样摄像机始终面对着背景(即用不完的屏幕背景)。

 更重要的事情——让我们连接新的公共属性。切换回Unity,在“Hierarchy”面板中选中“Player”对象。从“Hierarchy”面板中拖拽 “Main Camera”到“Inspector”面板中的新的 “Main Camera”属性上;从“Hierarchy”面板中拖拽“Background”对象到“Inspector”面板中的新的 “Game Background”属性上

 恭喜,你终于完成了!点击“File\Build and Run”,run the finished game on your iPhone.以怪异的角度轰炸鲨鱼吧!

 

7.Unity调试

 我想不免会触及一些话题,因为当你自己开发时,你会碰上麻烦,你需要调试你的游戏,incident,一些简单的事情要牢记:

 1.不要忘记在toolbar工具栏上有一个暂停按钮,所以你如果需要停止执行游戏,并检查所有对象的属性——只需要点击Pause按钮,然后浏览你周围的厂家,在“Inspector”面板中查看各种属性值。

 2.如果你不确定你的方法是否触发了,在控制台打印一条消息(类似在Xcode中)。使用:Debug.Log(“message”); 将消息打印到控制台。你可以选择菜单栏“Window/Console”,来调出控制台窗口。

 3.养成这种习惯:当你在MonoDevelop完成编码时,你切换回Unity看一看Unity的状态栏(在应用窗口的底部)——如果你写了错误的代码,将不会被验证,你会得到有红色的错误消息,你点击这些错误消息就能马上带你回到MonoDevelop。

 4.如果你的对象不动——三重检查你的script脚本文件是否连接到你的对象上。

 5.当你运行你的游戏时,你可以改变在“Inspector”面板中的值,只管尝试不同的值。当你暂停游戏时:NB在“Inspector”面板中的所有值都被重置到你运行游戏之前的数据。因此,如果你忘了停止游戏和你进行的更改,它们会丢失,所以请务必完成测试后停止游戏,然后继续开发。

 

源代码如下:sample project

如果你想学习更多有关Unity的知识请访问它们的论坛网站www.unity3D.com/support/.也可以看下Unity C# Reference.

 

 如需转载,请注明翻译出处 http://www.cnblogs.com/jiangshiyong/p/3150991.html

 

 

posted on 2013-06-24 01:12  一梦浮生2012  阅读(6396)  评论(1编辑  收藏  举报