Unity开发2d游戏全套教程
官方手册:https://docs.unity.cn/cn/2023.2/Manual/class-EdgeCollider2D.html
项目素材地址(Github),欢迎star:
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/unity-demo/SnakeRun
- 本期只演示最基本的操作,大家可以在这个基础上进行修改,比如添加背景或者添加音乐
环境准备:下载Unity
- 下载Unity
进入官网,选择对应操作系统、对应版本下载即可
我这里是mac,直接下载最新长期支持版的mac即可:
也可以直接下载Unity Hub,从Unity Hub中安装

下载好后,根据自己后续游戏开发的必要,下载对应的扩展包,但需要勾选WebGL Build Support,因为我们后续会将游戏打包为Web发布到网站上。

- 下载.net环境
游戏开发语言使用C#,所以需要准备.net环境。
创建项目
我们开发的是2D游戏,这里选择2D游戏模板

实战开发
场景搭建+实现小蛇跳跃
1. assets中导入角色与背景图片
2. 创建Snake物品,create empty

3. 给这个Snake物品添加一个sprite renderer,将小蛇图片拖入其中,按住shit键可以等比例缩放小蛇
相当于我们这里用这个小蛇图片进行渲染


4. 调整渲染图颜色及物体大小

5. 点击播放,查看效果

效果:

6. 给Snake这个物品添加Rigidbody 2D重力,让其实现自然坠落

7. 添加C#脚本代码,实现Snake跳跃操作

            
            
              csharp
              
              
            
          
          using UnityEngine;
public class SnakeController : MonoBehaviour
{
    //每次跳动的高度
    public float jumpForce = 5f;
    private Rigidbody2D rb;
    public GameObject gameOverPanel;
    private bool isGameOver = false;
    public float upperLimit = 1000000000f; // Set this to the top of your screen
    public float lowerLimit = -1000000000f; // Set this to the bottom of your screen
    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    private void Update()
    {
        if (isGameOver) return;
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Jump();
        }
    }
    private void Jump()
    {
        rb.linearVelocity = Vector2.up * jumpForce;
    }
}运行游戏查看效果

创建障碍物+实现物体碰撞
1. 创建空物品Barrier,在下面分别创建topBarrier、bottomBarrier
分别给topBarrier、bottomBarrier添加Sprite Renderer,并调整物品页面布局

点击运行游戏,查看效果:

2. 添加C#脚本,让障碍物实现向左移动(从视觉上实现小蛇向右移动)

            
            
              csharp
              
              
            
          
          using UnityEngine;
public class BarrierController : MonoBehaviour
{
    public float speed = 2f;
    public float lifetime = 10f;
    private void Start()
    {
        //实现超出范围后,销毁多余的障碍物
        Destroy(gameObject, lifetime);
    }
    private void Update()
    {
        MoveLeft();
    }
    private void MoveLeft()
    {
        //向左移动障碍物
        // Debug.Log("move left....");
        transform.Translate(Vector2.left * speed * Time.deltaTime);
    }
}
效果:

3. 给小蛇、障碍物都添加collider,实现碰撞效果
障碍物、小蛇添加:Box collider 2D
- 因为障碍物、小蛇类似正方体,所以添加box collider更合理。当然大家也可以根据自己角色进行调整
给障碍物添加collider:
小蛇同理

效果:

4. 解决碰撞后,翻滚问题
目前小蛇和障碍物碰撞后,小蛇会翻滚

解决:调整小蛇的rigidbody 2d属性,冻结Z方向

效果

脚本实现障碍物自动随机生成
目前游戏场景中的障碍物是我们自己手动拖进去的,如果要添加多个障碍物肯定不能由我们手动去操作。这里我们可以通过C#代码实现自动生成。
1. 在Assets目录下新建Prefab文件夹,用于存储我们的复制品
2. 将Barrier拖到Prefab文件夹中,这样Barrier就成了复制品,然后我们就可以删除场景里的Barrier了
如果我们想要Pipe,直接到Asset目录下的Prefab文件夹下拖动Pipe即可,想要多个就拖动多个。优化:后续会采用代码来实现自动生成

3. 新建BarrierSpawner物品,并添加BarrierSpawner脚本实现自动生成障碍物

            
            
              csharp
              
              
            
          
          using UnityEngine;
public class BarrierSpawner : MonoBehaviour
{
    public GameObject barrierPrefab;
    public float spawnDelay = 2f;
    public float minSpawnHeight = -2f;
    public float maxSpawnHeight = 2f;
    private void Start()
    {
        //重复调用函数,实现物品复制重复创建
        InvokeRepeating("SpawnBarrier", 0f, spawnDelay);
    }
    private void SpawnBarrier()
    {
        float randomHeight = Random.Range(minSpawnHeight, maxSpawnHeight);
        Vector2 spawnPosition = new Vector2(transform.position.x, randomHeight);
        Instantiate(barrierPrefab, spawnPosition, Quaternion.identity);
    }
}效果

实现加分机制
当小蛇通过一个障碍物时,我们应该实现加分,实现思路:
在上下两个障碍物之间添加trigger,当小蛇通过后,触发trigger,执行加分函数
1. Barrier下添加scoreCheck,scoreCheck添加box collider 2d,并勾选Is Trigger

2. 添加ScoreManager物品,同时添加ScoreManager代码
ScoreManager.cs:
            
            
              csharp
              
              
            
          
          using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI; 
public class ScoreManager : MonoBehaviour
{
    public static int score = 0;
    public Text scoreText;
    private void Update()
    {
        // Update the text field with the current score
        //scoreText.text = score.ToString();
    }
    
