Unity的multi_compile和shader_feature编译指示符、shader variant和asset bundle

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com multi_compile编译指示符 multi_compile编译指示符的文档在这里。假如有以下的shader示例语句: #pragma multi_compile _USE_SEMITRANSPARENT _USE_OPAQUE #pragma multi_compile _MULTI_RED _MULTI_GREEN _MULTI_BLU ... fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); #if _MULTI_RED col = col * fixed4(1,0,0,1); #elif _MULTI_GREEN col = col * fixed4(0,1,0,1); #elif _MULTI_BLUE col = col * fixed4(0,0,1,1); #endif #if _USE_SEMITRANSPARENT col.a = 0.5; #elif _USE_OPAQUE col.a = 1.0; #endif return col; } 那么根据排列组合,就会有 $ 2 \times 3 = 6 $ 种代码段的组合,即分别是 _USE_SEMITRANSPARENT与_MULTI_RED , _USE_SEMITRANSPARENT与_MULTI_GREEN , _USE_SEMITRANSPARENT与_MULTI_BLUE , _USE_OPAQUE与_MULTI_RED , _USE_OPAQUE与_MULTI_GREEN , _USE_OPAQUE与_MULTI_BLUE。总得来说,就是各种排列组合对应编译生成的变体, $\color{#FF0000}{无论有没有被使用上,都会被编译打包到游戏包或者资源包中}$ 。所以 在运行时 ,可以使用 Material.

Unity3D的Model Import Settings window - Model tab

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 Model tab 当选中模型文件时,Inspector窗口就会显现出Import Settings窗口,且定位到Model页。可以通过在此页中调整参数控制模型导入的细节。 Model页上的各种属性可以分为三个区,分别是: 分区 细节 (A) Scene 和关卡场景相关的,比如光源和摄像机的导入,还有scale factor的设置 (B) Meshes. 和网格导入相关的属性 (C) Geometry 和网格拓扑相关的户型,比如的顶点的纹理UV,法线等等 2 Scene分区的属性描述表格 属性 功能 Scale Factor 在导入的原始模型文件的比例值,不适合项目中的预期比例时,设置此值,可作为一个全局的对原始模型的缩放比例值。 Unity的物理系统,期望游戏世界中的1米,就对应于原始模型文件的1个单位。 Convert Units 启用此选项,可将导入的原始模型文件的比例值。转换为Unity的比例。导入BlendShapes时,启用此属性可允许Unity导入网格物体的混合形状。 Import BlendShapes Enable this property to allow Unity to import blend shapes with your Mesh. See Importing blend shapes below for details.Note: Importing blend shape normals requires smoothing groups in the FBX file Import Visibility 导入FBX设置,这些设置将会确定是否启用MeshRenderer组件,当启用时改mesh可见 Import Cameras 从.FBX文件中导入在这些文件中定义的camera Import Lights 从.

Update、FixedUpdate、LateUpdate函数,定时器和帧速率

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 Update、LateUpdate、FixedUpdate函数 Unity将每帧调用一次 Update() 函数。这意味着,如果你以60fps的速度运行,那意味着每秒调用60次 Update() 函数。如果以50fps的速度运行,则每秒调用50次Update函数。这也就是说。每两次执行update函数之间的时间间隔,其实是变化不定的。正是由于这一点,使用 Update() 函数的最大问题是它可能与物理引擎不同步。调用行为可以改变,因为它可以结束更快或更慢,这取决于您的图形在渲染的硬件上放置了多少负载,使用物理更新可能会导致完全错误的反应。 Unity确实会尝试以项目所指定的速率调用FixedUpdate()函数。但是,这些调用也需要根据当前实际的帧速率去确定。这意味着虽然任何给定帧上可能有零次,一次甚至超过100次对FixedUpdate()函数的调用,但Unity会动态调整到实际帧速率。通过深入挖掘,我们逐渐意识到,这也意味着对FixedUpdate()的所有调用都不一定在指定的时间间隔内。下面举例说明下这种情况: 默认情况下 FixedUpdate() 函数的更新频率是50FPS(0.02s),如果当游戏的更新频率为60FPS时,那么FixedUpdate有固定的更新速率是很好理解的,因为这种绝对可以保证到,每执行一次 FixedUpdate() 函数,就至少执行了一帧,但是如果游戏本身的更新频率就很低,例如为30FPS时,每一帧的时间间隔明显大于0.02秒的,那么这时候在每两次 Update() 函数的调用之间。 FixedUpdate() 函数就被调用了多次。 通常 FixedUpdate() 函数比 Update() 函数更频繁地被调用。 FixedUpdate() 函数可以在一帧内被调用多次,如果帧速率很低,则根本不能在帧之间调用。 如果帧速率很高,也可能不会调用 FixedUpdate() 。 在 FixedUpdate() 函数被调用之后立即进行所有物理计算和更新。 作用力,扭矩或其他与物理相关的函数时,应使用FixedUpdate函数。 FixedUpdate() 函数由一个准确可信的计时器调用,而与实际的帧速率无关,因此在 FixedUpdate() 中应用移动计算时,您不需要将您的值乘以Time.deltaTime。 Update() 函数是每一帧中执行更新操作的主要(入口)函数。 Update() 函数中用来移动非物理系统驱动的物体。 Update() 函数用来接受用户输入。 Update() 函数可用来实现简单的计时器。 由于 Update() 的执行方式,与物理引擎的执行步调不同,即可能在一帧中, FixedUpdate() 函数执行了多次,而Update函数则只执行了一次。这取决于渲染器在渲染图形时的负载量,以及所耗费的CPU时间。如果在 Update() 函数中执行物理运算时,会导致未知的结果。同时也可以看到: 函数的执行间隔,未必就是TimeManager界面中Fixed TimeStep项中所指定的值。 LateUpdate() 函数每帧会被调用一次,在 Update() 函数结束后调用 所有在 Update() 函数中执行的计算,将会在 LateUpdate() 函数调用之前完成执行。 如果实现一个跟随式的第三视角摄像机,则摄像机的状态更新放在 LateUpdate() 函数中执行是一个通用的做法。 因为你的角色是在 Update() 函数里面执行移动和转向的操作。所以在 LateUpdate() 函数执行摄像机的位置和旋转度计算,可以确保在计算时,角色已经全部完成了位置计算,摄像机可以正确地跟踪到角色的正确位置。

