程序入口

VirtualCityMgr
做了几件事

  1. 设置分辨率
  2. 设置帧率
  3. 移动端启动log记录
  4. 启动缓冲池
  5. 启动TimeManager
  6. 启动版本更新,资源更新,AssetMgr
  7. 启动读配置表
  8. 启动sdk相关(wxpay,alipay)
void Start()
{
m_instance = this;

if (Application.isMobilePlatform == false)
{
DataMgr.m_resolution = 1.0f;
}
int width = (int)(Screen.currentResolution.width * DataMgr.m_resolution);
int height = (int)(Screen.currentResolution.height * DataMgr.m_resolution);
Screen.SetResolution(width, height, true);

Debug.Log("屏幕分辨率:" + Screen.width + "," + Screen.height);
Screen.sleepTimeout = SleepTimeout.NeverSleep;
Application.targetFrameRate = 30;

m_tarns = this.transform;
if (Application.isMobilePlatform == true)
{
MyLogCallback.Instance.Startup();
}

//if (PublicFunc.IsExistFile("NewGuide.txt") == false)
//{
// DataMgr.m_isNewGuide = true;
//}
//启动全局缓冲池
PoolMgr.Instance.StartUp();

//启动消息中心
MessageCenter.Instance.StartUp();
Framework.Tools.TimeManager.Instance.StartUp();
SmssMgr.Instance.StartUp();
Loom.Current.StartUp();
HttpMgr.Instance.Startup();
SpProto.StartUp();
#if UNITY_EDITOR && EditorLoadAb

VcData.Instance.LoadData(Init);
#else
AssetMgr.Instance.Init(Init);
#endif

if (Application.platform == RuntimePlatform.IPhonePlayer)
{
AliComponent.Instance.Startup();
WeChatComponent.Instance.Startup();
}

APK更新

  1. 本地大版本号比对服务器cdn下BigVersion.txt,里面包含大版本号和apk包大小信息
  2. 不一致启动下载apk,下载完后启动安装apk。
  3. 大版本更新安装下好的apk,兼容任意安卓5.0,7.0,8.0版本
IEnumerator doBigVersionUpdate()
{

string dataPath = AppConst.BigVerionSavePath + "/"; //数据目录
string url = AppConst.BigVersionDownUrl + "/";
string apkName = "vc.apk";
if (Directory.Exists(AppConst.BigVerionSavePath) == false)
{
Directory.CreateDirectory(AppConst.BigVerionSavePath);
}
WWW www = new WWW(url + "BigVersion.txt");
yield return www;
if (www.error != null)
{
Debug.LogError("大版本检测失败:" + www.error.ToString());
//StartGameManager();
Debug.Log("不能更新,开始游戏");

yield break;
}

string[] remoteVersion = www.text.Split('|');
if (remoteVersion[0] == VirtualCityMgr.m_instance.m_bigVersion)
{
Debug.Log("大版本一致");
}
else
{
m_isBigVersionUpdate = true;
DataMgr.m_downTotal = long.Parse(remoteVersion[1]) * 1024 * 1024;
List<string> updateUrls = new List<string>();
List<string> updateFiles = new List<string>();
updateUrls.Add(url + apkName);
updateFiles.Add(dataPath + apkName);
UIManager.Instance.PushPanelFromRes(UIPanelName.firstpanel, UIManager.CanvasType.Screen);
if (DataMgr.m_downTotal > 0)
{
ispanel ispanel = (ispanel)UIManager.Instance.PushPanelFromRes(UIPanelName.ispanel, UIManager.CanvasType.Screen, false, false);
ispanel.SetContent("提示", "本次大版本更新需要下载" + (DataMgr.m_downTotal / 1024d/1024d).ToString("0.00") + "MB资源");
ispanel.m_cancel = () =>
{
Debug.Log("取消");
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif


};

while (ispanel.m_isClickOk == false)
{
yield return null;
}

yield return StartCoroutine(doDownResources(updateFiles, updateUrls));
}

Debug.Log("apk下载完成:"+ dataPath + apkName);
UIManager.Instance.PopSelf();

string path = dataPath + apkName;
path = path.Replace(":", "");
AndroidFunc.InstallApk(path);

}
yield return null;
}

资源更新

  1. apk版本号一致情况下,获取服务器cdnfiles.txt文件
  2. files.txt信息,每行格式为 ab包 | md5| ab包大小
  3. Unity3d+虚拟城市:更新,登录流程:APK更新,资源更新,注册登录_unity3d

  4. 文件逐行扫描,跟本地文件对比,本地md5与服务器不一致或者缺少本地文件,把此文件加入更新列表中
private IEnumerator doUpdateResources()
{
Debug.Log("更新资源");
if (AppConst.m_isUpdateRes == false)
{
yield break;
}
UIManager.Instance.PushPanelFromRes(UIPanelName.firstpanel, UIManager.CanvasType.Screen);
//LuaCall("UpdateResourceAPI", "ShowUpdateInfo", UpdateResourcePanelApi, 1, 0);
Debug.Log("打开了第一个面板");
string dataPath = AppConst.AbDataPath + "/"; //数据目录
string url = AppConst.DownUri + "/";

if (Directory.Exists(AppConst.AbDataPath) == false)
{
Directory.CreateDirectory(AppConst.AbDataPath);
}
WWW www = new WWW(url + "files.txt");
Debug.Log("下载的files的url:"+www.url);
yield return www;
if (www.error != null)
{
Debug.LogError("Update Resources Failed! :" + www.error.ToString());
//StartGameManager();
Debug.Log("不能更新,开始游戏");
UIManager.Instance.PopSelf();
yield break;
}

List<string> updateUrls = new List<string>();
List<string> updateFiles = new List<string>();

File.WriteAllBytes(dataPath + "files.txt", www.bytes);
string[] files = www.text.Split('\n');
int needUpdateSize = 0;
for (int i = 0; i < files.Length; i++)
{
var file = files[i];
if (string.IsNullOrEmpty(file))
continue;

string[] keyValue = file.Split('|');
string filename = keyValue[0];
string localfile = (dataPath + filename).Trim();
string path = Path.GetDirectoryName(localfile);
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
string fileUrl = url + filename;
bool needUpdate = !File.Exists(localfile);
if (!needUpdate)
{
string remoteMd5 = keyValue[1].Trim();
string localMd5 = PublicFunc.GetFileMD5(localfile);
needUpdate = !remoteMd5.Equals(localMd5);
}

if (needUpdate)
{
updateUrls.Add(fileUrl);
updateFiles.Add(localfile);

needUpdateSize += int.Parse(keyValue[2]);
}
}
DataMgr.m_downTotal = needUpdateSize * 1024;

if (DataMgr.m_downTotal > 0)
{
Debug.Log("打开了更新确认下载面板");
ispanel ispanel = (ispanel)UIManager.Instance.PushPanelFromRes(UIPanelName.ispanel, UIManager.CanvasType.Screen,false,false);
ispanel.SetContent("提示", "本次更新需要下载" + (DataMgr.m_downTotal / 1024d / 1024d).ToString("0.00") + "MB资源");
ispanel.m_cancel = () => { Debug.Log("取消");
#if UNITY_EDITOR
EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif


};

while (ispanel.m_isClickOk == false)
{
yield return null;
}

yield return StartCoroutine(doDownResources(updateFiles, updateUrls));
}
UIManager.Instance.PopSelf();
//StartGameManager();
}

文件下载器

WebClient下载,实时通知下载进入给主进程

public class FileDownloder : MonoBehaviour {

public System.Diagnostics.Stopwatch sw;

public string DownloadingFileName;
public float DownloadingSpeed;
public bool DownloadComplete;
long m_lastDown = 0;
public FileDownloder()
{
sw = new System.Diagnostics.Stopwatch();
DownloadComplete = false;
DownloadingFileName = "";
}

public bool DownloadFile(string url, string file)
{
if (DownloadingFileName == "")
{
DownloadComplete = false;
DownloadingFileName = file;

Loom.RunAsync(() =>
{
using (WebClient client = new WebClient())
{
sw.Start();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);
//Debug.Log(String.Format("Download URL:{0} FILE:{1}", url, file));
client.DownloadFileAsync(new Uri(url), file);
}
});
return true;
}
else
{
return false;
}
}

private void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
sw.Reset();
m_lastDown = 0;
DownloadComplete = true;
DownloadingFileName = "";
}

