赞
踩
一、创建游戏工程导入游戏素材
二、创建游戏主角及敌人的预制
1、将主角Idle动画的Sprite一起拖入Hierarchy面板,会生成一个主角,同时会生成主角的Player Controller(动画控制器)和PlayerIdle动画,将其他动画分别拖到Player上会生成各自的Animation。
2、敌人创建方法同理,但由于存在多个不同的敌人,它们之间动画相同,只是Sprite不同,所以后面的敌人可以重写第一个创建的敌人时生成的动画控制器,再使用自己的动画。
三、游戏素材中其他素材(如墙、食物、地板、障碍物等)可以直接做成Prefab。
四、游戏地图的生成
这个游戏地图是10*10的大小,围墙和地板两种不同的GameObject,刚好使用两个for循环来生成地图(循环的嵌套)。
五、控制障碍物、食物、敌人的随机生成
1、在围墙边应留一行通路,确保玩家能通过,在剩下中间的位置来生成障碍物。
2、障碍物生成的个数的位置都应该是随机的,因此可以同样用两个for循环遍历所有能生成障碍物的位置,放入一个List列表,然后随机取出一个位置随机放入一个障碍物(注意:取出位置后要把这个位置从List移除)。
3、对于食物和敌人,可以使用同样的方法去实例化,而且在生成障碍物时已经遍历了位置,可以直接使用。
六、完善主角和敌人的动画状态机
1、添加动画切换条件
2、关于状态机的一些参数
如果有切换动画条件Condition,一般不勾选Has Exit Time,由条件控制动画的切换;如果没有Condition,则勾选Has Exit Time表示在什么时候切换动画,下面Settings-->Exit Time值(0到1)来表示切换时间,它是一个百分比的值,1代表动画播放完切换。
2d游戏的动画时帧动画,可以将Transition Duration值设为0。
七、控制主角的移动
1、首先在player上添加Rigidbody2D(不需要重力)和BoxCollider2D组件。
2、使用Rigidbody2D上的MovePosition方法插值Verctor2.Lerp()。
3、由于实在Update方法中移动player的,可能按下方向键时player每帧都会移动,为了避免player移动过快,可以设置一个休息时间。
八、控制主角对墙体的攻击
1、将所有的墙设置一个tag标签,由于围墙不能攻击,只有里面的墙才能攻击,只需给内墙添加被攻击的方法。
2、2D游戏的射线检测:Physical.Linecast()返回一个RaycastHit2D的对象,如果返回的这个对象不为空,通过tag标签判断如果是内墙就可以攻击。
注意:player在发射射线时,可能检测到自身的collider,因此在检测之前要禁掉自己的collider,检测之后在恢复。
3、通过SendMessage通知碰撞到的墙调用被攻击的方法。
4、在显示内墙被攻击的状态时,可以修改SpriteRenderer组件的sprite。而主角的攻击动画直接用Animator的SetTrigger方法。
九、控制主角吃食物
与攻击墙体的方法差不多,只是食物的collider为触发器,食物在被吃掉后主角的食物量会增加,在Destroy食物时有些信息不能被Destroy,因此可以将吃食物的逻辑放在GameManager中(像这种管理类一般可以使用单例模式)。
十、控制敌人的移动和攻击
1、给敌人添加Rigidbody2D和BoxCollider2D组件,敌人之间、敌人和Player之间碰撞可能会导致旋转,因此将敌人和Player的Rigidbody2D组件的Constraints的旋转锁定。
2、敌人的移动和Player一样使用插值,判断当前位置和目标位置的距离,Vector2中的magnitude返回两个位置的向量的长度。
3、Player移动两步,敌人移动一步,所以敌人移动的方法可以在GameManager中调用,在GameManager中,使用List集合来存放所有的敌人。
4、第2步里判断magnitude小于1.1(1是临界值)时,攻击玩家。
十一、控制食物数量和游戏失败UI的显示
通过一个更新Text的方法在每次食物数量变化时调用来显示食物数量。
十二、游戏关卡胜利的判断和加载
1、当Player的下一个目标位置是终点时,加载下一关SceneManager.LoadScene(0)。
2、系统函数OnLevelWasLoaded()实现关卡数的增加以及地图和UI的初始化。
十三、控制天数UI的显示
Invoke("HideBlack",1)方法等待1秒调用HideBlack方法。
十四、添加音效
随机播放音效,音效播放速度也随机。
单独在一个类中写音效的播放,做成单例模式,带参数数组的方法。
- using UnityEngine;
-
- public class AudioManager : MonoBehaviour
- {
-
- private static AudioManager _instance;
-
- public static AudioManager Instance
- {
- get { return _instance; }
- }
-
- public AudioSource audioSource;
- public AudioSource BGMusic;
- private float minPitch = 0.9f;
- private float maxPitch = 1.1f;
-
- void Awake()
- {
- _instance = this;
- }
-
- public void RandPlay(params AudioClip[] audios) //参数数组
- {
- float pitch=Random.Range(minPitch,maxPitch);
- int index=Random.Range(0,audios.Length);
- AudioClip clip = audios[index];
- audioSource.clip = clip;
- audioSource.pitch = pitch;
- audioSource.Play();
- }
-
- public void StopBGMusic()
- {
- BGMusic.Stop();
- }
- }
参数数组和数组参数的不同在于函数的调用,调用参数数组的函数时,我们可以传递过来任意多个参数,然后编译器会帮我们自动组拼成一个数组;调用数组参数的时候,那个数组我们要自己手动创建。(参数数组就是帮我们减少了一个数组的创建过程)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。