unity3d如何更新 热更新什么意思

Unity Android DLL 热更新与加密 | 杨振林的博客
游戏开发者
大家好,我是杨振林,一位 iOS / Android / Unity 开发者,目前从事手机游戏开发工作,希望和大家多多交流。
作者:杨振林 yangzhenlin.com
本文主要介绍,在安卓环境下,通过更换或解密 Unity-Mono 加载的 Assembly-CSharp.dll 数据文件的方法,达到更新或加密代码的目的。首先介绍如何编译生成 libmono.so,然后讲述通过修改 mono - image.c - mono_image_open_from_data_with_name 方法达到修改 DLL 的目的。
工具与环境
OS macOS Sierra 10.12.2
Mono mono unity-5.5
Unity Unity 5.5.0f3 for Mac
Android SDK
Android NDK Android NDK r10e
Xcode Command Line Tools
pkg-config
Xcode Command Line Tools 安装方法 xcode-select --install
autoconf automake libtool pkg-config 四项可以使用 Homebrew 安装。
获取 Homebrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
安装 brew install autoconf automake libtool pkg-config
编译 libmono.so
【步骤一】选择 Unity 版本对应的 Mono 分支,例如本文选择 Unity 5.5.0f3 则对应 Mono 的版本是 unity-5.5。进入 mono 根目录,mono 根目录是编译 Mono 的工作目录。
【步骤二】修改./external/buildscripts/build_runtime_android.sh和./external/buildscripts/build_runtime_android_x86.sh。
build_runtime_android_x86.sh主要负责编译 x86 架构下的 libmono.so。
build_runtime_android.sh主要负责编译 arm 架构下的 libmono.so,然后调用build_runtime_android_x86.sh。
build_runtime_android_x86.sh去掉-g,去掉调试符号。
build_runtime_android.sh将 CFLAGS 下的-g修改为-O2,去掉调试符号,并增加优化符号。
-g 调试符号
-O2 优化符号
注意:“O”是英文第15个字母的大写,不是零。
build_runtime_android.sh删除编译armv5、armv6_vfp,只剩下armv7a。
【步骤三】在 mono 根目录下,执行./external/buildscripts/build_runtime_android.sh。
编译成功后,终端会提示:
Build SUCCESS!
Build failed? Android STATIC/SHARED library cannot be found... Found
4 libs under builds/embedruntimes/android
drwxr-xr-x
136 12 30 11:40 armv7a
drwxr-xr-x
136 12 30 11:42 x86
在./builds/embedruntimes/android目录下,会有armv7a和x86架构下的libmono.so。
DLL 热更新与加密原理
打开./mono/metadata/image.c文件,找到mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name)函数。
char *data DLL 数据的指针
guint32 data_len DLL 数据的长度
const char *name DLL 名
使用glib库的g_message方法,在 Android Logcat 中输出 Assembly-CSharp.dll 的 name = /data/app/包名-1.apk/assets/bin/Data/Managed/Assembly-CSharp.dll。
从参数可以看出,进入mono_image_open_from_data_with_name函数后,通过辨认name,可以对data和data_len做出修改,从而影响实际加载的 DLL。
DLL 加密与解密
从 Unity 导出 Android 工程后,可以拿到Assembly-CSharp.dll,在 Unity 中编写的大多数代码都会在这个动态链接库下。通过一些加密算法对此 DLL 进行加密后,初学者使用一些反编译工具就无法看到源代码了。示例工程中,首先将Assembly-CSharp.dll的首字节+1(加密),然后在mono_image_open_from_data_with_name中将Assembly-CSharp.dll的首字节-1(解密),从而实现了对 DLL 的加密过程。
DLL 热更新
首先在mono_image_open_from_data_with_name函数上面补充两个函数。实现从可读写路径中读取 DLL 的操作。
static FILE *OpenFileWithPath(const char *path)
const char *fileMode = "rb";
return fopen (path, fileMode);
static char *ReadStringFromFile(const char *pathName, int *size)
FILE *file = OpenFileWithPath (pathName);
if (file == NULL)
fseek (file, 0, SEEK_END);
int length = ftell(file);
fseek (file, 0, SEEK_SET);
if (length & 0)
fclose (file);
char *outData = g_try_malloc (length);
int readLength = fread (outData, 1, length, file);
fclose(file);
if (readLength != length)
g_free (outData);
return outD
改写mono_image_open_from_data_with_name函数,当发现可读写路径中存在/data/data/包名/files/Assembly-CSharp.dll时,加载新的 DLL。
MonoImage *
mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name)
////////Modify Begin////////
int datasize = 0;
if(name != NULL && strstr (name, "Assembly-CSharp.dll"))
//重新计算路径,这里假设包名以“com.”开头。
const char *_pack = strstr (name, "com.");
const char *_pfie = strstr (name, "-");
char _name[512];
memset(_name, 0, 512);
int _len0 = (int)(_pfie - _pack);
memcpy(_name, "/data/data/", 11); //_name = "/data/data/"
memcpy(_name + 11, _pack, _len0); //_name = "/data/data/com.Company.ProductName"
memcpy(_name + 11 + _len0, "/files/Assembly-CSharp.dll", 26); //_name = "/data/data/com.Company.ProductName/files/Assembly-CSharp.dll"
char *bytes = ReadStringFromFile (_name, &datasize);
if (datasize & 0)
data_len =
////////Modify End////////
MonoCLIImageInfo *
MonoImage *
if (!data || !data_len) {
if (status)
*status = MONO_IMAGE_IMAGE_INVALID;
return NULL;
if (need_copy) {
datac = g_try_malloc (data_len);
if (!datac) {
if (status)
*status = MONO_IMAGE_ERROR_ERRNO;
return NULL;
memcpy (datac, data, data_len);
////////Modify Begin////////
if(datasize & 0 && data != 0)
g_free (data); //释放新 DLL 的数据
////////Modify End////////
image = g_new0 (MonoImage, 1);
image-&raw_data =
image-&raw_data_len = data_
image-&raw_data_allocated = need_
image-&name = (name == NULL) ? g_strdup_printf ("data-%p", datac) : g_strdup(name);
iinfo = g_new0 (MonoCLIImageInfo, 1);
image-&image_info =
image-&ref_only =
image-&ref_count = 1;
image = do_mono_image_load (image, status, TRUE, TRUE);
if (image == NULL)
return NULL;
return register_image (image);
修改代码后,重新编译 Mono。将./builds/embedruntimes/android目录中对应armv7a和x86架构下的libmono.so分别替换 Unity 导出的 Android 工程中的libmono.so。然后就可以进行安卓打包了。
最近的文章
作者:杨振林 yangzhenlin.com本篇是Unity iOS 插件开发与SDK接入的姊妹篇。概述虽然使用 Unity 可以完成制作一款游戏的绝大部分工作,但研发过程中难免会遇到以下几个问题,需要建立 Unity 与 Android 的交互。
接入代理商的登录和支付功能,但代理商只提供 Android 平台 SDK。
一些优秀的插件或工具只提供 Android 平台 SDK。
接入微博、微信等平台的分享功能。
本文通过“Unity 与 Andr...&
更早的文章
作者:杨振林 yangzhenlin.com本文讲解服务器配置SSL证书部署HTTPS网站。环境是阿里云服务器ECS ,系统是CentOS6 64bit,Web服务器是Nginx。需要SSL模块的支持。签发SSL证书的CA机构是 沃通电子认证服务有限公司 WoSign CA Limited。部署HTTPS网站一般需要有服务器的控制权,(云)主机、VPS均可,虚拟主机基本上做不到。具体步骤如下:向CA机构申请SSL证书SSL证书的价格一般较贵,申请之前可以去网上搜索一下,最好选择信任度高、浏...&五种方案:
1.LUA(需要LUA与C#绑定,性能低,需要掌握两门语言)
2.ILRT(总体最佳方案)
3.JSB(类似LUA)
4.直接更dll(最好方案,但IOS不能用)
5.将CS当成脚本(类似直接更dll,只不过是动态编译cs脚本,同样IOS不能用)
待编辑。。。
阅读(...) 评论()请完成以下验证码
后使用快捷导航没有帐号?
请完成以下验证码
查看: 602回复: 13
unityLua热更新教程
元素币活跃度贡献值
unity3D区版主
土豪金2041
在线时间1548 小时
楼主-元素创造者
马上注册成为元素者,获取海量元素资源,结识各路大神级人物
才可以下载或查看,没有帐号?
本帖最后由 狼之独步 于
14:47 编辑
资源大小:1.17GB 更新时间:价格:20元素币 销售总额:580元素币 购买人数:29尊敬的游客 ,本内容需要支付 20元素币 来下载,您可以 或者 。也可使用获取 同等点击次数 ,来轻松下载。
活跃度 +15
看着有点像siki的。。。。
伟大的元素神,送我一个水灵灵的妹纸吧!
享有帖子相关版权3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和的同意4、所有内容仅供个人学习、研究之用,请勿用于商业用途5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意7、管理员和版主有权不事先通知发贴者而删除本文', this.href);">论坛版权
元素币活跃度贡献值
元素皇, 积分 82150, 距离下一级还需 17850 积分
元素皇, 积分 82150, 距离下一级还需 17850 积分
在线时间2031 小时
沙发-元素射日者
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
unity3D区版主
土豪金2041
在线时间1548 小时
板凳-元素追月者
哈哈,就是
伟大的元素神,送我一个水灵灵的妹纸吧!
元素币活跃度贡献值
元素王, 积分 6840, 距离下一级还需 23160 积分
元素王, 积分 6840, 距离下一级还需 23160 积分
在线时间91 小时
地板-元素观星者
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 1729, 距离下一级还需 271 积分
元素侠, 积分 1729, 距离下一级还需 271 积分
在线时间23 小时
元素帖子强,满满正能量!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 1729, 距离下一级还需 271 积分
元素侠, 积分 1729, 距离下一级还需 271 积分
在线时间23 小时
我们先定一个能达到的小目标,先赚它一亿元素币
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 4485, 距离下一级还需 515 积分
元素魔, 积分 4485, 距离下一级还需 515 积分
在线时间52 小时
一个神语言要诞生了
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 24148, 距离下一级还需 5852 积分
元素王, 积分 24148, 距离下一级还需 5852 积分
在线时间535 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 24148, 距离下一级还需 5852 积分
元素王, 积分 24148, 距离下一级还需 5852 积分
在线时间535 小时
我们先定一个能达到的小目标,先赚它一亿元素币
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 708, 距离下一级还需 1292 积分
元素侠, 积分 708, 距离下一级还需 1292 积分
在线时间9 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素侠, 积分 1334, 距离下一级还需 666 积分
元素侠, 积分 1334, 距离下一级还需 666 积分
在线时间22 小时
我们先定一个能达到的小目标,先赚它一亿元素币
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素魔, 积分 3954, 距离下一级还需 1046 积分
元素魔, 积分 3954, 距离下一级还需 1046 积分
在线时间89 小时
我们先定一个能达到的小目标,先赚它一亿元素币
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素王, 积分 7108, 距离下一级还需 22892 积分
元素王, 积分 7108, 距离下一级还需 22892 积分
在线时间137 小时
还没有设置签名!您可以在此展示你的链接,或者个人主页!
元素币活跃度贡献值
元素师, 积分 548, 距离下一级还需 252 积分
元素师, 积分 548, 距离下一级还需 252 积分
在线时间7 小时
感谢楼主分享!
还没有设置签名!您可以在此展示你的链接,或者个人主页!
【拥有1000元素币】你就可以领取
【拥有3000元素币】其实也是很容易的事情
【50小时】的学习,已经证明了你自己,这件法袍是你的了,由于使用了简陋的材料,能穿一个月已经不错了!
【600小时】在线,足以驾驭魔神的力量,他们会守护你!
加入【元素1年】自古美女爱英雄,这是千年不变的定律!英雄盾会为你们见证
加入【元素6月】在元素冒险的时候,你一定会用到它,尤其是在遇到像小强这种可怕生物时
达成成就【中级追猎者】在元素悬赏中50次被评为最佳答案 ,双十二特别礼品
达成成就【元素智者】在元素知道
超过5次解决提问者的问题
达成成就【元素皇者】升级成为元素皇
元素【鼓励师】职业标志,从此走上了不一样的巅峰之路。元素鼓励师,一句你就湿!
【元素晶石】
只有【元素大神】才能拥有,自由出入元素秘境之钥
【真爱之花】
情人节限量版,据说此花会带来桃花运!
平时一次性兑换土豪金超过3000,圣诞节期间一次性兑换土豪金超过500即可获取!
守望者【猎空】
据说可以随时呼唤猎空,需要消耗100点贡献
【MP50】这次的冒险才刚刚开始,和所有故事一样,你得先有一个属于自己的法杖!即使他的法力会在30天后消失
达成成就【闪电链】发布55张包含3条以上内部相关链接的帖子
元素推荐-友情提示 /1
每周一次的扩散大招带来更多元素币收益!
快速登录:Unity Dll热更新
来源:博客园
最简单的案例代码,备后需使用 using System.C using System.Collections.G using System.X using UnityE using System.R using System.IO; using S ///
/// 加载web代码 ///
public class LoadWebScript : MonoBehaviour { static LoadWebScript _ public static LoadWebScript Instance { get { if (_instance != null) { return _ } else { GameObject g = new GameObject("LoadWeb"); return g.AddComponent(); } } } ///
/// 代码网络地址 ///
public string NetPath { get { XmlDocument doc = new XmlDocument(); doc.Load(Application.streamingAssetsPath+ "/WebConfig/webconfig.xml"); XmlElement list= doc.DocumentE XmlElement ele = (XmlElement)list.SelectSingleNode("remote"); string path = ele.GetAttribute("path"); if (string.IsNullOrEmpty(ScriptSpaceName)) { ScriptSpaceName = ele.GetAttribute("script"); } } } private string ScriptSpaceN private string ScriptFullName { get { return ScriptSpaceName + ".dll"; } } private string OutScriptPath { get { return Application.streamingAssetsPath + "/OutScript/"; } } private void Awake() { StartCoroutine(UpdateScript()); } IEnumerator UpdateScript() { print(NetPath); WWW www = new WWW(NetPath+"/"+ScriptFullName); if (www.error != null) { Debug.LogWarning(www.error); Load(); } else { StartCoroutine(SaveScript(www.bytes,Load)); } } IEnumerator SaveScript(byte[] b,Action act) { FileStream fs = File.Open(OutScriptPath+ScriptFullName, FileMode.Create); fs.Write(b, 0, b.Length); fs.Close(); act.Invoke(); } private void Load() { if (File.Exists(OutScriptPath + ScriptFullName)) { print(OutScriptPath + ScriptFullName); byte[] _byte = File.ReadAllBytes(OutScriptPath + ScriptFullName); print(_byte.Length); Assembly Ass = Assembly.Load(_byte); Type t = Ass.GetType(ScriptSpaceName + ".OutManager"); print(ScriptSpaceName + ".OutManager"); print(t); MethodInfo m = t.GetMethod("Main"); m.Invoke(null, null); } } }
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动另类Unity热更新大法:代码注入式补丁热更新 - 简书
另类Unity热更新大法:代码注入式补丁热更新
眼看Unity引擎热火朝天,无数程序猿加入到了Unity开发的大本营。
一些老项目,当时ulua/slua还不如今天那样的成熟,因此他们选择了全c#开发;也有一些出于性能考虑,全c#开发;也有一些没有太丰富运营经验的开发团队,没有想太多,用全c#爽爽地开发。
用C#开发爽爽的日子一天一天的过去了,直到突然有一天,策划老大说:“我们得做个热更新模块!”;突然有一天,老板说:“别人游戏用Lua热更新,为什么我们不行?”;突然有一天,运营说:“线上游戏出了个bug,重新编译出包审核得几天啊!”——嗯,这时候,受伤的总是程序猿。
有没有亡羊补牢,临危受命的折衷方法?可以不用把C#改成Lua,可以不用区分平台(AndroidDLL重载IOS却不行),可以对任何代码做修复的方法?
有的,并且用很笨的一句代码来概括:
class Fucker {
void Fucking() {
if (PatchScript.HasPatchScript("Fucker.Fucking")) {
// do patch fuck
PatchScript.CallPatchScript("Fucker.Fucking");
// do origin fuck
Log.Info("I am a original fuck");
往所有的函数注入代码,当存在补丁脚本时执行补丁脚本,不存在时执行原代码。
因此,本文的热更新等同于打补丁。
什么是热更新?
吐槽一点,虽然我们这个方法确实将热更新做成模块了,但这绝对是迫不得已的。 热更新绝对不是一个功能模块能实现,它是一个底层架构所决定的。要说一个项目不好,无法实现热更新,这归根到底是架构没想好、策划没坚持、程序没执着、运营懒得管等等各种各样复杂原因所导致的。
我心目中理想热更新是怎样?要热!:
对任意部位的代码进行修改;
运行时,自动下载更新代码,尔后无需重启;
运行时,立即重载代码,并继续运行;
兼顾开发环境与生产环境的简便性;
热更新在Web开发领域非常普遍,毕竟HTTP是无状态的;而游戏这种高实时性的开发相比,要想做好热更新就确实需要架构层的更多考虑了。怎么做好热更新,我们还是回到主题,接下来介绍方法,可以达到什么目的:
对任意部位的方法体代码进行修改;
运行时,立即重载代码,并继续运行
语言无关:同样的思路可以应用在Java、C#、Go、C++等等
使用起来不太方便
亡羊补牢专用
代码注入补丁热更新大法流程
上面说了很多废话。接下直奔主题,要怎样做到:
class Fucker {
void Fucking() {
if (PatchScript.HasPatchScript("Fucker.Fucking")) {
// do patch fuck
PatchScript.CallPatchScript("Fucker.Fucking");
// do origin fuck
Log.Info("I am a original fuck");
我们要针对Fucker类的Fucking方法进行更新,则新建Lua脚本Fucker.Fucking.lua
-- 文件名Fucker.Fucking.lua
function Func()
print("I am a patch fuck!")
return Func
一个补丁脚本就此完成,当程序运行到Fucking函数时,实际上它执行的是Lua脚本,变相的实现了热更新的功能——改变代码的执行行为。
STEP 1:执行环境
本文针对Unity游戏开发,那么原语言,当然是C#了;而打补丁的语言,当时Lua了;
在这里我们使用SLua插件,它的高质量代码和强大的反射功能,非常适合代码注入补丁热更新。
class PatchScript
public bool HasPatchScript(string path)
return File.Exists("Script/" + path + ".lua");
public void CallScript(string path)
string scriptCode = File.ReadAllString(path);
var luaFunc = this.luaState.doScript(scriptCode) as LuaF
luaFunc.call();
STEP 2:代码注入
嗯,执行环境,非常的简单,不就是简单的if判断吗? 估计最令人迷惑的部分就是,如何往所有的C#函数体前部分插入代码了。
我们要做的,遍历所有的c#文件,取得class类名,然后再分析函数名,定位函数在代码中的起始位置、获取函数的参数列表、参数类型……等等。看起来很复杂,是不是要对c#做语法分析、词法分析了?感觉工作量很大啊。
幸好,轮子已经做好了。这里要用到一个重要的库——。包括IDE MonoDevelop中的语法智能提示、重构都是基于这个库进行的。有了它,语法分析词法分析仅仅是API的调用而已。
我们要做的,就是使用NRefactory找出C#的方法体,并插入代码:
using (var script = new DocumentScript(document, formattingOptions, options))
CSharpParser parser = new CSharpParser();
SyntaxTree syntaxTree = parser.Parse(code, srcFilePath);
foreach (var classDec in syntaxTree.Descendants.OfType&TypeDeclaration&())
if (classDec.ClassType == ClassType.Class || classDec.ClassType == ClassType.Struct)
var className = classDec.N
foreach (var method in classDec.Children.OfType&MethodDeclaration&())
var returnType = method.ReturnType.ToString();
if (returnType.Contains("IEnumerator") || returnType.Contains("IEnumerable"))
// 暂不支持yield!
// 。。。。这里找到了方法体! 开始进行插入!
我把使用NRefactory对C#方法体注入的代码,抽象成一个单独的类,看文章底部。
STEP 3:编写Lua补丁
补丁的方法,在上文“代码注入补丁热更新大法流程”中已有提及:
对需要打补丁的函数,创建Lua脚本
如上文中要改变Fucker.Fucking函数的执行行为,则创建Fucker.Fucking.lua脚本文件,脚本末端返回一个Lua函数。
本文着重提供了一种思路,而不提供完整的源代码,毕竟涉及到部分人的商业利益,遗憾点到即止。
使用下面的MethodInjector类,会把函数的参数值也进行解析、预编译指令引入、并且可以在Lua补丁中控制是否在执行补丁后,继续执行原C#代码,基本能达到大部分的需求了。
这里举例一个更好的方案:注入DLL的IL代码,而不是注入c#代码,来确保我们的c#代码不会被改动。
金融毕业误入歧途的前互联网公司资深技术架构师
自嘲Web/App/Game技术全栈,曾参与和主导多个社交产品、网络游戏
现任餐饮企业IT负责人,探索新零售智能升级.
人生就是一场认知升级的旅行, 期待你与我同行.
公众号:小霖的认知旅行
我已委托“维权骑士”(rightknights.com)为我的文章进行维权行动
https://rightknights.com/material/author?id=24775
由于网上关于Unity Lua学习的资料较少,本人也是刚入门U3D不久,现在项目准备基于LuaFramework用Lua做热更新开发,最近几天看了ToLua官网的文档说明,研究了一下C#与Lua的交互并做了一些尝试,发现实际入手还是遇到了很多配置文件,方法调用的坑,并根据学...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金相信有很多朋友...
用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你能获得这些料: 知道setContentView()之后发生了什么? ... Android 获取 View 宽高的常用正确方式,避免为零 - 掘金 相信有很多...
热更新实现方式:
1、使用Lua脚本编写游戏的UI或者其他逻辑,Lua是一个精悍小巧的脚本语言,可以跨平台运行解析,而且不需要编译过程。
2、使用C#Light
3、使用C#反射技术 关于AssetBundle
Unity提供了一个资源更新技术,就是通过AssetB...
Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua 是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeir...
春天悄无声息的来了,越来越多的人喜欢穿毛衣了,脱掉厚重大衣后,针织衫和时髦卫衣便成了早春主角。而V领毛衣更能体现女性的魅力。也成了众多明星网红的喜爱。 流线型V领露锁骨,线条流畅温和,气质性感又不失温柔。 后背流线修饰肩背线条, 均匀的竖向坑条显瘦没话说。 小V领+收腰+压...
我的拥有就在我身 生活在这一世界里,一个拥有丰富内在的人,就像在冬月的晚上,在漫天冰雪中拥有一间明亮、温暖、愉快的圣诞小屋。 如果一个人内在充足、丰富,不需要从自身之外寻求娱乐,那么,这个人就是一个最幸运的人。 能够自得其乐,感觉到万物皆备于我,并...
七月烈日灼心,八月秋风扫荡。 这两个月,很多人的目光都瞄准了中印边界,无论是在国内还是在海外,无论是漂在北上广还是扎根新农村,无论是生活在乌有乡还是理想国,无论你是“五毛”还是“美分”,在这件事面前,没有中国人能够置身事外。 从6月18日印度士兵开着挖掘机越境中国,到中国海...
农产品品牌策划和设计的要素是什么?品牌设计不仅是要宣传企业品牌形象,更重要的是展现产品特性,吸引顾客。下面迈上就给大家介绍一下农产品品牌设计的要素。 县域农产品品牌设计主要有以下几个要素: A、产品包装:包装颜色、款式、图案的确定,要依据消费者的喜好和和产品自身的特点及拟售...
单身久了,就成了习惯,当爱情可能来临,也会犹豫。如果一个人和你三观相近谈得来和脾气,在一起舒服而不会感到压力,愿意花时间陪你,能给你动力和期待,不管未来会怎样,如果遇到了,就应该珍惜。}

我要回帖

更多关于 unity3d如何更新 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信