Unity3D出iOS的包操作指南

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 切换平台到iOS下 打开 【Unity|File|Build Setting】 菜单,选择iOS平台,然后点击左下角的 Switch Platform 切换到iOS平台,右边选择 Release。确保项目能在iOS平台上正确运行了再下一步打包。 2 配置Unity项目PlayerSetting 界面上各个选项如下表所示: 选项 细节 Company Name 公司名,与下面的Bundle Identifier对应 Product Name 项目名,也是与下面的Bundle Identifier对应 Bundle Identifier com.CompanyName.ProductName,这个在打包成xCode工程之后,需要和在苹果开发者网站上的app IDs一致,不然会报错:项目Identifier与开发者账号申请的证书的Identifier不同。 Scripting Backend 选择IL2CPP,支持64位。 Api Compatibility Level 如果项目中使用到了文件的操作,要选择“.NET 2.0” Target Device 项目要运行的平台,有哪个就选哪个,不过到时候审核的时候也是要iPhone和iPad分开审核。 Target SDK 这个选择DeviceSDK,选用设备的SDK就行了。 Target minimum iOS Version 限制最低可运行iOS版本,这个在xCode中也可以更细致调整。 PlayerSetting界面如下图所示: 到这里,就可以打包了,点击 【File|Build And Run】 菜单,会弹出要保存的项目文件地址,Unity3D会把工程导出成一个可以给xcode使用的工程。 3 构建开发版的包 首先在xcode的 Account 里面添加苹果开发者账号。从 xcode 7 开始,在开发阶段,如果只需要进行真机调试而不要求发布到AppStore上的话,可以使用一个普通的苹果用户ID作为真机调试账号。方法如下: 第1步:首先点击菜单 【Xcode|Preferences…】 , 第2步:然后点击 【Accounts】 切换到如图所示界面,然后点击左下角的 “+” 号,会弹出一个填写对话框,在此对话框中添加你的苹果用户ID,密码等等,信息,最后点击 【Sign in】 按钮

Unity3D shader优化技巧集合

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 一些优化的tips,基于2019.3版本 只做需要的计算,比如一直在shader设置某个固定颜色,就等于白做计算 能给vs做的,就不要给fs做,能在脚本设置的,就不要在shader里做,比如在shader代码里面用 if-else ,就不如在脚本中用 keyword 优化surface shader:启用 approxview 编译指示符,在光照计算时,在vs中而不是在fs中做视线向量的规格化 优化surface shader:启用 halfasview 编译指示符,在光照计算时,使用半角向量做光照计算,且半角向量的计算在vs中执行 优化surface shader:启用 noforwardadd 编译指示符,确保在 Forward rendering 模式中, 只使用一个有向平行光光源 在fs中执行光照计算,其他的实时光源都只在vs中进行计算,此指示符确保只在一个pass中执行渲染操作 优化surface shader:编译指令 noambient 禁用着色器上的环境照明和球谐光。这样可以使性能稍快一些。 数据精度的优化:世界坐标系下的坐标值,纹理映射坐标值,用 float 数据精度的优化:除了HDR颜色之外的数据,使用 half 数据精度的优化:纹理数据的相关的一些简单操作用 fixed 各种GPU的区别: 桌面GPU ,内部都会统一用 float 计算 各种GPU的区别: 移动GPU 内部能真正支持half精度,大胆地使用它 各种GPU的区别: 老旧的GPU 才内部实现了 fixed , OpenGL ES3 及后续的都内部把 fixed 处理为 half 了 Alpha Testing :在iOS等等使用了PowerVR芯片的平台,表现不佳。 ColorMask :在某些平台上(大多数是在iOS和Android设备的移动GPU),使用 ColorMask 忽略某些通道(例如 ColorMask RGB )可能会占用大量资源,因此仅在确实需要时才使用它。 参考网页: https://docs.unity3d.com/Manual/SL-ShaderPerformance.html https://www.cnblogs.com/sifenkesi/p/4716791.html