    // public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
    // {
    //     SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    //     score = 0;
    // }
}SnakeController.cs代码中添加分数逻辑:

3. 新增Canvas物品,添加分数面板展示分数

4. 添加Text展示分数

5. 调整页面分数字体大小、颜色等

6. ScoreManager.cs添加分数展示逻辑,并将Score Text文字展示框拖动到ScoreManager物品下
            
            
              csharp
              
              
            
          
              private void Update()
    {
        // Update the text field with the current score
        scoreText.text = score.ToString();
    }
效果

实现游戏结束逻辑
1. Canvas下添加Panel,并调整页面展示位置与大小

2. GameOverPanel下添加Text与Button,提示游戏结束与重新开始按钮
UI - Legacy - Text
UI - Legacy - Button
效果:


3. 隐藏游戏结束页面,当触发碰撞💥条件时,游戏才结束

SnakeController.cs中新增游戏结束逻辑:
            
            
              csharp
              
              
            
          
              //当snake与Barrier相撞时,游戏结束
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Barrier"))
        {
            // Game over
            GameOver();
        }
    }
    private void GameOver()
    {
        isGameOver = true; // Add this line
        // Freeze the Snake's motion
        rb.linearVelocity = Vector2.zero;
        if (gameOverPanel != null)
        {
        	//展示游戏结束页面
            gameOverPanel.SetActive(true);
        }
    }SnakeController.cs全部代码:
            
            
              csharp
              
              
            
          
          using UnityEngine;
public class SnakeController : MonoBehaviour
{
    //每次跳动的高度
    public float jumpForce = 5f;
    private Rigidbody2D rb;
    public GameObject gameOverPanel;
    private bool isGameOver = false;
    public float upperLimit = 1000000000f; // Set this to the top of your screen
    public float lowerLimit = -1000000000f; // Set this to the bottom of your screen
    //public AudioSource jumpSFX;
    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }
    private void Update()
    {
        if (isGameOver) return;
        // Check if Snake is out of bounds【小蛇超出页面也触发游戏结束】
        // if (transform.position.y > 50f || transform.position.y < -50f)
        // {
        //     //Debug.Log(transform.position.y);
        //     GameOver();
        // }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Jump();
        }
    }
    private void Jump()
    {
        rb.linearVelocity = Vector2.up * jumpForce;
        //jumpSFX.Play();
    }
    //与Trigger部分碰撞时,触发分数加操作
    private void OnTriggerEnter2D(Collider2D collision)
    {
        // if (isGameOver) return; // Add this line
        //Debug.Log("Score: " + ScoreManager.score);
        ScoreManager.score++;
    }
    //当snake与Barrier相撞时,游戏结束
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Barrier"))
        {
            // Game over
            GameOver();
        }
    }
    private void GameOver()
    {
        isGameOver = true; // Add this line
        // Freeze the Snake's motion
        rb.linearVelocity = Vector2.zero;
        if (gameOverPanel != null)
        {
        	//展示游戏结束页面
            gameOverPanel.SetActive(true);
        }
    }
}4. SnakeController中添加游戏结束Panel

5. 为障碍物添加Barrier标签
因为c#代码中是通过Barrier Tag来判断

给topBarrier、bottomBarrier分别添加tag:



效果

实现重玩逻辑
给游戏结束页面的[重新开始]按钮绑定事件,点击时,触发游戏重新开始
1. ScoreManager.cs新增重玩逻辑代码:
            
            
              csharp
              
              
            
          
          //游戏重新开始,分数清零,重新加载游戏场景
public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
{
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    score = 0;
}ScoreManager.cs全部代码:
            
            
              csharp
              
              
            
          
          using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI; 
public class ScoreManager : MonoBehaviour
{
    public static int score = 0;
    public Text scoreText;
    private void Update()
    {
        // Update the text field with the current score
        scoreText.text = "Score:" + score.ToString();
    }
    //游戏重新开始,分数清零,重新加载游戏场景
    public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        score = 0;
    }
}2. GameOverPanel下的Button绑定重新开始逻辑

效果

游戏打包
1. File - Build Profile

2. 选择打包参数
因为我们这里是打包发布到web服务器上,所以这里直接选择web,然后点击切换平台

3. 修改压缩参数,改为gzip或不压缩
因为Brotli 在http上不支持压缩,改成G-zip或不压缩


4. 点击Build打包游戏,然后选择打包后文件存放位置

游戏上线(itch.io)
itch.io可以算是全球最大的独立游戏平台。它和steam一样,你可以把你的游戏上架到itch上,可以是免费的,也可以让大家捐赠,也可以让大家付费购买。
- 
注册账号之后,创建项目: 
  
- 
填写游戏基本信息 
  
- 
填写完后选择save,保存为draft(第一次只能保存为草稿) 
  
- 
保存完后,点击项目,改为public,表明游戏公开,然后就可以把体验链接发给其他人体验了 
本地运行游玩
打包后的游戏,有两个文件夹(Build、TemplateData),一个文件(index.html)

            
            
              python
              
              
            
          
          # 本地运行项目:可以通过python直接起http服务,也可以下载nginx或Tomcat等
# 9999指定运行端口
# --directory 指定unity打包后的路径
python3 -m http.server 9999 --directory /Users/ziyi/Desktop/ZiyiSnakeRun
浏览器访问localhost:9999
效果:

全部代码地址(资源文件地址)
Github(欢迎star~):https://github.com/ziyifast/ziyifast-code_instruction/tree/main/unity-demo/SnakeRun