private void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
DataMgr.m_downCur += (e.BytesReceived - m_lastDown);
m_lastDown = e.BytesReceived;
DownloadingSpeed = float.Parse((e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));

Loom.QueueOnMainThread((param) =>
{
EventManager.Instance.DispatchEvent(Common.EventStr.UpdateProgress, new EventDataEx<float>(DownloadingSpeed));
}, null);
if (e.ProgressPercentage == 100 && e.BytesReceived == e.TotalBytesToReceive)
{
sw.Reset();
m_lastDown = 0;
DownloadComplete = true;
DownloadingFileName = "";
}
}
}

读完数据进入loginpanel

这台手机第一次打开游戏

  1. 如果第一次打开游戏,向固定登录http地址,请求到HallServer,ChatServer ip地址端口号,连接
  2. 打开注册窗口,通过SMSSDK短信验证码
  3. Unity3d+虚拟城市:更新,登录流程:APK更新,资源更新,注册登录_注册登录_02

  4. 验证码通过,发送手机号给HallServer,确定是新用户还是注册用户
  5. 最后得到登陆信息,发送登陆协议,等回包正式进入游戏第一个场景

全部源码下载

​https://github.com/luoyikun/VirtualCity​

演示视频

​https://www.bilibili.com/video/BV1sQ4y1v7d4?spm_id_from=333.999.0.0​