程序入口
VirtualCityMgr
做了几件事
- 设置分辨率
- 设置帧率
- 移动端启动log记录
- 启动缓冲池
- 启动TimeManager
- 启动版本更新,资源更新,AssetMgr
- 启动读配置表
- 启动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更新
- 本地大版本号比对服务器cdn下BigVersion.txt,里面包含大版本号和apk包大小信息
- 不一致启动下载apk,下载完后启动安装apk。
- 大版本更新安装下好的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;
}
资源更新
- apk版本号一致情况下,获取服务器cdnfiles.txt文件
- files.txt信息,每行格式为 ab包 | md5| ab包大小
- 文件逐行扫描,跟本地文件对比,本地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
这台手机第一次打开游戏
- 如果第一次打开游戏,向固定登录http地址,请求到HallServer,ChatServer ip地址端口号,连接
- 打开注册窗口,通过SMSSDK短信验证码
- 验证码通过,发送手机号给HallServer,确定是新用户还是注册用户
- 最后得到登陆信息,发送登陆协议,等回包正式进入游戏第一个场景
全部源码下载
https://github.com/luoyikun/VirtualCity
演示视频
https://www.bilibili.com/video/BV1sQ4y1v7d4?spm_id_from=333.999.0.0