Unity学习笔记 - Roguelike Tutorial(上)

// Unity学习笔记(零基础入坑),自用的同时也许也能帮助别人

// 初学者,没太多编程基础,所以难免可能会有写错的地方,请见谅

//详细教程视频都有,笔记只记重点

Unity学习笔记 - Roguelike Tutorial(上)_第1张图片

官网教程链接:http://unity3d.com/cn/learn/tutorials/projects/2d-roguelike-tutorial/project-introduction?playlist=17150

这个中文版的教程讲的也很详细:http://tieba.baidu.com/p/4335701141

我本来是两个配合着看的,不过两个版本的脚本写法不大一样,后面就以官网教程为主了。

一、创建主角和敌人的动画


如何创建帧动画?

直接选中所有帧拖到物体上(或直接拖到 Hierarchy),会自动生成动画和动画控制器。

每个Object对应一个动画控制器(Animation Controller),里面包含多个动画。

分别把闲置动画、攻击动画和受伤动画的帧拖上去,生成各自的动画文件。

同类角色控制器的共用

在AnimatorController目录下,Creative-->Animator Override Controller创建一个控制器的重写副本(本例为Enemy2),将原版控制器(Enemy1)拖入controller项中。再将Enemy2的闲置和攻击动画拖入对应项中,完成重写。

Unity学习笔记 - Roguelike Tutorial(上)_第2张图片

这一步的总流程:

1.创建player,将主角的3种动画拖到player上

2.将生成的动画文件和动画控制器文件放到对应目录下(Assets-Animation-Animations&AnimatorControllers)

3.打开主角动画控制器,修改闲置动画(Idle)的速度为0.5

4.player物体拖入prefabs,删除场景中的

(player加box collider、rigidbody)

5.同上创建enemy1及动画,并拖入prefabs

(enemy1加box collider、rigidbody)

6.场景中的enemy1直接改成enemy2,拖入enemy2的动画,但在控制器中删除这两个动画

7.用上文方法,创建控制器enemy1的重写enemy2,并将刚才创建的enemy2的动画拖入对应项

完成!

2016.07.31


二、创建地面、障碍物和道具


地板、墙、道具,拖入场景由sprite转为Game Objects,配置SortingLayer、Collider、tag、Layer,拖入prefabs转为预制件。


三、用于生成地图的地图管理器


这可以算是一个关卡生成器。

目标是什么?

- 自动生成地板、围墙(为什么不手动摆?1.省事 2.有随机变化):位置固定、内容随机

- 自动生成障碍墙、道具、敌人:位置随机、内容随机、数量随机,但都有限制,并且敌人数量随关卡增加

- 顺便把出口exit也给生成了:不需要随机

实现目标的思路?

内容随机:从物体组中随机选取即可(objectArray[Random.Range(0, objectArray.Length)])

位置随机:将位置转化为一个Vector3的List,从中随机选取即可

                常用list.Add();   list.RemoveAt();   list.Count;   list[]

数量随机:在设定好的最大最小值之间随机选取即可

需特殊处理的:对于敌人的数量,以level为变量通过函数计算即可

                      使用list.RemoveAt()来避免,在一个位置上重复放东西

//这样写完感觉其实so easy啊 :目

具体怎么操作?

最终这个脚本包含了5个函数,只有最终的SetScenes是public的,其余都是内部使用。

没有使用Start和Update,所以唯一的运行条件就是SetScenes被调用(交给GameManager了)。

void InitialiseList()    //函数1,地图坐标列表初始化函数,用于放障碍、道具、敌人

void BoardSetup()  //函数2,铺地板、围墙

Vector3 RandomPosition() //函数3,自动选取放障碍、道具、敌人的随机位置,调用函数1中的变量

void LayoutObjectAtRandom(GameObject[] tileArray, int minimum, int maxmum) //函数4,摆放障碍、道具、敌人,调用函数3

public void SetupScene(int level) //函数5,完成关卡场景的布置,调用函数1、2、4

Unity学习笔记 - Roguelike Tutorial(上)_第3张图片
这一步搞了个类,感觉其实没有也可以的
Unity学习笔记 - Roguelike Tutorial(上)_第4张图片
Unity学习笔记 - Roguelike Tutorial(上)_第5张图片
函数1
Unity学习笔记 - Roguelike Tutorial(上)_第6张图片
函数2
Unity学习笔记 - Roguelike Tutorial(上)_第7张图片
函数3、4
Unity学习笔记 - Roguelike Tutorial(上)_第8张图片
函数5

