1、Unity3D项目学习笔记(1)- 2D Roguelike Tutorial

来源:互联网 发布:sql找不到存储过程 编辑:程序博客网 时间:2024/06/12 20:49

游戏介绍:玩家控制一个2D帧动画人物在地图上行走,目标是到达出口,进入下一关。途中会有食物、敌人和障碍物。玩家每进行一个动作都会销耗食物,靠近敌人会攻击玩家,可以摧毁障碍物。食物耗尽时游戏结束。

1、游戏组件

1.1、帧动画 Animation

这个游戏是简单的帧动画,美术资源已按固定大小准备好每一帧的动画。

  • 选中动画的所有帧,拖动到GameObject中会生成相应的Animation文件和配套的AnimationController。
  • Animation包括闲置动画、攻击动画和被攻击动画(Idle、Attack、Damage)

    • 当Trigger.Attack触发时,Idle立即转为Attack,Attack播放完后回到Idle。
    • 当Trigger.Damage触发时,Idle立即转为Damage,Damager播放完后回到Idle
  • 通过Override Controller使不同的敌人共用一个AnimationController,但播放不同的动画。


1.2 渲染层 SpriteRenderer.SortingLayer

游戏中渲染层有Background、Items、Units(可以自己添加)。渲染层低的物体绘制比较晚,所以会遮挡渲染层高的物体。

  • Backgound 放置背景(Floot、OutWall)等无需交互的物体。
  • Items 放置物品(Food、Suda)等需要交互的物体。
  • Units 放置角色(Player、Enemy)等会行动的角色。

1.3 行走和碰撞检测 Rigidbody and BoxCollider

添加BlockLayer层,为Player、Enemy、Wall等所有碰撞检测(BoxCollider)都将在这个层中进行。

  • Player和Enemy等需要运动的角色,设置为Kinematic Rigidbody,即可以通过物理系统移动,但不会收到环境力影响。
  • 将Player和Enemy等需要和环境交互的单位,其碰撞器尺寸(BoxCollider.size)设置为0.9,防止角色移动时与周围环境发生不必要的碰撞。
  • 将Exit和Food等物体设置为触发器模式(IsTrigger),不会产生物理碰撞效果。

1.4 界面(UI)

界面包括DayImage和FoodText

  • DayImage显示当前天数,只在玩家进入每个关卡前出现,1秒后消失。
  • FoodText显示玩家当前食物数量,并在每次食物变化时出现改变的值(停留0.5秒)。

1.5 声音(AudioSource)

背景音乐循环播放。
音效包含玩家移动、攻击、受伤、拾取食物和死亡,敌人攻击等。通过AudioManager脚本统一控制。


2、代码结构

2.1 游戏管理类

2.1.1 GameManager(游戏管理类)

单例模式 Singleto

    - 通过DontDestoryOnLoad(this),使自己不会在关卡开始时被销毁、重置。    - 在Awake()中进行游戏的初始化(包括重新生成地图)    - 在MainCamera上的脚本中建立Singleto。

初始化游戏 InitGame()

    - 调用MapManager.InitMap()随机生成地图。    - 重新初始化当前UI。    - 清空上一关卡中的敌人List。

管理敌人 EnemyList

    - 在敌人生成后加入EnemyList统一管理。    - 协程EnemyMove()让敌人按一定顺序移动。

管理地图

  • OnLevelWasLoaded(int level)已停用,用OnSceneLoad(Scene scene, LoadSceneMode sceneMode)代替。
  • 删除Awake()中的InitGame(),InitGame()仅在OnSceneLoad()中使用。

    private void OnDisable() {    SceneManager.sceneLoaded -= OnSceneLoaded;}private void OnEnable() {    SceneManager.sceneLoaded += OnSceneLoaded;}void OnSceneLoaded(Scene scene, LoadSceneMode mode) {    level++;    InitGame();    Debug.Log("当前第" + level + "天");    Debug.Log("饥饿:" + hunger);}

    2.1 MapManager(地图管理类)

    //生成地图范围for (int x = 2; x < cols - 2; x++) {    for (int y = 2; y < rows - 2; y++) {        positionList.Add(new Vector2(x, y));    }}//随机生成一个游戏交互物private void RandomInstantatePrefab(GameObject[] prefabs) {    //随机生成位置    int positionIndex = Random.Range(0, positionList.Count);    Vector2 position = positionList[positionIndex];    positionList.RemoveAt(positionIndex);//该位置已存在物体(即将),移除该位置    //根据位置,随机生成一个一个物体    int index = Random.Range(0, prefabs.Length);    GameObject gameObject = Instantiate(prefabs[index], position, Quaternion.identity) as GameObject;    gameObject.transform.SetParent(mapHolder);}

2.2 角色类

Player和Enemy类使用,通过RaycastHit2D检测前方的物体。

//移动mRigidbody.MovePosition(Vector2.Lerp(transform.position, mTargetPosition, speed * Time.deltaTime)); 、//...mCollider.enabled = false;//防止射线击中自己RaycastHit2D hit = Physics2D.Linecast(transform.position, mTargetPosition + new Vector2(h, v));//发射射线检测mCollider.enabled = true;if(hit.transform == null) { //说明前方无障碍物    //前进} else {     switch (hit.collider.tag) {         case  "Wall"://前方是障碍物            //攻击             break;         //...     }}

2.3 其他类

  1. Wall类

     public Sprite damageSprite;//受到攻击后的图片 //通过替换图片来达到显示破损状态 GetComponent<SpriteRenderer>().sprite = damageSprite;//收到攻击后,替换图片
原创粉丝点击