第一个Unity项目——Flappy Bird

Unity是什么:
它就是一个2D/3D编辑器,同时又是一个游戏引擎
游戏引擎:使用者只需要调用这些功能,而不需要重写实现这些功能

第一步:资源导入与资源处理

资源导入的方法:

  1. 在这里插入图片描述

  2. 直接将资源拖入Project面板

资源处理
2D游戏总的来说是依靠Sprites(图片精灵)

在这里插入图片描述
Sprite的类型
Default——默认纹理类型
Normal map——法线贴图资源
Editor GUI and Legacy ——用户界面的特图资源
Sprite——图片精灵
Cursor——鼠标光标
Cookie——光斑
Lightmap——光照贴图
Directional Lightmap——方向光贴图
Single Channel——单通道纹理

主角图片的创建
在这里插入图片描述
首先要将Single(单张图片) 变为Multiple(多张图片)
然后点击Sprite Editor 进行图片编辑
在这里插入图片描述
对图片进行分割
Automatic 自动
Grid By Cell Size 按照每一格像素切割
Gird By Cell Count 按照图片的数量切割

在这里插入图片描述
透明模式与颜色模式

场景创建

在这里插入图片描述
场景的层级关系
不同的图片处于不同的层级
Sorting Layer 层级的设置
Order in Layer 层级的优先级
1、
同一层级的图片,优先级越大,图片越处在前面

2、
在这里插入图片描述
添加新的图层,越在下的图层就越在前。

项目开始:快捷Ctrl+P

主角组件创建

在这里插入图片描述
增加组件

在这里插入图片描述
2D物理组件
2d
2D刚体

在这里插入图片描述
圆形碰撞器

场景组件创建

在这里插入图片描述
添加Colider(碰撞器)

在这里插入图片描述
编辑编辑器

第二步:添加代码脚本

设置代码编辑器:
在这里插入图片描述

在这里插入图片描述
常见的MonoBehaviour类的消息
在这里插入图片描述
快捷使用unity的各类方法(消息)
在这里插入图片描述
在这里插入图片描述

  1. 点击屏幕时,使Bird能够飞翔
  if (Input.GetMouseButtonUp(0))//Input为unity的一个类,调用这个类中的GetMouseButtonUp()的方法 ,检查鼠标是否按下。(0位左键,1为右键)
            {
                rb2d.velocity = Vector2.zero;//将速度设置为0,每一帧的速度都为0

                rb2d.AddForce(new Vector2(0, 360));//添加一个向上的力
            }

2.小鸟碰撞与死亡

   bool isDead=false;
    private void OnCollisionEnter2D(Collision2D collision)//碰撞检测
    {
        isDead = true;

    }

碰撞有三种状态
1、OnCollisionStay2D 碰撞进行
2、OnCollisionEnter2D 碰撞开始
3、OnCollisionExit2D 碰撞退出

思考题
1、Unity引擎是如何知道我们的脚本中没有写特定名字的方法的?又是如何调用的?
通过反射,查找特定的名字
通过反射直接调用该方法
2、能否将碰撞处理放在Ground对象上?

   private void OnCollisionEnter2D(Collision2D collision)
    {
        //collision.gameObject.GetComponent<SpriteRenderer>().enabled = false;//获得碰撞体的SpriteRenderer组件,并启用状态设为关闭

        collision.gameObject.GetComponent<Bird>().isDead = true;//将碰撞体的Bird组件的isDead设为ture
    }

3、一个对象A的子对象B发生1碰撞,A会不会收到碰撞信息

1、如果父节点和子节点都有Rigidbody,就相当于两个独立的物体,各自碰各自的。
2、如果父节点有Rigidbody,子节点没有,子节点相当于父节点的一部分,就看在谁的身上有响应的接口,在父节点有响应接口,父节点响应,子节点有接口,子节点响应,两者都有接口,父节点不会影响到子节点,但子节点响应会让父节点也响应。
3、如果父节点没有Rigidbody,子节点有,子节点会响应,父节点没有响应。

GameObject 和gameobject的区别

GameObject是Unity场景中所有实体的基类,是一个类型
gameobject是一个对象,就和this一样,指这个脚本所附着的游戏物体

