资讯动态

Unity零基础开发2D贪吃蛇游戏完整教程

发布时间:2026/10/17 6:10:14 来源:尧图企业网站定制
哪个男孩手里没攥过一个“哪天我也做个游戏”的念头但大多数人卡在了“不知道从哪开始”这一步。我用Unity做的第一个完整小项目就是贪吃蛇2D。这个项目几乎是为零基础量身定制的不需要美术功底不需要复杂的数学C#虽然是一门编程语言但贪吃蛇用到的语法就那么几行做完之后你会把Unity里最核心的几个概念全部过一遍场景、物体、组件、预制体、输入、碰撞、UI。不管拿它当练手项目还是想先跑通一次完整的游戏开发流程都很合适。这篇博文就从完全零基础出发手把手带着你做一版能玩、能计分、能重开、能拿去给同学朋友炫耀的贪吃蛇。我尽量把每一步为什么这样做讲清楚而不是只让你对着教程抄代码。做完这个项目你会发现后面再做任何小游戏的信心都已经攒起来了。1. 动手前的准备装好Unity并搞懂三个关键概念1.1 Unity Hub装哪个版本选LTS版本别追新去Unity官网下载Unity Hub然后通过Hub安装Unity编辑器。版本选择上我建议直接选最新的LTS长期支持版本别选带“beta”或者刚发布的“最新版”。LTS的意思是官方会持续维护修复的稳定版本很多线上教程和社区资源也基于LTS遇到问题好查答案。版本太新反而可能碰到教程里没提到的情况零基础阶段少一点变量就少一点烦恼。安装界面里记得勾选2D模板或者叫2D URP模板它会自动把编辑器的默认工作环境设置成2D模式相机默认是正交投影新建的Sprite会直接铺在视野中央。如果你选的是3D模板再做2D也不是不行但视角、光照都要手动调没必要给自己加难度。1.2 场景、GameObject、组件Unity世界的三个基石零基础最容易懵的就是Unity里一堆窗口和名词。其实Unity的世界观可以用一个生活场景来解释整个游戏相当于一部舞台剧场景Scene就是舞台本身舞台上有多少个演员、多少件道具都在Hierarchy窗口里列着每个演员或道具就是一个GameObject游戏对象。而GameObject本身是空的它之所以能显示成方块、能播放声音、能移动是因为挂在上面的组件Component。比如你创建一个“蛇头”GameObject给它挂上SpriteRenderer组件它就能显示成一个方块再挂上Collider2D组件它就有了“碰撞体积”再挂上一个自定义的脚本组件它就有了行为逻辑。也就是说GameObject是身体组件是装备脚本是大脑。预制体Prefab也顺便讲一下因为贪吃蛇的蛇身会大量用到它。预制体相当于一个“模具”你先做好一节蛇身存成预制体之后所有新增的蛇身都是用这个模具复制出来的。改模具所有复制出来的实例一起跟着变这在开发里省了太多事。1.3 第一次新建项目和认识编辑器界面打开Unity Hub新建项目模板选2D项目名字我用的Snake2D保存路径随意。创建完成进入编辑器后你会看到几个主要窗口中间最大的Scene窗口用来摆放物体右上角是Game窗口运行时显示画面左边有Hierarchy和Project等面板右边是Inspector用来查看和修改选中物体的组件属性。第一次进来可以随便点击Scene里的物体再观察Inspector里组件参数的变化熟悉“选中-修改”这个基本交互模式。另外记得在Scene窗口顶部把2D开关打开这样场景会以平面视角显示方便摆2D的东西。这些不一次性全弄懂也没关系用到什么学什么但上面三个核心概念场景、GameObject、组件是后面所有操作的底层逻辑。2. 核心设计思路动手写代码之前先想清楚蛇是怎么动的2.1 蛇的身子怎么存用List管理每一节很多人一上来就急着写移动代码结果写出来的蛇要么自己没有身体要么身体追不上头。先想数据结构。贪吃蛇本质上是一条由若干节组成的链每一节在网格上占据一格位置。蛇吃到一个食物身体末尾会长出一节正常情况下每走一格前面出来一个新位置后面丢掉尾巴那一节。在C#里最合适的就是List列表。因为数组长度一旦声明就固定了而蛇的长度是不断变化的。我用了两个List一个存所有身体节点的Transform方便每帧同步位置另一个存每一节的“历史网格坐标”用来计算新位置。核心操作就是每一拍把新蛇头位置插入列表头部如果没吃到食物就把列表尾部的旧节点删掉这两步做完蛇就完成了一次前进。2.2 移动方式用时间间隔控制步伐而不是每帧都动如果让蛇每帧都移动一次画面刷新率是60帧每秒蛇会快得看不清。真正贪吃蛇的移动方式是按“拍”前进每隔一小段时间往前挪一格。这个间隔决定了游戏难度经典贪吃蛇大概是一拍0.15秒左右。具体实现不需要用复杂的物理系统。在Update函数里用一个计时器每帧累加Time.deltaTime这一帧过去了多少秒当累加值超过移动间隔时执行一次“走一步”的动作然后把计时器归零。这种移动方式和帧率无关不管游戏跑在30帧还是120帧蛇的节奏都是一致的。2.3 场景怎么搭直接摆Sprite而不是用Tilemap搭建游戏区域有两种思路。一种是用Tilemap瓦片地图画背景格子和墙优点是地图清晰、扩展方便但零基础要先学Tilemap工具学习曲线陡。另一种是直接用Sprite精灵图片摆出边界和蛇身这更接近“用积木搭房子”的思路代码也直观。我做第一版时用的就是后一种跑了没几天就上手了。关键设计定下来每个方块边长0.5单位蛇头的Sprite长宽都设为0.5移动步长就是0.5。食物也按0.5的整数倍坐标生成。整个游戏区域比如由四面墙围成一个矩形玩家需要在这个区域里控制蛇移动。3. 一步步实现从空场景到能玩的贪吃蛇3.1 搭建场景摄像头、背景、墙和蛇头新建项目里自带一个Main Camera。把Scene背景设置成深色比如深蓝黑色这样灰色地板和白色蛇身对比明显。这个背景其实是相机视图的固有色不参与游戏逻辑纯粹为了好看。然后创建四个墙在Hierarchy里右键创建一个2D Object - Sprite选择一张纯色的方形Sprite。把四个墙分别移动到游戏区域的上、下、左、右边界颜色用深灰色。为了检测碰撞给每面墙挂BoxCollider2D这里不需要勾IsTrigger因为撞墙就是要触发游戏结束。接着做蛇头。新建一个Sprite对象挂SpriteRenderer颜色白色尺寸0.5×0.5再加BoxCollider2D并勾选IsTrigger这样蛇头碰到食物时能触发检测同时自身不会把食物“推走”。别忘了添加Rigidbody2D类型选Kinematic运动学刚体。这是很多人漏掉的2D触发器要正常工作两个碰撞体里至少有一个物体带Rigidbody2D。蛇头作为主动移动的一方加Kinematic刚体最合适。3.2 创建预制体蛇身和食物都从预制体生成蛇身的预制体和蛇头长得一样只是颜色稍浅一点碰撞体和刚体逻辑相同。把做好的蛇身拖到Project窗口里生成一个预制体资源。食物也做成一个预制体红色方块。这里有个小技巧给食物加上BoxCollider2D并勾选IsTrigger标签Tag设为“Food”蛇头撞上去时通过标签判断这是食物而不是墙。预制体的好处在这一刻就体现出来了蛇吃到食物要加长我们Instantiate一个预制体就行食物被吃掉要换位置也只是移动那一个食物实例不用新建销毁。整个游戏里我们一直复用这两个预制体。3.3 蛇的移动与方向控制核心脚本Snake.cs现在写真正的移动脚本。思路已经很清楚方向用一个Vector2表示每拍走一步。在Update里读取上下左右键并做180度掉头保护如果当前方向是向右就不能直接按左键否则蛇会一头扎进自己身体。这个保护极其重要不做的话第一次玩就会原地自噬。using System.Collections.Generic; using UnityEngine; public class Snake : MonoBehaviour { public GameObject segmentPrefab; // 蛇身预制体 public float moveInterval 0.15f; // 每拍移动间隔 public float stepLength 0.5f; // 每格边长也是移动步长 private ListTransform segments new ListTransform(); private Vector2 direction Vector2.right; private Vector2 nextDirection Vector2.right; private float playTimer; private int growthNeeded; // 待增长节数 void Start() { segments.Add(transform); // 蛇头就是挂脚本的物体本身 } void Update() { // 读取输入且禁止向当前方向的相反方向掉头 if (Input.GetKeyDown(KeyCode.UpArrow) direction ! Vector2.down) nextDirection Vector2.up; else if (Input.GetKeyDown(KeyCode.DownArrow) direction ! Vector2.up) nextDirection Vector2.down; else if (Input.GetKeyDown(KeyCode.LeftArrow) direction ! Vector2.right) nextDirection Vector2.left; else if (Input.GetKeyDown(KeyCode.RightArrow) direction ! Vector2.left) nextDirection Vector2.right; playTimer Time.deltaTime; if (playTimer moveInterval) { playTimer 0f; MoveOneStep(); } } void MoveOneStep() { direction nextDirection; Vector3 newHeadPos segments[0].position (Vector3)(direction * stepLength); GameObject newNode Instantiate(segmentPrefab, newHeadPos, Quaternion.identity); segments.Insert(0, newNode.transform); if (growthNeeded 0) { growthNeeded--; } else { Transform tail segments[segments.Count - 1]; segments.RemoveAt(segments.Count - 1); Destroy(tail.gameObject); } } public void Grow() { growthNeeded; } }这里的核心逻辑就是MoveOneStep方法先在头部前方插入一节新身体如果没吃到食物就把尾巴删掉。这样蛇的光是“整体前进了一格”而不是散得到处都是。用List而不是数组就是为了方便这种插入和删除这也是List相对数组的核心优势。3.4 食物的生成与吃到食物的判定食物逻辑单独写一个Food脚本。在Start或“被吃后重生”时调用RandomPosition方法void RandomPosition() { float x Random.Range(-8.5f, 8.5f); float y Random.Range(-4.5f, 4.5f); x Mathf.Round(x * 2f) / 2f; // 0.5整数倍 y Mathf.Round(y * 2f) / 2f; transform.position new Vector2(x, y); }这里有个特别容易踩的坑如果直接让食物坐标随机在(-8.5f, 8.5f)生成的坐标可能带小数点后很多位蛇的步长是0.5可能永远对不齐。所以务必用Mathf.Round把坐标取成0.5的整数倍。做完全局对齐后蛇头只要到了食物所在的格子就能吃到了。蛇头吃到食物的检测可以在Snake脚本里加OnTriggerEnter2Dvoid OnTriggerEnter2D(Collider2D other) { if (other.CompareTag(Food)) { Grow(); score; other.GetComponentFood().RandomPosition(); // 更新UI分数 } else if (other.CompareTag(Wall)) { GameOver(); } }3.5 撞自己身体的判定别漏掉这个撞墙会死很多新手做了。但撞自己身体也会死这个经常被忽略。判定方法有很多对零基础最直观的就是每走一步之后遍历segments列表里除了蛇头以外的所有节点比较它们的位置和蛇头位置是否重合。因为所有位置都是0.5整数倍精度可控直接用比较即可。bool HitSelf() { Vector2 headPos segments[0].position; for (int i 1; i segments.Count; i) { if ((Vector2)segments[i].position headPos) return true; } return false; }这段代码放在MoveOneStep之后调用一旦发现自撞就进入游戏结束流程。3.6 分数UI和重新开始在场景里创建一个Canvas右键UI - Text即可。把得分Text拖到Snake脚本的public字段上在吃到食物后更新text.text 得分 score。游戏结束时显示一个“游戏结束按R重新开始”的文字然后设置Time.timeScale 0f暂停游戏。重新开始时调用SceneManager.LoadScene重载当前场景并把Time.timeScale恢复为1。零基础只要记住Time.timeScale是全局时间缩放设成0游戏就暂停了。using UnityEngine.SceneManagement; void GameOver() { Time.timeScale 0f; gameOverText.gameObject.SetActive(true); } void Update() { // 在GameOver状态时按R重开 if (gameOverText.gameObject.activeSelf Input.GetKeyDown(KeyCode.R)) { Time.timeScale 1f; SceneManager.LoadScene(SceneManager.GetActiveScene().name); } }到这里一个能玩的贪吃蛇已经跑起来了。如果你能独立把上面这些代码不报错地跑通你就已经掌握了Unity开发的第一轮完整闭环搭场景、做预制体、写脚本、碰撞交互、UI反馈。但真到这一步后面还有几个坑等着你。4. 跑通之后回头看那些必须遇到的坑和解决办法4.1 快速连按方向键为什么蛇会“吞输入”甚至反向我第一版做的贪吃蛇有个烦人的问题快速连续按了上、左两个键蛇可能先往上但还没等移动就又吃到左边输入结果该往上走的一拍变成了往左走直接造成90度急转有时还会导致撞墙。原因在于输入读取和移动计算被放在同一个Update里输入被无缓冲地覆盖了。解决办法是引入“暂存下一拍的方向”机制也就是我在代码里写的nextDirection。每次按键只更新nextDirection真正移动时再把direction赋值为nextDirection。这样即使在两拍之间按了一堆键也只会有最后一次按键生效。这是游戏输入处理里的经典技巧输入缓冲。以后做任何需要控制方向的项目都会用到。4.2 快速移动的触发器丢失为什么你的蛇偶尔穿过食物用OnTriggerEnter2D判断碰撞时如果蛇移动间隔很短、速度很快可能会出现一种诡异现象蛇头明明从食物位置扫过去了却什么都没发生。这其实是物理检测采样的经典问题两帧之间物体移动距离超过了碰撞体大小触发器的采样点直接跳过了对方。解决办法有两个。一是把移动间隔限制在不太小的值比如0.1秒以上保证单拍步长不至于让碰撞体完全跳过目标。二是改用主动检测在MoveOneStep里用Physics2D.OverlapPointAll检查新蛇头位置有没有贴着食物。我最终版本用的是后者因为更稳不受帧率影响。零基础可以先按第一种跑起来等真遇到问题再升级成主动检测。4.3 食物生成到墙上或蛇身上怎么办食物随机生成时可能生成到墙里也可能生成到蛇的当前位置。墙的问题好解决随机范围直接取在游戏区域内部四面墙内缩一个步长就保证了不碰墙。蛇身的问题则要去查生成食物后遍历一遍所有蛇身节点的位置如果重合就重新随机。零基础容易图省事食物生成一遍就完事。但玩个几分钟食物刷在蛇身上的概率其实不低尤其蛇长到十几节之后。千万别偷懒这个校验必须加。4.4 蛇长到几百节之后画面卡了怎么办贪吃蛇理论上可以一直吃蛇身会越来越长。我实测长到三百节左右Instantiate和Destroy的频繁调用开始让GC垃圾回收压力变大游戏出现微小卡顿。零基础阶段可以暂时不管但如果你想做更完善的版本有两个思路。一是减少Instantiate和Destroy吃食物时不再新生成节点而是把队列尾部的一个旧节点“挪”到头部。具体做法是所有蛇身节点共用一群预先实例化的对象用队列维护“当前活跃”的节点。这就是最简单的对象池思想。二是把位置同步改成只移动头部节点并间隔同步身体节点大幅减少每帧的操作量。这些优化对零基础不是必须但知道原理很重要它们会出现在你未来的每一个Unity项目里。5. 从贪吃蛇出发再往前走的升级方向和路线5.1 玩法扩展加分道具、障碍物、双人对战基础版跑通之后游戏性还很薄。加一个加速道具蛇吃到后在一定时间内的移动间隔减半立刻刺激起来。加障碍物也是好方向在游戏区域中间摆几个石头蛇要绕着走。想再进一步可以做双人对战一条蓝蛇一条橙蛇谁先撞到对方身体谁输。这些扩展用到的技术点基本都在贪吃蛇里出现过不太需要新知识。5.2 视觉和音效升级一个能拿得出手的版本纯白方块版适合跑通逻辑但不适合展示。做几个简单的Sprite蛇头画上两个黑点当眼睛蛇身颜色从深到浅渐变食物加一个2D动画让它小幅度旋转。音效可以在吃到食物时播放一个短促的点击声。这些资源可以先用代码生成或简单图片编辑工具随便画一个重要的是体验“给游戏加反馈”的感觉音效和动画会让十分的内容看起来像八十分。5.3 做完贪吃蛇之后下一步练什么贪吃蛇完成之后不要急着碰大型项目。我建议按顺序做三件事第一把官方入门教程里的火箭发射小项目跟着做一遍巩固场景和脚本基础第二做一款打砖块你会在里面学到鼠标交互和子弹运动第三做一款井字棋或者记忆翻牌掌握简单的游戏状态管理。每一步都能复用你已经在贪吃蛇里学会的技能难度梯度刚刚好。最后分享一点个人感受。做项目最忌讳的是“教程看了一遍就觉得自己会了”打开Unity自己动手把贪吃蛇从零写一遍遇到报错就看报错信息主动寻找解决方案这个过程本身才是真正的学习。贪吃蛇虽然是个几十年前就有的老游戏但它涵盖了游戏开发最核心的思想数据结构选型、时间驱动逻辑、碰撞交互、界面反馈、状态管理。把它吃透你就拥有了独立完成任意一款休闲小游戏的底气也把“那个男孩想用Unity做一款游戏”的念头变成了一个真正落地的东西。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