Unity开发 第三章 浮动的按钮以及第一个小游戏(贪吃蛇的移动逻辑)
Unity开发 第一章 认识模板和界面以及项目导入到Rider
Unity开发 第二章 2D游戏制作之文件结构以及素材利用(主要是脚本绑定)
Unity开发 第三章 浮动的按钮以及第一个小游戏
Unity开发 第四章 贪吃蛇小游戏制作半完成版
文章目录
前言
游戏开发应该要明确自己做的游戏是什么,或者要加入的功能是什么。
入门的学习不能说一上来就是3A大作,一口吃成胖子属于是,如果不想看前言就直接看后面的吧,全是操作。
但是呢,要学技术,就先明确咱们的方向,再去看操作才有所理解。
首先
在上一章,我们明确了资源和脚本与Unity上的组件的联系,现在会实现一个浮动的按钮,来加深脚本如何影响组件的理解
其次
学会看API,以及明确咱们一步一步入门Unity开发的游戏路线,从易到难,由浅入深,再进行转3D会让我们更加能跳脱思维,咱们的游戏路线为
一、制作这样的界面需要的认识
写脚本先认识一下这个基类
这个搞前端的会非常清楚,不过我还是讲点人话
- Start就是后端的初始化,最先执行的
- Update就是后续按钮浮动要用到的,每一帧都在浮动
- FixedUpdate 嗯,可以联系现实的时间
- 其他的自己也晓得,自己了解去吧,还可以做的就是自定义一个和基类方法一致的东西,不过还是要自己看APi才行,我也不多说。
二、浮动的按钮
浮动的按钮其实技术难度不是说很高
首先是素材
这个素材用于制作一个三角形的按钮
调整一下参数
然后是代码
using System.Collections;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Games.UI
{
public class TriangleButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler{
private Image _buttonImage;
private RectTransform _rectTransform; // 获取按钮的 RectTransform 组件
public Color normalColor = Color.green;
public Color hoverColor = Color.cyan;
public Color clickColor = Color.red;
public float floatSpeed =4f; // 浮动速度
public float floatHeight = 10f; // 浮动的最大高度(偏移量)
private Vector3 _originalPosition; // 原始位置,用来计算浮动
private bool _isHovered = false; // 用来标记是否悬停在按钮上
private bool _isFloating = true; // 用来标记按钮是否正在浮动,初始为浮动状态
void Start(){
_buttonImage = GetComponent<Image>();
_rectTransform = GetComponent<RectTransform>();
// 获取按钮的原始位置
_originalPosition = _rectTransform.localPosition;
_buttonImage.color = normalColor;}
void Update(){
// 使按钮浮动
if (_isFloating){FloatButton();}}
// 浮动效果
private void FloatButton(){
float yOffset = Mathf.Sin(Time.time * floatSpeed) * floatHeight; // 计算浮动的偏移量
_rectTransform.localPosition = new Vector3(_originalPosition.x, _originalPosition.y + yOffset, _originalPosition.z);}
// 鼠标进入时的效果
public void OnPointerEnter(PointerEventData eventData){
_isHovered = false; // 设置为悬停状态
_isFloating = false; // 停止浮动效果
_buttonImage.color = hoverColor; // 鼠标悬停时的颜色
StartCoroutine(SmoothReturnToOriginalPosition());}
// 鼠标离开时的效果
public void OnPointerExit(PointerEventData eventData)
{
_isHovered = true; // 设置为离开状态
_isFloating = true; // 开启浮动效果
_buttonImage.color = normalColor;} // 鼠标离开时的颜色
// 鼠标点击时的效果
public void OnPointerClick(PointerEventData eventData)
{
_buttonImage.color = clickColor; // 点击时的颜色
Debug.Log("三角形按钮被点击了!");
}
private IEnumerator SmoothReturnToOriginalPosition(){float time = 0f;
Vector3 currentPos = _rectTransform.localPosition;
while (time < 1f){time += Time.deltaTime * 5f; // 5f 为恢复速度,可以根据需要调整
_rectTransform.localPosition = Vector3.Lerp(currentPos, _originalPosition, time);
yield return null;}
_rectTransform.localPosition = _originalPosition;}}} // 确保位置完全恢复
然后写好的脚本绑定到三角形上并且自己调整一下方向就行了,本来我还想把颜色变化也弄进去的,但是没成功
实现了浮动效果
后面是只实现了一个移动逻辑贪吃蛇,下一期会把贪吃蛇的完整逻辑给写完
三、小游戏(贪吃蛇)
游戏制作第一步,准备素材以及设计逻辑
素材咱们先规划一下
- 图形素材
蛇的身体:可以是简单的几何形状(如矩形或圆形),或者更复杂的自定义图形。
食物:可以是一个小圆点或者任何吸引玩家注意的图标。
背景:游戏的背景图,可以是纯色或者具有一定图案的背景。
UI元素:包括开始按钮、结束游戏的提示、分数板、暂停菜单等。
蛇和食物的动画:如果需要,可以为蛇的移动和食物的生成添加简单的动画效果。
首先咱们进行抠图,如果不下载作者的垃圾资源包的话就自己用ps抠抠图,这样也会对于游戏素材如何产生有很高的理解
随便找个像素蛇的图片进行抠图,主要是抠出蛇头,蛇身体,以及蛇尾部
初步设计蛇哥
一个蛇头和蛇身,蛇尾
蛇身部分要使用一段非常好的躯干来用代码生成蛇的躯干,以及弯曲的躯干
调整了很久后,导出素材
再抠一个
以及背景图
-
音频素材
背景音乐:轻松愉快的背景音乐,可以增加游戏的趣味性。
音效:包括蛇移动的声音、吃到食物的声音以及游戏结束的声音。
我觉得蛇的移动和吃到食物可以自己去自定义去,到时候再搜点资源。
然后BGM我想用《凑热闹》来当做音乐。 -
代码
游戏逻辑:编写控制蛇移动、食物生成、得分计算等逻辑的代码。
UI控制:编写控制UI元素显示和交互的代码。
UI的话
我是随便做了一下
首先我们要自己规定一下图层
最底下的是背景
然后就是我们的一些UI控件
按这个指标进行调整,并且图层给搞好
然后是我们的游戏对象的素材
添加组件sprite Render
然后把图放上去,贪吃蛇也是一样的,这里我就不细说了,给个效果图
然后自己调整好位置
最后就是把那些UI给做好就行,下面这些组件中jifenban是
得分和0都是Text(TMP)
剩下的按钮和之前的文章是一样的,这样,咱们的大致UI就已经做好了。
- 其他素材
字体:用于显示分数和游戏状态的字体。
图标:用于UI按钮和菜单的图标。
我不多说,直接下一步
字体第二章有如何导入的方法
游戏制作第二步,代码逻辑以及资源绑定
我们需要处理的逻辑,在进行第一步认识游戏时其实就要进行设计,但为了不出现信息断层,这里讲一下大致的思路。
- 蛇头根据上下左右进行响应,产生移动和旋转的逻辑
- 蛇身需要根据蛇头的情况,需要处于八个方向的状态,这里蛇身其实需要两个状态(转弯和直行)然后乘以旋转的4个方向正好8个状态。
- 蛇尾和蛇头的碰撞逻辑以及蛇头与边缘的碰撞逻辑
- 蛇头吃下食物后的蛇身增长逻辑
- GameOver的逻辑,返回、暂停、开始的逻辑
- 计分板分数变动的问题
- 蛇的运动状态不断增快的逻辑
一般来说,搞过程序的都有写过,不过我还是会说一下。
第一个是蛇头的移动逻辑
这里我们不会做加快这玩意运动的东西,如果要加的话,自己去看看逻辑怎么写
这里贴出代码,是未完成的代码,到时候会把这个项目放到gitcode或者gitee上去,github也丢一个
namespace Games.games.Gluttonous_Snake
{
using UnityEngine;
public class SnakeHead : MonoBehaviour{
public float moveSpeed = 5f;
public Vector2 direction = Vector2.up; // 初始方向(向右)
public Vector2 lastDirection; // 上一次的方向(用于避免掉头)
private bool isMoving = true; // 是否正在移动
public delegate void OnFoodEaten();
public static event OnFoodEaten FoodEaten;
void Start(){lastDirection = direction; // 初始化上一次的方向}
void Update(){
if (!isMoving) return;
HandleInput(); // 处理玩家输入
Move(); // 移动蛇头}
private void HandleInput(){
if (Input.GetKeyDown(KeyCode.UpArrow)){
direction = Vector2.up; // 向上(0,-1)
RotateSnake(0f); // 旋转蛇头}
else if (Input.GetKeyDown(KeyCode.DownArrow)){
direction = Vector2.down; // 向下(0,1)
RotateSnake(180f); // 旋转蛇头}
else if (Input.GetKeyDown(KeyCode.LeftArrow)){
direction = Vector2.left; // 向左(-1,0)
RotateSnake(90f); // 旋转蛇头}
else if (Input.GetKeyDown(KeyCode.RightArrow))
{direction = Vector2.right; // 向右(1,0)
RotateSnake(-90f); // 旋转蛇头}}
private void RotateSnake(float angle) { // 旋转蛇头,根据新的方向设置旋转角度
transform.rotation = Quaternion.Euler(0, 0, angle); } // 旋转蛇头,Z轴旋转
private void Move() {// 让蛇头朝着当前方向移动
transform.Translate(direction * (moveSpeed * Time.deltaTime),Space.World);
lastDirection = direction; // 更新上次的方向}
private bool CheckCollisionWithBody(){
foreach (Transform bodySegment in GameManager.Instance.snakeBodySegments)
{if (Vector2.Distance(transform.position, bodySegment.position) < 0.5f){return true; }}return false; }// 如果蛇头与身体段距离太近,表示碰撞
public void EatFood(){FoodEaten?.Invoke();} // 触发吃到食物的事件,吃掉食物时的逻辑
public void StartMoving(){isMoving = true;}
public void StopMoving(){isMoving = false;}}}
绑定到SnakeHead
然后是考虑我们的蛇身的状态变化
两种状态变化我们应该怎么做才能更合理,下一篇博客会把这些都写好的,因为在解决UI和资源文件后,基本上代码逻辑就会很好实现了,毕竟又不做太高深的东西。
总结
算是把这次的经验全部体现出来了,虽然多,但是非常详细的好吧,如果有帮助的话,或者复现成功的话,记得和本作者说一下,我会很高兴的,下一期是贪吃蛇的完整代码逻辑实现。