从0开始学Unity做SLG系列(1)

5 篇文章 0 订阅
4 篇文章 0 订阅


因为这部分已经做完了,回头整理文档顺便复盘,所以可能不是很详细,先给了整体代码,后面再慢慢分析

GameFramework框架

写这个例子前最好看下框架的教程
我们用开发模版,很多内容已经写好了,首先下载

搜索New Prefab,然后都删掉
在这里插入图片描述
这是整体的目录结构,框架整体是流程procedure来控制的,游戏的入口在GameFramework-Builtin-Procedure的设置面板里,Available Procedures是所有的游戏流程,Entrance Procedure就是第一个执行的流程,即入口。

流程 (Procedure) – 是贯穿游戏运行时整个生命周期的有限状态机。通过流程,将不同的游戏状态进行解耦将是一个非常好的习惯。对于网络游戏,你可能需要如检查资源流程、更新资源流程、检查服务器列表流程、选择服务器流程、登录服务器流程、创建角色流程等流程,而对于单机游戏,你可能需要在游戏选择菜单流程和游戏实际玩法流程之间做切换。如果想增加流程,只要派生自 ProcedureBase 类并实现自己的流程类即可使用。

打开入口文件ProcedureLaunch,重命名namespace名为MaliGame,vs编辑器会自动替换所有文件,修改命名空间后,还要修改下面几个地方

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

加载登陆界面

在这里插入图片描述
首先确定分辨率,添加640*1136
在这里插入图片描述

然后新建一个scene,改名为Load修改摄像机模式为solid Color,并添加一个Image,因为Image需要Canvas为容器,所以会自动创建一个Canvas。
在这里插入图片描述
修改Canvas为LoadCanvas,Image为LoadBkg,并创建按钮,改名为registBtn,删除自带的Button,添加CommonButton
在这里插入图片描述
复制一个改名为loginBtn,并按图创建其他内容,在Procedure目录下创建游戏目录MaliGame,新建脚本取名ProcedureLoad,创建LoadScene脚本,并添加到LoadCanvas上
在这里插入图片描述
因为这部分是已经做完了,回头整理文档,所以介绍比较快,跟着来就好了。按图添加其他的text和image,并拖到对应的位置,脚本完整内容如下

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

namespace MaliGame
{
    public class LoadScene : MonoBehaviour
    {
        [HideInInspector]
        public bool IsStartGame = false; //登陆完成进入游戏

        public CommonButton registBtn;
        public CommonButton loginBtn;
        public Image progressFg;
        public Text loadLb;
        public GameObject shipEff;

        private float proNum = 0.0f;

        public float animSpeed = 10;  //动画播放速度 默认1秒播放10帧图片
        private float animTimeInterval = 0;  //帧与帧间隔的时间

        public Image animRenderer;//动画载体的渲染器
        public Sprite[] SpriteArray; //序列帧数组
        private int frameIndex = 0;  //帧索引
        private int animLength = 0;  //多少帧
        private float animTimer = 0; //动画时间计时器

        void Start()
        {
            Debug.Log("LoadScene Start");
            startLoad();

            animTimeInterval = 1 / animSpeed;//得到每一帧的时间间隔
            animLength = SpriteArray.Length; //得到帧数
        }

        void Update()
        {
            //假进度,正常是加载的时候更新进度
            if (proNum < 1)
            {
                proNum += 0.05f;
                setProgress(proNum);
            }

            animTimer += Time.deltaTime;
            if (animTimer > animTimeInterval)
            {
                animTimer -= animTimeInterval;//当计时器减去一个周期的时间
                frameIndex++;//当帧数自增(播放下一帧)
                frameIndex %= animLength;//判断是否到达最大帧数,到了就从新开始  这里是循环播放的
                animRenderer.sprite = SpriteArray[frameIndex]; //替换图片实现动画
            }
        }

        //更新进度条
        private void setProgress(float pNum)
        {
            Debug.Log("LoadScene setProgress " + pNum + "%");

            proNum = pNum;
            loadLb.text = (int)(pNum * 100) + "%";
            progressFg.fillAmount = pNum;
            shipEff.transform.SetLocalPositionX(-300 + 600 * pNum);

            if (proNum >= 1)
            {
                loadLb.text = "加载完成";
                progressFg.fillAmount = 1;
                shipEff.transform.SetLocalPositionX(300);
                loadOver();
            }
        }

        //开始加载资源
        private void startLoad()
        {
            Debug.Log("LoadScene startLoad");

            setProgress(proNum);

            //var registBtn = (CommonButton)this.GetComponent("registBtn");
            registBtn.gameObject.SetActive(false);

            //var loginBtn = (CommonButton)this.GetComponent("registBtn");
            loginBtn.gameObject.SetActive(false);

        }