《Unity3D内建着色器源码剖析》

书籍信息 信息 详情 定价 89.00 出版社 人民邮电出版社 版次 1 出版时间 2019年08月 开本 16 装帧 平装 页数 334 ISBN编码 9787115507044 官方QQ群 群1号码:672523982 书籍配套代码 代码文件 MD5值 Unity3D内建着色器源代码 版本2017.2.0f3 MD5: 1737874a497c6fa04031af3c90ff2f99 第12章的代码工程 MD5:640938e9f1a259b7e693b1abe866f368 书中参考引用到的一些技术文章 微软网站上关于DXT及BC系列格式的详细介绍 微软MSDN上有介绍块状压缩的文章 nVidia开发者网站有一篇介绍单程立体渲染原理的文章。 Unity3D官网也有单程立体渲染的介绍 《Unity3D内建着色器源码剖析》勘误表 第1版第1刷 章节 页数 位置 错误内容 正确内容 1.2.2 正文第4页 第5段第5行 $$\left< p_1,p_2,p_3 \right>$$ 的排列顺序称为顺时针方向(clockwise,CW)。 $$ \left< p_1,p_3,p_2 \right> $$ 的排列顺序称为顺时针方向(clockwise,CW)。…… 1.2.2 正文第4页 第6段第2行 在图1-7(b)的左手坐标系下排列顺序改为 $$ \left< p_1,p_2,p_3 \right> $$ 在图1-7(b)的左手坐标系下排列顺序改为 $$ \left< p_1,p_3,p_2 \right> $$ 1.

在Mac中如何安装VScode并作为Unity3D开发IDE

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 1 安装brew Homebrew 是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件,相当于linux下的apt-get、yum神器;Homebrew可以在Mac上安装一些MacOS上没有的,从Unix/Linux等系统移植过来的工具,Homebrew将这些工具统统安装到了 【/usr/local/Cellar】 目录中,并在 【/usr/local/bin】 中创建符号链接。 1.1 Homebrew的安装 Homebrew的安装很简单,只需在终端下输入如下指令: /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" Homebrew安装成功后,会自动创建目录 /usr/local/Cellar 来存放Homebrew安装的程序。 这时你在命令行状态下面就可以使用 brew 命令了. 1.2 Homebrew的使用 指令功能 指令格式 指令示例 安装软件 brew install 软件名 brew install wget 搜索软件 brew search 软件名 brew search wget 卸载软件 brew uninstall 软件名 brew uninstall wget 更新所有软件 brew update 通过 update 可以把包信息更新到最新,不过包更新是通过git命令,所以要先通过 brew install git 命令安装git。 更新具体软件 brew upgrade 软件名 brew upgrade git 显示已安装软件 brew list brew list 查看软件信息 brew info 软件名 brew info git 用浏览器打开官方网页查看软件信息 brew home 软件名 brew home git 查看那些已安装的程序需要更新 brew outdated brew outdated 显示包依赖 brew deps brew deps 创建你自己的Homebrew包 brew create 文件名 $ brew create https://foo.

