Unity3D学习(16)之初识DDD

来源:互联网 发布:up to date数据库官网 编辑:程序博客网 时间:2024/05/16 01:49

最开始看到DDD是不是一脸懵逼?DDD其实是 Data Driven Design,也就是数据驱动设计。通过数据驱动设计,使得游戏代码更加稳固 (robustness)。我们可以通过改变数据,实现游戏规则、 场景布局、游戏难度的动态改变,而不要程序员的参与。 让游戏发布后,运维与设计师进行”后设计” (Post-Design) 成为可能。

之前关卡的数据都是通过写在代码中实现的

 switch (round)        {            case 1:                diskData.size = 0.8f;//设置大小                diskData.color = Color.green;//设置颜色                newDisk.transform.localScale = new Vector3(25 * diskData.size, 25 * diskData.size, 25 * diskData.size);                newDisk.GetComponent<Renderer>().material.color = diskData.color;                break;            case 2:                diskData.size = 0.7f;//设置大小                diskData.color = Color.yellow;//设置颜色                newDisk.transform.localScale = new Vector3(25 * diskData.size, 25 * diskData.size, 25 * diskData.size);                newDisk.GetComponent<Renderer>().material.color = diskData.color;                break;            case 3:                diskData.size = 0.6f;//设置大小                diskData.color = Color.red;//设置颜色                newDisk.transform.localScale = new Vector3(25 * diskData.size, 25 * diskData.size, 25 * diskData.size);                newDisk.GetComponent<Renderer>().material.color = diskData.color;                break;        }

现在我们将数据保存在Json文件中去,在Asset文件夹下新建Data文件夹,然后新建Disk_Level_1.Json, Disk_Level_2.Json,Disk_Level_3.Json 和Game_Info.Json如下,把我们的数据写进文件里

然后新建一个FileManager.cs用于读取游戏版本及其关卡文件。

public class FileManager : MonoBehaviour {    public string url;    public SceneController sceneControler { get; set; }    // Use this for initialization    void Awake () {        //print(Application.persistentDataPath);        sceneControler = (SceneController)SSDirector.getInstance().currentScenceController;        sceneControler.fileManager = this;        LoadGameInfoJson("game_info.json");    }// Update is called once per framevoid Update () {}    // 输入游戏信息文件名,启动协程读取文件      public void LoadGameInfoJson(string name)    {        url = "file://" + Application.dataPath + "/Data/" + name;        StartCoroutine(LoadGameInfo());    }    IEnumerator LoadGameInfo()    {        if (url.Length > 0)        {            WWW www = new WWW(url);            yield return www;            if (!string.IsNullOrEmpty(www.error))                Debug.Log(www.error);            else                sceneControler.stageGameInfo(www.text.ToString());   // 返回json字符串给scene          }    }                                                                                               //输入游戏关卡文件名,启动协程读取文件    public void loadLevelJson(string name)    {        url = "file://" + Application.dataPath + "/Data/" + name;        StartCoroutine(LoadLevel());    }    IEnumerator LoadLevel()    {        if (url.Length > 0)        {            WWW www = new WWW(url);            yield return www;            if (!string.IsNullOrEmpty(www.error))                Debug.Log(www.error);            else                sceneControler.stageLevel(www.text.ToString());  // 返回json字符串给scene          }    }}


然后写两个可序列化的类用于保存游戏版本信息和关卡信息

[SerializeField]public class GameInfo{    public string version;//游戏版本    public int totalRound;//游戏总轮数    public static GameInfo CreateFromJSON(string json)    {        return JsonUtility.FromJson<GameInfo>(json);    }}[SerializeField]public class LevelData{    public float size;//飞碟大小    public string color;//飞碟颜色    public float speed;//飞碟速度    public static LevelData CreateFromJSON(string json)    {        return JsonUtility.FromJson<LevelData>(json);    }}

在SceneController里面添加两个变量保存游戏版本及关卡总数

public string _version;//版本号public int _totalRound;//总共轮数


由于FileManager读取了版本信息后调用了scene.stageGameInfo,所以相应地在sceneController中添加该方法,接收 json 字符串:

public void stageGameInfo(string json)    {        UpdateData = GameInfo.CreateFromJSON(json);        _version = UpdateData.version;        _totalRound = UpdateData.totalRound;    }


此外游戏的关卡是在游戏过程中读取的,所以修改sceneController的 nextRound() 方法:

public void nextRound()    {        if(++round > _totalRound)        {            round = 1;        }        string file = "Disk_Level_" + round.ToString() + ".json";        fileManager.loadLevelJson(file);    }

然后在sceneController中添加 stageLevel 方法接收json字符串,更新关卡:

public void stageLevel(string json)    {        LevelData data = LevelData.CreateFromJSON(json);        Color _color;        if (!ColorUtility.TryParseHtmlString(data.color, out _color))        {            _color = Color.gray;        }                                                                                               //所有更新的关卡信息全部保存在预制中,工厂制造飞碟根据预制        factory.diskPrefab.GetComponent<DiskData2>().color = _color;        factory.diskPrefab.GetComponent<DiskData2>().size = data.size;        factory.diskPrefab.GetComponent<DiskData2>().speed = data.speed;    }


然后实现联网检查更新,首先用node搭建服务器(有点对不起王青爸爸的教诲,已经忘了怎么做,于是重头来过)

var http = require('http');var url=require('url');var fs=require('fs');var server = http.createServer(function(req,res){if(url.parse(req.url).pathname == "/") {res.writeHead(200, {'Content-type' : 'text/plain'});res.write("2.0");//当前服务器最新游戏版本号res.end();}if(url.parse(req.url).pathname == "/version") {//res.writeHead(200, {'Content-type' : 'text/plain'});res.write(fs.readFileSync("version.json"));//读取版本文件res.end();}if(url.parse(req.url).pathname == "/Disk_Level_1") {//res.writeHead(200, {'Content-type' : 'text/plain'});res.write(fs.readFileSync("Disk_Level_1.json"));//读取关卡1的文件res.end();}if(url.parse(req.url).pathname == "/Disk_Level_2") {//res.writeHead(200, {'Content-type' : 'text/plain'});res.write(fs.readFileSync("Disk_Level_2.json"));//读取关卡2的文件res.end();}if(url.parse(req.url).pathname == "/Disk_Level_3") {//res.writeHead(200, {'Content-type' : 'text/plain'});res.write(fs.readFileSync("Disk_Level_3.json"));//读取关卡3的文件res.end();}});server.listen(1337,"localhost",function(){ //端口号1337 console.log("listened");//启动时在命令行打印});


文件目录如下:

启动服务器


然后在场景控制者写 checkUpdate()检查更新

public void checkUpdate()    {        string checkUrl = "http://localhost:1337/";        this.StartCoroutine(checkVersion(checkUrl));    }    IEnumerator checkVersion(string url)    {        WWW www = new WWW(url);        yield return www;        Debug.Log(www.text.ToString());        if (_version != www.text.ToString() && www.text.ToString() != "")        {            updateManager.OpenPanel();//如果版本号不相同,则弹出提示窗口        }    }

然后建立提示框,一个panel里面加了两个Button,一个text

制作个进入与退出的动画,然后写UpdateManager.cs

public class UpdateManager : MonoBehaviour {    public GameObject UpdatePanel;    public SceneController sceneControler { get; set; }    void Awake()    {        sceneControler = (SceneController)SSDirector.getInstance().currentScenceController;        sceneControler.updateManager = this;    }    public void OpenPanel()    {        UpdatePanel.SetActive(true);//激活提示框    }    public void ClosePanel()    {        UpdatePanel.GetComponent<Animator>().SetBool("Open", false);//播放关闭动画        StartCoroutine(CloseDelay());//启动协程,让动画播放完再灭活    }    public IEnumerator CloseDelay()    {        int CoolTimes = 1;        while (CoolTimes > 0)        {            print("还剩" + CoolTimes);            yield return new WaitForSeconds(1);            CoolTimes--;        }        UpdatePanel.SetActive(false);//灭活    }}

点击Yes按钮除了面板退出还会调用Update1更新文件

public void Update1()    {        StartCoroutine(UpdateVersion());    }    IEnumerator UpdateVersion()    {        completeLoad = false;//未完成下载        updateFile = true;//更新文件中        string updateUrl = "http://localhost:1337/version"; //服务器网址        loadJson(updateUrl);        while (!completeLoad)        {            yield return null;        }        this.StartCoroutine(writeFile());    }    void loadJson(string url)    {        this.StartCoroutine(getData(url));    }    IEnumerator getData(string url)    {        WWW www = new WWW(url);        yield return www;        string json = www.text.ToString();        GameInfo data = GameInfo.CreateFromJSON(json);        UpdateData = data;        _version = data.version;//将更新的版本同步到游戏        _totalRound = data.totalRound;//将更新的总轮数同步到游戏        completeLoad = true;//完成下载    }IEnumerator writeFile()//写入文件    {        string jsonUrl = "Assets/Data/Game_Info.json";        StreamWriter sw;        sw = new StreamWriter(jsonUrl, false);        string json = JsonUtility.ToJson(UpdateData);        sw.WriteLine(json);//写入流        sw.Close();//关闭流        sw.Dispose();//销毁流        yield return null;        updateFile = false;//更新完毕    }


如果需要更新,弹出提示框

如果不需要更新,就直接进入游戏

当然如果想要真正发布,需要改一改的,使用PersistentDataPath去读写文件,以PC端为例

print(Application.persistentDataPath);

打印的结果如下


还有很多不懂的,等我懂了再写深入

参考博客Unity3D学习笔记(10)

原创粉丝点击