本文节选自洪流学堂公众号技术专栏《大话Unity2019》,未经允许不可转载。
洪流学堂公众号回复专栏
,查看更多专栏文章。
洪流学堂,让你快人几步。你好,我是郑洪智。
小新:“大智,最近我在做一个虚拟展厅的demo,你说我怎么最大程度提高这个程度的扩展性呢?最好图片和文字说明是可以动态替换的。”
大智:“这个问题用我们这两周学的配置文件和读取文件的知识,串起来就可以搞定这个问题了!”
小新:“那你可以不可以给我提示一下?”
大智:“没问题,基本思路是这样的:”
- 使用json配置图片的路径和文字说明
- 动态获取外部的图片,这样图片可以在外面替换,不用重新发布程序
实战:动态配置图片
小新:“好,我大概有思路了,我先试试。”
创建场景
1、先创建一个虚拟展厅的场景,我这里偷懒就使用一个3D Object > Quad创建了一面墙,然后调整物体的Scale。
2、由于主要是展示图片和文字,在这里就用3D UI进行搭建,这里面有几点需要注意。
- 注意图片选择Raw Image组件。RawImage可以直接显示Texture类型的贴图,而不用转换为Sprite。
- Canvas设置为World Space,然后设置位置和Scale,符合三维场景中墙壁的尺寸。
- 这里我将Text作为了图片的子物体(如果你的层级结构不同,下面获取图片对应的代码需要做相应的修改)
配置图片和说明
配置的json文件如下:
[
{
"Id": 1,
"Url": "http://www.zyzw.com/sjmhxs/sjmhxst/sjmhxst003.jpg",
"Name": "蒙娜丽莎"
},
{
"Id": 2,
"Url": "http://www.zyzw.com/sjmhxs/sjmhxst/sjmhxst003.jpg",
"Name": "蒙娜丽莎"
},
{
"Id": 3,
"Url": "http://www.zyzw.com/sjmhxs/sjmhxst/sjmhxst003.jpg",
"Name": "蒙娜丽莎"
}
]
一定要注意保存的文件不要有BOM头。
这里面你会注意到我加了一个Id,这个Id是用来和场景中的物体进行对应,便于修改与调试。否则我们就只能通过数组的索引来访问,很不方便。
不知道你还记不记得,Unity自带的JsonUtility无法解析最外层是数组的JSON字符串,如果你像我上面那样写,需要导入LitJson。
ConfigManager
由于我们很多对象中都需要获取这个配置信息,所以我们通过一个通用的管理类来获取配置的数据。
using System;
using System.Collections;
using System.IO;
using System.Linq;
using LitJson;
using UnityEngine;
using UnityEngine.Networking;
// 图片信息
public class PicData
{
public int Id;
public string Url;
public string Name;
}
public class ConfigManager : MonoBehaviour
{
// 设置为静态,方便在其他地方访问
public static PicData[] Data;
IEnumerator Start()
{
var uri = new Uri(Path.Combine(Application.streamingAssetsPath, "data.json"));
var request = UnityWebRequest.Get(uri);
yield return request.SendWebRequest();
if (request.isHttpError || request.isNetworkError)
Debug.Log(request.error);
else
ParseJsonStr(request.downloadHandler.text);
}
// 解析获取到的JSON字符串
private void ParseJsonStr(string json)
{
Data = JsonMapper.ToObject<PicData[]>(json);
Debug.Log(Data.Length);
}
// 使用Linq获取第一个符合Id的数据
public static PicData GetData(int id)
{
return Data.First(t => t.Id == id);
}
}
记得把LitJson导入到工程中,如果忘了回去看看195节哦。
创建一个Manager空物体,将这个脚本挂到Manager空物体上。
针对每个图片物体的脚本
下面的代码用于从配置类中获取信息,然后去下载对应的图片。
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Picture : MonoBehaviour
{
public int Id;
IEnumerator Start()
{
// 防止配置文件还没读取完毕
while (ConfigManager.Data == null) yield return null;
var data = ConfigManager.GetData(Id);
// 如果Id有误,没有对应的数据则退出此协程
if (data == null) yield break;
var uri = new Uri(data.Url);
// 使用UnityWebRequestTexture类来获取图片
var request = UnityWebRequestTexture.GetTexture(uri);
yield return request.SendWebRequest();
if (request.isHttpError || request.isNetworkError)
Debug.Log(request.error);
else
GetComponent<RawImage>().texture = DownloadHandlerTexture.GetContent(request);
GetComponentInChildren<Text>().text = data.Name;
}
}
将这个脚本挂在Pic1、Pic2、Pic3物体上并设置相应的Id即可。
总结
最后的结果如下:
如果你想改变墙上的图片和内容,即使发布出来以后,也只需要修改json文件即可,不需要重新发布。
今日思考题
大智:“如果使用本地的图片,看看需要做哪些改变呢?”
小新:“好嘞!”
大智:“收获别忘了分享出来!也别忘了分享给你学Unity的朋友,也许能够帮到他。”
洪流学堂公众号回复专栏
,查看更多专栏文章。
《大话Unity2019》,大智带小新学Unity2019的有趣经历,让你学Unity更简单。