        private void loadOver()
        {
            Debug.Log("LoadScene loadOver");
            //var registBtn = (CommonButton)this.GetComponent("registBtn");
            registBtn.gameObject.SetActive(true);

            //var loginBtn = (CommonButton)this.GetComponent("registBtn");
            loginBtn.gameObject.SetActive(true);

        }

        public void OnRegistBtnClk()
        {
            Debug.Log("LoadScene OnRegistBtnClk");
            GameEntry.UI.OpenUIForm(UIFormId.LoginForm, this);
        }

        public void OnLoginBtnClk()
        {
            Debug.Log("LoadScene OnLoginBtnClk");
            IsStartGame = true;
        }

    }

}

ProcedureLoad代码如下

using GameFramework.Event;
using GameFramework.Procedure;
using UnityEngine;
using UnityGameFramework.Runtime;
using ProcedureOwener = GameFramework.Fsm.IFsm<GameFramework.Procedure.IProcedureManager>;

namespace MaliGame
{
    public class ProcedureLoad : ProcedureBase
    {
        public LoadScene m_LoadScene;

        //private LoginForm m_LoginForm = null;

        //进入加载流程的时候
        protected override void OnEnter(ProcedureOwener procedureOwener)
        {
            Debug.Log("ProcedureLoad OnEnter");
            base.OnEnter(procedureOwener);
            m_LoadScene = GameObject.Find("LoadCanvas").GetComponent<LoadScene>();

        }

        protected override void OnUpdate(ProcedureOwener ProcedureOwener, float elapseSeconds, float realElapseSeconds)
        {
            Debug.Log("ProcedureLoad OnUpdate    " + m_LoadScene.IsStartGame);
            base.OnUpdate(ProcedureOwener, elapseSeconds, realElapseSeconds);
            if (m_LoadScene.IsStartGame)
            {
                ProcedureOwener.SetData<VarInt>(Constant.ProcedureData.NextSceneId, GameEntry.Config.GetInt("Scene.Main"));
                ChangeState<ProcedureChangeScene>(ProcedureOwener);
            }
        }

        protected override void OnLeave(ProcedureOwener procedureOwner, bool isShutdown)
        {
            Debug.Log("ProcedureLoad OnLeave");
            base.OnLeave(procedureOwner, isShutdown);
        }


    }
}

这里在新建一个脚本LoginForm一会说,代码如下

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

namespace Ship
{
    public class LoginForm : UGuiForm
    {
        private LoadScene m_LoadScene = null;

        protected override void OnOpen(object userData)
        {
            Debug.Log("LoginForm OnOpen");
            base.OnOpen(userData);
            m_LoadScene = (LoadScene)userData;

        }

        protected override void OnClose(object userData)
        {
            Debug.Log("LoginForm OnClose");
            m_LoadScene = null;
            base.OnClose(userData);
        }

        public void OnStartButtonClick()
        {
            Debug.Log("LoginForm OnStartButtonClick");
            Close();
            m_LoadScene.IsStartGame = true;
        }

    }

}

因为是复盘,所以先把代码都贴出来了,下面来添加素材,然后一步步说。unity里面的图片想要给image设置需要线修改属性,这步比较麻烦,我们来整个脚本,以后导入就直接变了。

在根目录下创建一个Editor文件夹 之后在Editor文件夹下创建一个脚本 TextureChage
在这里插入图片描述

using UnityEditor;
using UnityEngine;

public class AssetPostManager : AssetPostprocessor
{
    void OnPostprocessTexture(Texture texture)
    {
        if (assetPath.StartsWith("Assets/Resources/Image"))
        {
            TextureImporter importer = AssetImporter.GetAtPath(assetPath) as TextureImporter;
            if ((importer != null) && (importer.textureType != TextureImporterType.Sprite))
            {
                importer.textureType = TextureImporterType.Sprite;
                importer.SaveAndReimport();
            }
        }
    }
}

在这里插入图片描述
先判断一下路径(对于我的项目来说,prefab的图片都是放在这里的,所以我就只修改这个目录下的图片类型)。
接着判断一下,如果不是Sprite就改成Sprite。这个类型判断最好加上,因为可能会影响九宫格的数据。
最后一定要SaveAndReimport()一下,才能看到被修改了。

在这里插入图片描述
好了,把素材都拖进来,然后设置给之前创建的对应image,为了查看方便可以选择左上角那个2d模式查看

在这里插入图片描述
在这里插入图片描述
给按钮设置完图片后,再添加点击事件,OnClick这里点击右下角+号,把LoadCanvas拖到OnClickli ,然后选择对应的事件
这里要注意,需要拖拽的时候哪个canvas,而不是哪个脚本,不然选不了点击事件

