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)
- Unity3D学习(16)之初识DDD
- 【和我一起学习Unity3D】初识Unity3D
- 领域驱动/DDD模型初识
- Unity3D 学习笔记(一)初识U3D
- unity3D游戏开发一之初识unity
- unity3D游戏开发一之初识unity
- unity3D游戏开发一之初识unity
- 初识Unity3D
- 初识Unity3D
- jQuery学习之--初识
- Swift学习之初识
- 【Docker学习】之 初识
- python 学习之初识
- DDD学习笔记
- DDD之通用语言
- DDD之模型
- Unity3D学习之刚体
- unity3d学习之光源
- UVA 11134 Fabled Rook 枚举 multiset加速
- 关于海康威视网络摄像机二次开发问题
- 2-7 laravel中的Eloquent入门
- Trailing Zeroes (III) (数论(二分查找值,规律))
- Spring Boot学习笔记-Nginx+Jar包部署项目
- Unity3D学习(16)之初识DDD
- 文章标题
- 今天收到阿里巴巴一个电话面试
- babel-plugin-import不生效的问题
- [二进制分组 dsu on tree 二次函数] Codechef KILLER Painting Tree
- C++上机实验五——数组1
- linux内核分析1--反汇编分析
- 浅谈动态代理
- DFS的两种非递归的实现方法