3D游戏建模与设计3:基于Unity平台编写第一款数字小游戏

1.游戏介绍

  这是一款有点烧脑的小游戏,需要玩家拥有强大的一位数加法能力以及战略选择能力。游戏会给出玩家需要达到的目标值以及能输入数字的次数,玩家需要在规定的输入数字的次数内按下数字按键以输入数字,输入数字的范围为1到9,每一个数字只能输入一次,游戏会自动加上玩家输入的数字,当输入次数等于游戏给出能输入数字的次数时,如果加到的总值等于游戏给出的玩家需要达到的目标值,游戏胜利,否则游戏失败。

  例如,游戏随机更新的目标值和输入次数为16和5,如果玩家输入的5个数字分别为1、2、3、4、6,由于1+2+3+4+6=16,则玩家胜利。如果玩家输入的5个数字分别为1、2、3、4、5,由于1+2+3+4+5=15,并非16,则游戏失败。

2.游戏编写

  本游戏基于Unity引擎编写,使用的脚本文件语言为C#,首先需要确保保证电脑中安装Unity引擎,我的版本是2023.3.8f1c1,还需下载VSCode或VStudio用于编写代码,还需要Unity的Plastic SCM用于管理代码,具体安装方法这里不过多介绍。

接着我们打开Unity,找到项目,选择新项目。

选择3D,项目命名为NumberGame,保存地址我选择的是D盘。(启动版本管理可选可不选)

现在我们进入了Unity引擎界面,如图所示,什么内容也没有。

在Assets栏中空白区用鼠标右键点击,选择Create中的C# Script生成我们游戏的游戏脚本

将脚本命名为NumberGame。(该名称在后续无法修改,请一定不要拼写错误)

点击我们刚刚生成的脚本,如果按装了VS或VSCode,电脑会自动使用VS或VSCode打开,我的电脑使用了VSCode打开,现在脚本中代码如图所示:

本游戏代码只需要如下三个头文件:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

脚本中自带了类如下:

public class NumberGame : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

我们只需要Start()不需要Update(),现在在此基础上进行修改。

先添加几个全局变量。

private static int count;  //用于记录玩家输入的总值
private static int chance; //用于记录玩家能输入几次
private static int total;  //用于记录目标值
private static int time; //用于记录玩家输入了几次
private int[,] KeyBoard = new int[3, 3]; //用于判断按钮是否被按过
private int[,] NumberBoard = new int[3, 3]; //用于记录每个按钮对应的数字
private Rect window0 = new Rect(550, 20, 200, 200); //提示窗口坐标信息
private bool showWindow = false;  //用于显示提示窗口

然后在Start()中添加函数 Init(),至于 Init()的函数内容我们到后面再编写。

void Start()
{
   Init();
}

当玩家重复点击同一个数字按钮时,我们需要使用一个新窗口提示他,效果如图所示:

Unity中GUI显示窗口的代码格式如下:

GUI.Window(窗口编号, 窗口坐标, 窗口函数, "content“)

其中每个窗口都有唯一的窗口编号;窗口坐标为相对于背景的坐标和窗口的长宽,也就是我们上文全局变量中的window0;窗口函数可实现在该窗口内实现某些功能,显示某些内容。在我的新窗口中窗口函数显示了一个Box,实现了一个按钮用于关闭新窗口;content显示在窗口上边栏,例如我的新窗口的content便是warnning。

现在我们编写窗口函数oneWindow。

void oneWindow(int windowID)
{
    GUI.Box(new Rect(10, 50, 180, 30), "同一个数字按钮不能多次按下");
    if (GUI.Button(new Rect(10, 120, 150, 50), "关闭"))
    {
        showWindow = false;
    }
}

其中Rect中前两位分别是横坐标和纵坐标,后两位分别是长与宽。

Unity中GUI的按钮Button的代码格式如下:

if (GUI.Button(new Rect(x,y,h,w),"content")
{
    //按钮按下后需要实现的函数
}

if (GUI.Button(new Rect(x,y,h,w),"content")会按照Rect中的内容创建一个按钮,上面显示的名称为content。我们在这个if中写下我们想要实现的功能,例如我们九让showWindow=false,这样新窗口就不可见了。程序执行完后会返回true。

现在我们编写GUI部分,我们先创造一个没有内容的box作为背景,然后创建Restart按钮,if函数里面写Inti()用于重置参数,Init()同样到后面再写。再用两个Lable表明目标值以及能输入的次数。当玩家输入次数还未到达游戏给出能输入的次数前时,我们创建1-9这9个按钮。需要说明的是,我们使用KeyBorad[i,j]用于记录该按钮是否被按过,若KeyBorad[i,j]未按过,则KeyBorad[i,j]=0;若KeyBorad[i,j]按过,则KeyBorad[i,j]=1。如果KeyBorad[i,j]=0,说明没按过,我们执行函数Press(),这个函数我们后面再编写。如果KeyBorad[i,j]=1,说明按过,我们弹出提示框。

当玩家输入次数到达游戏给出能输入的次数时,我们用GameOver函数判断玩家是否胜利,该函数到后面再编写,若玩家胜利,我们生成一个小Box表明玩家胜利;若玩家失败,我们生成一个小Box表明玩家失败。

代码如下:

void OnGUI()
{
    GUI.Box(new Rect(210, 25, 300, 300), "");
    if (GUI.Button(new Rect(310, 270, 100, 30), "Restart"))
    {
        Init();
    }
    string total_content = "您的目标值为:" + total.ToString();
    GUI.Label(new Rect(225, 26, 100, 30), total_content);
    string chance_content = "您能输入的次数为:" + chance.ToString();
    GUI.Label(new Rect(335, 26, 120, 30), chance_content);
    if (showWindow)
    {
        GUI.Window(0, window0, oneWindow, "warnning");
    }
    if (time < chance)
    {
        if (GUI.Button(new Rect(255 + 0 * 70, 50 + 0 * 70, 70, 70), "1"))
        {
            if (KeyBoard[0, 0] == 0)
            {
                Press(0, 0);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 1 * 70, 50 + 0 * 70, 70, 70), "2"))
        {
            if (KeyBoard[0, 1] == 0)
            {
                Press(0, 1);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 2 * 70, 50 + 0 * 70, 70, 70), "3"))
        {
            if (KeyBoard[0, 2] == 0)
            {
                Press(0, 2);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 0 * 70, 50 + 1 * 70, 70, 70), "4"))
        {
            if (KeyBoard[1, 0] == 0)
            {
                Press(1, 0);
            }
            else
            {
                 showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 1 * 70, 50 + 1 * 70, 70, 70), "5"))
        {
            if (KeyBoard[1, 1] == 0)
            {
                Press(1, 1);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 2 * 70, 50 + 1 * 70, 70, 70), "6"))
        {
            if (KeyBoard[1, 2] == 0)
            {
                Press(1, 2);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 0 * 70, 50 + 2 * 70, 70, 70), "7"))
        {
            if (KeyBoard[2, 0] == 0)
            {
                Press(2, 0);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 1 * 70, 50 + 2 * 70, 70, 70), "8"))
        {
            if (KeyBoard[2, 1] == 0)
            {
                Press(2, 1);
            }
            else
            {
                showWindow = true;
            }
        }
        if (GUI.Button(new Rect(255 + 2 * 70, 50 + 2 * 70, 70, 70), "9"))
        {
            if (KeyBoard[2, 2] == 0)
            {
                Press(2, 2);
            }
            else
            {
                showWindow = true;
            }
        }
    }
    else if (time == chance)
    {
        if (GameOver() == true)
        {
            GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n you has won.");
        }
        if (GameOver() == false)
        {
            GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nYou loss!\n please try again.");
        }
    }
}

现在编写Init(),我们分别初始化我们的全局变量count和time,至于chance用1-10内的随机数初始化,minTotal和maxTotal分别规定了total的随机取值上下界,假如随机生成的chance=5,那么我们的total的最小值只能为1-5这5个数之和,即15;total的最大值只能为5-9这5个数之和,即35。我们必须这样随机生成total,不然会出现total过大或过小导致玩家无法完成游戏。值得说明的是,NumberBoard与按键一一对应,方便后面计算count。

代码如下:

void Init()
{
    count = 0;
    time = 0;
    chance = Random.Range(1, 10);
    int minTotal = 0;
    int maxTotal = 0;
    for (int i = 1; i <= chance; i++)
    {
       minTotal += i;
    }

    for (int i = 9; i >= 10 - chance; i--)
    {
        maxTotal += i;
    }
    total = Random.Range(minTotal, maxTotal + 1);
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            KeyBoard[i, j] = 0;
        }
    }
    int temp = 1;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            NumberBoard[i, j] = temp;
            temp++;
        }
    }

}

现在编写Press函数,每次执行Press,KeyBoard相应位置会由0变成1,我们的count要累加NumberBoard对应值,玩家已输入次数需要加1.

代码如下:

void Press(int i, int j)
{
    KeyBoard[i, j] = 1;
    count += NumberBoard[i, j];
    time++;
}

现在编写GameOver函数,如果玩家输入的值不等于目标值,返回false,即游戏失败,如果玩家输入的值等于目标值,则游戏胜利。

代码如下:

bool GameOver()
{
    if (count != total)
    {
        return false;
    }
    return true;
}

3.游戏代码