在低版本中的XCode中使用高版本的iOS SDK

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 当iPhone或iPad的手机的iOS系统,升级到了版本,例如11.1版本时,而当前的Xcode版本,例如Xcode9,所能编译出来的软件,最多只能支持的最高版本是11.0时,就会出现以下的问题: 最好的解决的方式当然是直接升级XCode到最新版本,但有时候,升级XCode到最新的版本,需要你当前运行的MacOS的版本到某一个版本号,即还需要你首先升级操作系统,但往往有时候因为你的硬件比较陈旧,没法升级到某个新版本的MacOS了,这时候你就不得不购买新的iMac或者Mac Mini,而如果这时候你又 囊中羞涩 的话……。 为了解决这个囧况,可以通过一些hack手段,让你当前低版本的XCode,能使用上新的iOS SDK。方法如下: 1 首先下载iOS SDK 苹果网站上提供了SDK的下载,但往往在天朝内访问苹果实在太慢了,所以在 这里 有人整理出来所有的iOS SDK供下载。( 务必注意的是,因为这些SDK是非官方渠道提供的,本站不保证其安全性和有效性,所以必须要慎用,使用的话责任自负,本站将不承担任何责任 )。接着找到XCode程序的安装路径,一般是在 【/Appplications】 目录下,右键选择 【显示包内容】 打开,一路进入到 【/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport】 。把下载得到的SDK放置到这个DevicesSupport目录下,如图所示: 2 修改SDKSetting.plist文件 3 修改SDKSettings.plist文件中的版本号 进入 【/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk】 目录,打开SDKSettings.plist文件,将里面所有跟版本有关的数字都修改为填上最新的SDK版本号,例如11.1即可。运行就好可以了,如下图所示: 参考网页 解决低版本Xcode不支持高版本iOS真机调试的问题

C#中的Attribute学习笔记

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com C#的Attribute的一些细节描述: 1 C#的attribute,通常翻译为“ 特性 ”。经常出现的英文单词则翻译为“ 属性 ” 2 C#的attribute可以视为是一种 附着物。就像牡蛎吸附在船底或礁石上一样。这些附着物的作用是为它们的附着体,追加上一些额外的信息。而这些信息保存在附着物的体内。对,也即是被编译器编译进 程序集(assembly) 的 元数据(Metadata) 里,在程序运行的时候,随时可以从元数据里提取出这些附加信息,来决策或影响程序的运行。 3 C#的attribute不是什么别的,其本质上就是一个类,而且这个类在使用上要遵循以下的一些规则: 3.1 不使用new操作符来产生实例,而是使用在方括号里调用构造函数的来产生实例。构造函数的参数是一定要写的,有几个就得写几个。且参数的顺序不能错 3.2 方括号必需紧挨着放置在被附着目标的前面。 3.3 因为方括号里空间有限,不能像使用new那样先构造对象后,再对对象的 属性(Property) 一一赋值。因此,对Attribute实例属性的赋值,也需写在构造函数的圆括号里。但对property的赋值,可有可无,这是因为编译器肯定对property设置一个默认值。对多个property的赋值先后顺序也没有关系。 能被Attribute所附着的目标种类 Attribute能附着的目标的种类在枚举类型AttributeTargets中有定义,代码如下: namespace System { [ComVisible(true)] [Flags] public enum AttributeTargets { Assembly = 1, Module = 2, Class = 4, Struct = 8, Enum = 16, Constructor = 32, Method = 64, Property = 128, Field = 256, Event = 512, Interface = 1024, Parameter = 2048, Delegate = 4096, ReturnValue = 8192, GenericParameter = 16384, All = 32767 } } 从上面的定义可以看到,如果有指定多个attribute所能附着的目标类型的话,在设置AttributeTragets类型值是用按位或操作符连起来就好,例如:AttributeTargets.

Cocos2d-x之lua核心编程(第二版)》示例代码注释详解 3

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com ##用表模拟面向对象编程中的类和对象 1 用元表实现一个People类 People = {age = 18} --[[ 等同于这样的声明方式: function People.new(self) self就是People表本身 --]] function People:new() local p = {} -- 生成一个表p setmetatable(p, self) -- 表p的元表设置为表People self.__index = self --[[ 表People的__index值就是__People本身。前文说到,__index对应的值可以是 一个table也可以是一个table。现在以一个table作为__index的值 --]] return p end function People:growUp() self.age = self.age + 1 print(self.age) end -- 测试 p1 = People:new() --[[ p1:growUp()的调用等价于:p1.growUp(p1)。这个语句的执行可以分解为以下的一些步骤: 1 首先要拿到函数p1.growUp。从People:new函数中可以知道:p1就是People:new函数中的p,一开始就是一个空表, 但这个空表p的元表就是表People,且空表p的元表People表的__index方法就是它自己,这也就是说。虽然p表是一个空表, 但是当执行到p1.growUp时,会查找执行到People.growUp的函数去执行之。 2 得到了People.growUp函数之后执行值,这里p1:growUp()的调用方式是等价于People.growUp(p1)。在growUp函数内部 当执行到self.age = self.age+1语句时,一开始的p1表中没有age项目,但执行语句后,首先会从People表中复制一份age项到 p1表,然后再对p1自身的age项加1.所以输出19。p2也是遵循这个“复制一份age项到p2表”的操作,故而最后也是输出19 --]] p1:growUp() -- 输出19 p2 = People:new() p2:growUp() -- 输出19 ###2 在People类的基础上定义Man类