第三步 动画创建

unity中的动画系统

1、选中游戏对象
在这里插入图片描述
2、创建动画并命名
在这里插入图片描述

在这里插入图片描述
动画控制器
在这里插入图片描述
游戏对象上Animator都会有一个动画控制器

在这里插入图片描述
动画片段

3、动画制作
打开动画片段后,选中游戏对象

进入动画编辑界面
在这里插入图片描述
开启记录关键帧,将图片拖入动画,将采样率设置为1,。
定位到第一秒中的位置
添加关键帧(keyframe)
最后停止记录关键帧

4、动画控制器设置
进入动画控制器中,建立各个动画之间的转换
在这里插入图片描述
添加两个触发器
在这里插入图片描述
在Idle转换Flap中,将触发器设置为转换的条件
Conditions:条件
在这里插入图片描述
然后通过代码进行控制

   Animator anim;
 anim = GetComponent<Animator>();
   anim.SetTrigger("Flap");

完成后发现动画播放比较慢,将
在这里插入图片描述
取消。
它的作用就是是否等待上一个动画播放结束。

将Idle与Flap相互联系,可以让Idle和Flap相互转换,但注意在Flap转换Idle时,要将Has Exit Time 勾上,以防止在长时间没有Flap下,可以让Flap自动转换为Idle。
在这里插入图片描述

第四步 UI设计

添加三个Text
分别是 Score、Gameover、HinText
用于显示分数、游戏结束、游戏提示

在这里插入图片描述

然后进行UI设计

在这里插入图片描述

Text:文本内容设置
Font :文本字体设置
Font Size :文本字体大小设置
Horizontal Overflow :水平溢出
Vertical Overflow:垂直溢出
Color:颜色

第五步:游戏逻辑控制器

添加一个空对象作为游戏逻辑控制器
在这里插入图片描述
然后增加一个游戏逻辑控制脚本

public class GameControl : MonoBehaviour
{
    bool gameOver = false;
    public GameObject gameovertext;//设置一个Hierarchy层的游戏对象
    public GameObject hintext;
    public GameObject scoretext;

    private GameControl()
    { }

    private static GameControl instance ;//游戏控制器一般只有一个,所以使用单例模式

    public static GameControl GetInstance()
    {
        if (instance == null)
        {
            instance = new GameControl();

        }
        return instance;
    }

    private void Awake()
    {
        instance = this;
    }

    void Start()
    {
        
    }

    void Update()
    {
        if (gameOver==true && Input.GetMouseButtonUp(0))
        {
            SceneManager.LoadScene("Main"); //加载场景
        }
        
    }

   public void  OnBirdDied()
    {
        gameOver = true;
        gameovertext.SetActive(true);//死亡后使Text显示处理
        hintext.SetActive(true);
    }
 
}

碰撞时调用上面的OnBirdDied()方法
Brid类
  private void OnCollisionEnter2D(Collision2D collision)//碰撞检测
    {
        isDead = true;//优先更改数据,再进行画面表现
        anim.SetTrigger("Die");
        GameControl.GetInstance().OnBirdDied();//调用方法

    }

同时注意要将代码中的字段与游戏物体相关联。
在这里插入图片描述

第六步 制作卷轴背景

方法一:通过动画实现
添加两个动画控制器,分别控制两个不同的背景进行滚动
在这里插入图片描述
在这里插入图片描述
注意动画播放的速度要改为匀速

方法二:通过代码控制

public class Scrolling : MonoBehaviour
{
    Rigidbody2D rb2d;
    float startPosx;//起始的位置
    float width;

    void Start()
    {
        rb2d = GetComponent<Rigidbody2D>();
        rb2d.velocity = new Vector2(-5, 0);
        width = GetComponent<BoxCollider2D>().size.x;
        startPosx = transform.position.x;


    }


    void Update()
    {
        if (GameControl.GetInstance().gameOver == true)
        {
            rb2d.velocity = Vector2.zero;//将卷轴停下
     
            return;
        }


        if (startPosx - transform.position.x >= width)//如果起始位置-现在的位置
        {
            Vector3 pos = transform.position;//trsnsfrom作为结构体,position属性无法直接赋值
            pos.x = startPosx;
            transform.position = pos;
        }


    }
}