补充材料:

coding中关于类、对象、属性、方法的概念:

http://liuyuru.iteye.com/blog/806705

关于List

List存放的是单一的数据类型的数据(ArrayList可以存放不同类型的数据)

本例创建了一个Vector3的list(gridPosition),(x,y)从(1,1)到(6,6),可从中随机选取格子放置障碍、道具或敌人。

Unity学习笔记 - Roguelike Tutorial(上)_第9张图片

教程中的坐标零点选的是围墙内左下角

Unity学习笔记 - Roguelike Tutorial(上)_第10张图片

2016.08.06 凌晨 没有编程基础学起来会慢一些,但是这种不断学东西的感觉很好


四、游戏控制器 —— Game Manager


加上Game Manager之后,就可以测试地图生成器的效果了。

以level 3为例,Awake里获取到Board Manager,然后运行下SetupScene就已经可以测地图生成的效果了:(Inspector中要把变量对应的prefabs拖进去)

Unity学习笔记 - Roguelike Tutorial(上)_第11张图片

效果如下,因为是从(-1,-1)点开始摆的所以偏的

Unity学习笔记 - Roguelike Tutorial(上)_第12张图片

调下镜头位置和背景色

Unity学习笔记 - Roguelike Tutorial(上)_第13张图片

之后要做的,是保证Game Manager是一个单例(singleton),即只会存在一个instance。因为之后Game Manager会被做成prefab。我目前的理解是,全局使用的物体会需要使用这种单例模式,因为在被调用时有产生多个的可能性。(此处理解不到位,待学习)

Unity学习笔记 - Roguelike Tutorial(上)_第14张图片

返回unity,把Game Manager拖入prefabs,并删掉场景中的。

做一个Loader来加载Game Manager的实例。

如果当前没有GameManager类的实例,则创建。

Unity学习笔记 - Roguelike Tutorial(上)_第15张图片

Loader挂在Main Camera上,Game Manager拖入变量gameManager中。

---说明----

1. 全局静态变量

public static GameManager instance = null;  

静态变量属于类本身而不是类的实例。全局静态变量可在任何时候被任何脚本调用。

所以即使在Game Manager未被实例化时,Loader也可以调用instance!

This means that we can now access the public functions and variables of our game manager from any script in our game.

关于静态变量:

静态变量属于静态存储方式,其存储空间为内存中的静态数据区(在 静态存储区内分配存储单元),该区域中的数据在整个程序的运行期间一直占用这些存储空间(在程序整个运行期间都不释放),也可以认为是其内存地址不变,直 到整个程序运行结束(相反,而auto自动变量,即动态局部变量,属于动态存储类别,占动态存储空间,函数调用结束后即释放)。静态变量虽在程序的整个执行过程中始终存在,但是在它作用域之外不能使用。

http://www.cnblogs.com/dongzhiquan/archive/2009/07/21/1994792.html

2. 单例模式

if (instance == null)        

    instance = this;

else if (instance != this)

    Destroy(gameObject);

如果GameManager类的实例instance为空,则把当前GameManager类的实例(当前物体)赋予instance,如果instance不是当前这个实例,就销毁当前这个物体(当前这个实例)。

如果现在生成了一个GameManager的实例a,静态变量instance则被赋予实例a,这时又生成了一个GameManager的实例b,这时在实例b中,instance就不等于this(this是实例b),于是实例b就会被销毁。

关于单例:

http://www.cnblogs.com/gameprogram/archive/2012/10/24/2736856.html

http://www.360doc.com/content/15/0418/20/12109864_464203821.shtml


3.DontDestroyOnLoad

DontDestroyOnLoad means that when we load a new scene, normally all of the game objects in the hierarchy will be destroyed. Because we want to use the GameManager to keep track of the score between scenes we don't want it to be destroyed at that point. And so we're going to use DontDestroyOnLoad to make sure that it will persist between scenes.

---

为什么需要单例模式?

为什么要用一个Loader来调用Game Manager?

这些都还不太懂

2016.08.07 @@ 朦胧地理解了全局静态变量和单例模式,GOOD!

传送门:Unity学习笔记 - Roguelike Tutorial(中)

你可能感兴趣的:(Unity学习笔记 - Roguelike Tutorial(上))