游戏完整代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NumberGame : MonoBehaviour
{
    // Entities and their states / Model
    private static int count;  //用于记录玩家输入的总值
    private static int chance; //用于记录玩家能输入几次
    private static int total;  //用于记录目标值
    private static int time; //用于记录玩家输入了几次
    private int[,] KeyBoard = new int[3, 3]; //用于判断按钮是否被按过
    private int[,] NumberBoard = new int[3, 3]; //用于记录每个按钮对应的数字
    private Rect window0 = new Rect(550, 20, 200, 200); //提示窗口坐标信息
    private bool showWindow = false;  //用于显示提示窗口

    // System Handlers
    void Start()
    {
        Init();
    }


    // View to render entities / models
    void OnGUI()
    {
        GUI.Box(new Rect(210, 25, 300, 300), "");
        if (GUI.Button(new Rect(310, 270, 100, 30), "Restart"))
        {
            Init();
        }
        string total_content = "您的目标值为:" + total.ToString();
        GUI.Label(new Rect(225, 26, 100, 30), total_content);
        string chance_content = "您能输入的次数为:" + chance.ToString();
        GUI.Label(new Rect(335, 26, 120, 30), chance_content);
        if (showWindow)
        {
            GUI.Window(0, window0, oneWindow, "warnning");
        }
        if (time < chance)
        {
            if (GUI.Button(new Rect(255 + 0 * 70, 50 + 0 * 70, 70, 70), "1"))
            {
                if (KeyBoard[0, 0] == 0)
                {
                    Press(0, 0);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 1 * 70, 50 + 0 * 70, 70, 70), "2"))
            {
                if (KeyBoard[0, 1] == 0)
                {
                    Press(0, 1);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 2 * 70, 50 + 0 * 70, 70, 70), "3"))
            {
                if (KeyBoard[0, 2] == 0)
                {
                    Press(0, 2);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 0 * 70, 50 + 1 * 70, 70, 70), "4"))
            {
                if (KeyBoard[1, 0] == 0)
                {
                    Press(1, 0);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 1 * 70, 50 + 1 * 70, 70, 70), "5"))
            {
                if (KeyBoard[1, 1] == 0)
                {
                    Press(1, 1);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 2 * 70, 50 + 1 * 70, 70, 70), "6"))
            {
                if (KeyBoard[1, 2] == 0)
                {
                    Press(1, 2);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 0 * 70, 50 + 2 * 70, 70, 70), "7"))
            {
                if (KeyBoard[2, 0] == 0)
                {
                    Press(2, 0);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 1 * 70, 50 + 2 * 70, 70, 70), "8"))
            {
                if (KeyBoard[2, 1] == 0)
                {
                    Press(2, 1);
                }
                else
                {
                    showWindow = true;
                }
            }
            if (GUI.Button(new Rect(255 + 2 * 70, 50 + 2 * 70, 70, 70), "9"))
            {
                if (KeyBoard[2, 2] == 0)
                {
                    Press(2, 2);
                }
                else
                {
                    showWindow = true;
                }
            }

        }
        else if (time == chance)
        {
            if (GameOver() == true)
            {
                GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nCongratulations!\n you has won.");
            }
            if (GameOver() == false)
            {
                GUI.Box(new Rect(260, 50, 200, 200), "\n\n\n\n\nYou loss!\n please try again.");
            }
        }
    }
    void oneWindow(int windowID)
    {
        GUI.Box(new Rect(10, 50, 180, 30), "同一个数字按钮不能多次按下");
        if (GUI.Button(new Rect(10, 120, 150, 50), "关闭"))
        {
            showWindow = false;
        }
    }






    // Components /controls
    void Init()
    {
        count = 0;
        time = 0;
        chance = Random.Range(1, 10);
        //Debug.Log("随机生成的chance: " + chance);
        int minTotal = 0;
        int maxTotal = 0;
        for (int i = 1; i <= chance; i++)
        {
            minTotal += i;
        }

        for (int i = 9; i >= 10 - chance; i--)
        {
            maxTotal += i;
        }
        total = Random.Range(minTotal, maxTotal + 1);
        //Debug.Log("随机生成的total: " + maxTotal);
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                KeyBoard[i, j] = 0;
            }
        }
        int temp = 1;
        for (int i = 0; i < 3; i++)
        {
            for (int j = 0; j < 3; j++)
            {
                NumberBoard[i, j] = temp;
                temp++;
            }
        }

    }

    void Press(int i, int j)
    {
        KeyBoard[i, j] = 1;
        count += NumberBoard[i, j];
        time++;
    }

    bool GameOver()
    {
        if (count != total)
        {
            return false;
        }
        return true;
    }
}

4.游戏演示

3D游戏建模与设计作业2 基于unity平台个人设计的一款数字游戏

5.游戏资源

作业3/NumberGame.cs · 陈冠洲/3D游戏建模与设计 - Gitee.com

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值