load弄好后,在创建一个场景命名Main,和一个预制体LoginForm,先不用放内容,先把流程跑起来。

在这里插入图片描述

编写框架流程

这里依次打开我们的场景,添加上场景,另存为按制表符分割的txt文件

在这里插入图片描述
这里mac每次编写excel保存导出很是费劲,写了个脚本,修改好excel好后,执行脚本,会自动到处txt供项目使用

#!/usr/bin/python
#encoding:utf-8

# 把当前目录下所有Excel转成以制表符间隔的txt,相当于excel到处txt
# 如果excel存在多个sheet,最后一个生效
import os
import openpyxl
import sys

# 转换编码要不会报错
reload(sys)
sys.setdefaultencoding('utf8')

curPath = os.getcwd()  #返回当前文件所在的目录   
flie_dir = os.listdir(curPath)

def excelToTxt(file):
    #打开Excel文件,这个文件有4个sheet,分别为东,南,西, 北四个区的销售情况
    wb = openpyxl.load_workbook('DefaultConfig.xlsx')
    #循环来读取每一个sheet中的内容
    #写到对应的东,南,西, 北四个txt文件中
    for sheet in wb.sheetnames:
        #生成一个以sheet名字命名的txt文件
        file2 = file.split('.')
        file = open(file2[0] + '.txt', 'w')
        #打开对应的sheet
        ws = wb[sheet]
        #循环来读取每一个cell中的内容
        for i in range(1, ws.max_row + 1):
            for j in range(1, ws.max_column + 1):
                #如果cell中的内容为None,那么写到txt中的时候用空来代替
                if ws.cell(i, j).value is None:
                    continue
                #如果cell中有内容,将其转换成string写到txt中
                else:
                    content = str(ws.cell(i, j).value)
                #如果是第一列那么前面没有制表符分隔
                if j == 1:
                    file.write(content)
                #否者内容前面加上一个制表符分隔
                else:
                    file.write("\t" + content)
            #每一行写完,换行
            file.write("\n")
        #关掉txt文件
        file.close()


for file in flie_dir:
    if file.endswith('.xlsx'):
        excelToTxt(file)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里有个坑,配置里的界面组名称不是unity里的layer分层,而是需要在框架里手动创建的,不然会报错找不到这个default层
在这里插入图片描述

在这里插入图片描述
都编写完,运行脚本,生成txt,这里写了另一个脚本,区别在于遍历所有的excel

#!/usr/bin/python
#encoding:utf-8

# 把当前目录下所有Excel转成以制表符间隔的txt,相当于excel到处txt
# 如果excel存在多个sheet,最后一个生效
import os
import openpyxl
import sys

# 转换编码要不会报错
reload(sys)
sys.setdefaultencoding('utf8')

curPath = os.getcwd()  #返回当前文件所在的目录   
flie_dir = os.listdir(curPath)

def excelToTxt(file):
    #打开Excel文件,这个文件有4个sheet,分别为东,南,西, 北四个区的销售情况
    wb = openpyxl.load_workbook(file)
    #循环来读取每一个sheet中的内容
    #写到对应的东,南,西, 北四个txt文件中
    for sheet in wb.sheetnames:
        #生成一个以sheet名字命名的txt文件
        file2 = file.split('.')
        file = open(file2[0] + '.txt', 'w')
        #打开对应的sheet
        ws = wb[sheet]
        #循环来读取每一个cell中的内容
        for i in range(1, ws.max_row + 1):
            for j in range(1, ws.max_column + 1):
                #如果cell中的内容为None,那么写到txt中的时候用空来代替
                if ws.cell(i, j).value is None:
                    continue
                #如果cell中有内容,将其转换成string写到txt中
                else:
                    content = str(ws.cell(i, j).value)
                #如果是第一列那么前面没有制表符分隔
                if j == 1:
                    file.write(content)
                #否者内容前面加上一个制表符分隔
                else:
                    file.write("\t" + content)
            #每一行写完,换行
            file.write("\n")
        #关掉txt文件
        file.close()


for file in flie_dir:
    if file.endswith('.xlsx'):
        excelToTxt(file)

保存好以后,到GameMain/Scripts/UI/Builtin中修改UIFormId

在这里插入图片描述
在这里插入图片描述

添加主场景的流程脚本,然后勾选所有流程,并设置初始化流程

在这里插入图片描述
在这里插入图片描述
接着修改这两个地方,然后应该就可以跑起来了
注意下面这个地方需要设置,UI Groups需要添加一个,InstanceRoot也需要把左侧的拖过来设置下,不然加载form的时候会有问题
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值