第七步 添加障碍

在这里插入图片描述
将障碍设置为预制体,然后给障碍添加滚动的脚本。

在这里插入图片描述
在原有的scrolling脚本上修改。

public 让外界可以控制障碍回头的距离,方便与其他有相同的游戏物体区分。
if(width==0) 是让与障碍相同的脚本的游戏物体可以共用脚本。


注意:
要将刚体组件设置为Kinematic.,让游戏物体不受物理影响

在这里插入图片描述

第八步 通过障碍加分

在这里插入图片描述

在预制体中,给障碍添加一个得分的碰撞器,然后将碰撞器改为 Trigger触发器的模式

代码

Control类

  public GameObject scoretext;
    int score = 0;
  public void OnScore()
    {
        score += 10;
        scoretext.GetComponent<Text>().text = string.Format("Score:{0}", score);
    }

Bird类

  private void OnTriggerExit2D(Collider2D collision)//触发检测
    {
        GameControl.GetInstance().OnScore();
    }

第九步 动态生成障碍

在这里插入图片描述
添加两个空节点Upper 和Lower 作为最小上界 和最小下界

代码

public class Spawner : MonoBehaviour
{//Spawner 生成者

    public GameObject gamePrefab;
    public GameObject lowerbound;
    public GameObject upperbound;

    public float interval = 4f; //时间间隔
    void Start()
    {
        InvokeRepeating("Spawn",interval,interval);//Invoke:调用 Repeating:重复 //4秒已后,每隔4秒,重复执行“Spawner”方法
        
    }
    void Spawn()
    {
        //GameObject column = new GameObject();
        //column = gamePrefab;

       GameObject column=  Instantiate(gamePrefab);//根据预制体实例化一个对象
        column.transform.position = Vector3.Lerp(lowerbound.transform.position,upperbound.transform.position,Random.Range(0f,1f));

        
    }


    void Update()
    {
        
    }
}

定点消除障碍
Scrolling类

  public bool destory = false;
    if (startPosx - transform.position.x >= width)//如果起始位置-现在的位置
        {
            if (destory == true)//将destory勾上,就可以执行到这
            {
                Destroy(gameObject);
            }
            else
            {
            Vector3 pos = transform.position;//trsnsfrom作为结构体,position属性无法直接赋值
            pos.x = startPosx;
            transform.position = pos;
            }
            
          
        }

注意在预制体中
在这里插入图片描述
因为要执行到destory。

补充 对象池的使用

动态生成障碍,会造成内存碎片。

代码

ColumnPool类

public class ColumnsPool : MonoBehaviour
{
   public int poolsize = 100;

    public GameObject gamePrefab;
    public GameObject lowerbound;
    public GameObject upperbound;
    public float interval = 4f; //时间间隔

    public Queue<GameObject> pools;

    public static ColumnsPool instance;

    private void Awake()
    {
        instance = this;
    }


    void Start()
    {
        pools = new Queue<GameObject>();
        for (int i = 0; i < poolsize; i++)//实例化一百个柱子,将其设为关闭。然后入队
        {
            GameObject column = Instantiate(gamePrefab);
            column.SetActive(false);
            pools.Enqueue(column);
        }
        InvokeRepeating("Spawn", interval, interval);

    }

    void Spawn()//栈内的柱子预制体出队,将其启动,然后柱子在上界和下界取随机值,生成不同的柱子。
    {
        GameObject column = pools.Dequeue();
        column.SetActive(true);
        column.transform.position = Vector3.Lerp(lowerbound.transform.position, upperbound.transform.position, Random.Range(0f, 1f));

    }
    public void Despawn(GameObject go)//将柱子关闭并重新入队
    {
        go.SetActive(false);
        pools.Enqueue(go);
    }

}

Scrolling类调用Despawn方法

   ColumnsPool.instance.Despawn(this.gameObject);

对象池的好处:在生成一个固定的游戏物体时,可以减少不断重复实例化带来的内存碎片。
实质:利用队列先进先出的特性,使障碍一直保持固定的数量,不增加内存的消耗。

  • 27
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值