Unity3D游戏制作-场景角色-移动设备设置等_第1页
Unity3D游戏制作-场景角色-移动设备设置等_第2页
Unity3D游戏制作-场景角色-移动设备设置等_第3页
Unity3D游戏制作-场景角色-移动设备设置等_第4页
Unity3D游戏制作-场景角色-移动设备设置等_第5页
已阅读5页,还剩40页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Unity3D游戏制作开博写Unity的东西也写了好多,但大部分都是翻译,原创很少,接下来的一段日子,我会多写一些原创文章,介绍一些在项目中积累的简单实用的技术。一:3D横版场景的角色移动控制 一、导入场景,并在场景中加入TouchPlaneTouchPlane为鼠标屏幕时的Raycast平面,如下图场景中的绿线部分。由于是横版场景,地面一般是平坦的,所以可以选择进行一个平面来作为计算鼠标投射交点。之所以是绿线,是因为我disable该平面的MeshRender,该平面的Inspector视图如下:值得注意的是:1、 该平面使用Box Collider,而不用Mesh Collider,这样做的好处是可以减少碰撞的计算量;2、 Tag设定为“Plane”,这是为了鼠标点击时的Raycast选取;3、 Layer设定为“TouchPlane”,这样做也是为了以后进行Raycast鼠标选取操作。二、设定角色Component角色Inspector视图如下图所示:一共四个Component:Animation、Rigidbody、Capsule Collider以及Move Controller。Animation组件主要是角色的动作动画;Rigidbody组件是为了角色的移动,这个我在后面会解释,这里还有一点需要注意就是不使用“Use Gravity”,这样做一是因为角色只在地面上跑(如果你的游戏需要角色有跳跃功能,那么应该使用“Use Gravity”,二是可以在不影响效果的同时,减少模型的物理计算);Capsule Collider是碰撞器,与该文章所介绍移动内容没有关系;Move Controller是自定义的角色移动控制组件,其中MoveController.cs为其对应脚本。三、如何移动角色流程可设定如下:1、 鼠标点击地面,通过屏幕位置来计算出其所在三维空间中角色移动的目的位置。2、 将角色从当前位置移动到鼠标点击位置这样,我们就根据上述两个步骤来完成人物的移动操作。(1) 鼠标拾取操作csharp view plaincopyprint?1. voidMove()2. 3. if(Input.GetMouseButtonDown(0)4. 5. /m_layerMask是指TouchPlane的layer数,这也是为什么之前在设定/TouchPlane时要设定其layer的原因,这样做是为了方便鼠标拾取 6. m_layerMask=18;7. /根据鼠标在屏幕空间的位置计算射线 8. m_ray=Camera.main.ScreenPointToRay(Input.mousePosition);9. /进行三维场景中的射线求交 10. if(Physics.Raycast(m_ray,outm_hitInfo,100,m_layerMask)11. 12. /如果拾取的tag为“Plane”的话 13. if(m_hitInfo.transform.tag=Plane)14. 15. /将角色朝向目标点 16. LookatTargetPos(m_hitInfo.point);17. 18. 19. 20. void Move()if(Input.GetMouseButtonDown(0)/ m_layerMask是指TouchPlane的layer数,这也是为什么之前在设定/TouchPlane时要设定其layer的原因,这样做是为了方便鼠标拾取m_layerMask = 1 8;/ 根据鼠标在屏幕空间的位置计算射线m_ray = Camera.main.ScreenPointToRay(Input.mousePosition);/ 进行三维场景中的射线求交if (Physics.Raycast(m_ ray, out m_ hitInfo, 100, m_layerMask)/ 如果拾取的tag为“Plane”的话if (m_hitInfo.transform.tag = Plane)/ 将角色朝向目标点LookatTargetPos(m_ hitInfo.point);(2) 角色移动操作 csharp view plaincopyprint?1. voidLookatTargetPos(Vector3tarPos)2. 3. /判断当前角色是否可以移动 4. if(!m_bWalk)5. return;6. /记录下目标点 7. m_targetPos=newVector3(tarPos.x,tarPos.y,tarPos.z);8. /将角色朝向目标点 9. transform.LookAt(m_targetPos);10. /改变移动State 11. m_bMoving=true;12. void LookatTargetPos(Vector3 tarPos)/ 判断当前角色是否可以移动if (!m_bWalk) return;/ 记录下目标点m_targetPos = new Vector3(tarPos.x, tarPos.y, tarPos.z);/ 将角色朝向目标点transform.LookAt(m_targetPos);/ 改变移动Statem_bMoving = true;MoveController.cs中的Update函数如下:csharp view plaincopyprint?1. voidUpdate()2. 3. Move();4. /如果可以移动的话 5. if(m_bMoving)6. 7. /改变角色的Animation 8. animation.CrossFade(Run);9. /设定rigidbody的速度,由于之前已经将角色朝向目标点,所以现在的速度朝向即为transform.forward 10. rigidbody.velocity=transform.forward*8.0f;11. 12. /判断角色是否该停止移动 13. if(Vector3.Distance(transform.position,m_targetPos)0.1f)14. 15. rigidbody.velocity=Vector3.zero;16. m_bMoving=false;17. animation.CrossFade(Idle);18. 19. 20. void Update () Move();/ 如果可以移动的话if (m_bMoving)/ 改变角色的Animationanimation.CrossFade(Run);/ 设定rigidbody的速度,由于之前已经将角色朝向目标点,所以现在的速度朝向即为transform.forward rigidbody.velocity = transform.forward * 8.0f;/ 判断角色是否该停止移动 if (Vector3.Distance(transform.position, m_targetPos) Create-Shader来创建一个默认的Shader,并取名“MyShader”。2、将MyShader打开即可看见Unity默认的Shader代码csharp view plaincopyprint?1. ShaderCustom/MyShader2. Properties3. _MainTex(Base(RGB),2D)=white4. 5. SubShader6. TagsRenderType=Opaque7. LOD2008. 9. CGPROGRAM 10. #pragmasurfacesurfLambert 11. 12. sampler2D_MainTex;13. 14. structInput15. float2uv_MainTex;16. ;17. 18. voidsurf(InputIN,inoutSurfaceOutputo)19. half4c=tex2D(_MainTex,IN.uv_MainTex);20. o.Albedo=c.rgb;21. o.Alpha=c.a;22. 23. ENDCG24. 25. FallBackDiffuse26. Shader Custom/MyShader Properties _MainTex (Base (RGB), 2D) = white SubShader Tags RenderType=Opaque LOD 200CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;struct Input float2 uv_MainTex;void surf (Input IN, inout SurfaceOutput o) half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;ENDCG FallBack Diffuse3、将该Shader赋给一个角色,就可以看到该Shader所能表达出的Diffuse渲染效果。4、接下来我们将以此默认Shader作为蓝本,编写出自定义的Shader。另外,该Shader所用到的参数,我们将在下一章节进行说明。二、实现多种自定义渲染效果1、 BumpMap效果如果想实现Bump Map效果,可对上述的Shader做如下修改:1.1 在属性Properties中加入:csharp view plaincopyprint?1. Properties2. _MainTex(Base(RGB),2D)=white3. _BumpMap(Bumpmap,2D)=bump4. Properties _MainTex (Base (RGB), 2D) = white _BumpMap(Bumpmap, 2D) = bump 1.2在SubShader的变量中也进行相应修改:csharp view plaincopyprint?1. sampler2D_MainTex;2. sampler2D_BumpMap;3. 4. structInput5. float2uv_MainTex;6. float2uv_BumpMap;7. ;sampler2D _MainTex;sampler2D _BumpMap;struct Input float2 uv_MainTex;float2 uv_BumpMap;1.3最后修改surf函数,加入对Normal分量的计算:csharp view plaincopyprint?1. voidsurf(InputIN,inoutSurfaceOutputo)2. half4c=tex2D(_MainTex,IN.uv_MainTex);3. o.Albedo=c.rgb;4. o.Alpha=c.a;5. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap);6. void surf (Input IN, inout SurfaceOutput o) half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap);这样,角色的材质部分即可变为如下形式(暂定BumpMap的Shader名为“MyShader1”):然后,根据Base图来创建其Normal Map图,并拖入到BumpMap中即可。BumpMap的效果显示如下:说明:(1)首先是title的解释csharp view plaincopyprint?1. ShaderCustom/MyShader1Shader Custom/MyShader1 这种表示表明了该Shader在编辑器中的显示位置,例如我们可在如下地方找到该Shader。 (2)其次是Propertiescsharp view plaincopyprint?1. Properties2. _MainTex(Base(RGB),2D)=white3. _BumpMap(Bumpmap,2D)=bump4. Properties _MainTex (Base (RGB), 2D) = white _BumpMap(Bumpmap, 2D) = bump Properties可通过如下语义进行声明:name (displayname, property type) = default valuel “name” 是与Shader脚本中对应的名字l “display name”是在材质视图中所显示的名字l “propertytype”是指该property的类型,一般可有如下几种类型:Range,Color,2D,Rect,Cube,Float和Vectorl “defaultvalue”是指该property的默认值这里需要注意的是,如果你在Properties中加入了新的属性,那么你需要在CGPROGRAM中的SubShader中加入同样名字的参数。(3)接下来是“LOD”语义词的解释。这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的Shader LOD说明可以参见:/amazonzx/article/details/(4)我们在SubShader中还加入了csharp view plaincopyprint?1. sampler2D_BumpMap;2. float2uv_BumpMap;3. sampler2D _BumpMap;float2 uv_BumpMap;其中,_BumpMap是为了关联Properties中的_BumpMap属性。而uv_BumpMap,是为了获取BumpMap图中的uv坐标。(5)最后,我们在surf函数中获取每个顶点的纹理信息以及法线信息,这些信息将被应用于接下来的Vertex Fragment和Pixel Fragment。csharp view plaincopyprint?1. voidsurf(InputIN,inoutSurfaceOutputo)2. half4c=tex2D(_MainTex,IN.uv_MainTex);3. o.Albedo=c.rgb;4. o.Alpha=c.a;5. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap);6. void surf (Input IN, inout SurfaceOutput o) half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap);其中,tex2D函数可以读取纹理_MainTex中的IN.uv_MainTex坐标位置的像素颜色值。Albedo和Alpha分别获取该像素的RGB值和Alpha值,其中“Albedo”是一个漫反射参数,它表示一个表面的漫反射能力,即一个表面上出射光强与入射光强的比值。具体介绍可见:/wiki/Albedo。2、 Blinn-Phong效果如果想实现Blinn-Phong效果,可对上述的Shader做如下修改:2.1在属性Properties中加入:csharp view plaincopyprint?1. _AmbientColor(AmbientColor,Color)=(0.1,0.1,0.1,1.0)2. _SpecularColor(SpecularColor,Color)=(0.12,0.31,0.47,1.0)3. _Glossiness(Gloss,Range(1.0,512.0)=80.0_AmbientColor (Ambient Color, Color) = (0.1, 0.1, 0.1, 1.0)_SpecularColor (Specular Color, Color) = (0.12, 0.31, 0.47, 1.0)_Glossiness (Gloss, Range(1.0,512.0) = 80.02.2在SubShader的变量中也加入相应修改:csharp view plaincopyprint?1. fixed4_AmbientColor;2. fixed4_SpecularColor;3. half_Glossiness;fixed4 _AmbientColor;fixed4 _SpecularColor;half _Glossiness;2.3最后修改surf函数,进行如下修改:csharp view plaincopyprint?1. fixed4c=tex2D(_MainTex,IN.uv_MainTex);fixed4 c = tex2D (_MainTex, IN.uv_MainTex);这里将原有的half4替换为fixed4,这样做是为了提高渲染的性能,因为fixed的精度较之half要低,更高的精度意味着更大的计算量,而这里fixed的精度已经足够,所以使用fixed替代half4,从而来降低计算消耗,增加渲染性能。2.4将“#pragma surface surf Lamber”改成“#pragma surfacesurf CustomBlinnPhong”,同时加入与其对应的LightingCustomBlinnPhong函数来计算顶点光照。csharp view plaincopyprint?1. inlinefixed4LightingCustomBlinnPhong(SurfaceOutputs,fixed3lightDir,fixed3viewDir,fixedatten)2. 3. fixed3ambient=s.Albedo*_AmbientColor.rgb;4. 5. fixedNdotL=saturate(dot(s.Normal,lightDir);6. fixed3diffuse=s.Albedo*_LightColor0.rgb*NdotL;7. 8. fixed3h=normalize(lightDir+viewDir);9. floatnh=saturate(dot(s.Normal,h);10. floatspecPower=pow(nh,_Glossiness);11. fixed3specular=_LightColor0.rgb*specPower*_SpecularColor.rgb;12. 13. fixed4c;14. c.rgb=(ambient+diffuse+specular)*(atten*2);15. c.a=s.Alpha+(_LightColor0.a*_SpecularColor.a*specPower*atten);16. returnc;17. inline fixed4 LightingCustomBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten) fixed3 ambient = s.Albedo * _AmbientColor.rgb;fixed NdotL = saturate(dot (s.Normal, lightDir); fixed3 diffuse = s.Albedo * _LightColor0.rgb * NdotL;fixed3 h = normalize (lightDir + viewDir); float nh = saturate(dot (s.Normal, h); float specPower = pow (nh, _Glossiness);fixed3 specular = _LightColor0.rgb * specPower * _SpecularColor.rgb;fixed4 c;c.rgb = (ambient + diffuse + specular) * (atten * 2);c.a = s.Alpha + (_LightColor0.a * _SpecularColor.a * specPower * atten);return c;该函数的名称为什么不是“CustomBlinnPhong”呢?这是因为该函数虽然是由“#pragma surface surf CustomBlinnPhong”来调用,但是为了让该函数可以正常工作,我们需要在其名称前加入“Lighting”关键字,这样Unity才能识别出这是一个自定义的光照函数。通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader2”):其显示效果如下:3、 边缘光照(Rim Light)和卡通渲染(Toon Shading)可以通过对上述Shader做以下改进,来达到这种效果:3.1在属性Properties中加入:csharp view plaincopyprint?1. _RimColor(RimColor,Color)=(0.12,0.31,0.47,1.0)2. _RimPower(RimPower,Range(0.5,8.0)=3.03. _Ramp(ShadingRamp,2D)=gray_RimColor (Rim Color, Color) = (0.12, 0.31, 0.47, 1.0)_RimPower (Rim Power, Range(0.5, 8.0) = 3.0_Ramp (Shading Ramp, 2D) = gray 3.2在SubShader的变量中也加入相应修改:csharp view plaincopyprint?1. sampler2D_MainTex;2. sampler2D_BumpMap;3. sampler2D_Ramp;4. 5. fixed4_AmbientColor;6. fixed4_SpecularColor;7. half_Glossiness;8. 9. fixed4_RimColor;10. half_RimPower;11. 12. structInput13. float2uv_MainTex;14. float2uv_BumpMap;15. half3viewDir;16. ;sampler2D _MainTex;sampler2D _BumpMap;sampler2D _Ramp;fixed4 _AmbientColor;fixed4 _SpecularColor;half _Glossiness;fixed4 _RimColor;half _RimPower;struct Input float2 uv_MainTex;float2 uv_BumpMap;half3 viewDir;3.3修改surf函数,进行如下修改:csharp view plaincopyprint?1. voidsurf(InputIN,inoutSurfaceOutputo)2. fixed4c=tex2D(_MainTex,IN.uv_MainTex);3. o.Albedo=c.rgb;4. o.Alpha=c.a;5. o.Normal=UnpackNormal(tex2D(_BumpMap,IN.uv_BumpMap);6. fixedrim=1.0-saturate(dot(normalize(IN.viewDir),o.Normal);7. o.Emission=(_RimColor.rgb*pow(rim,_RimPower);8. void surf (Input IN, inout SurfaceOutput o) fixed4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap);fixed rim = 1.0 - saturate (dot (normalize(IN.viewDir), o.Normal);o.Emission = (_RimColor.rgb * pow (rim, _RimPower);这里主要是用来计算边缘光照的,首先通过视线与法线的夹角来找到模型的边缘,然后再根据距离的远近来控制发射光的强度。3.4将“#pragma surface surf CustomBlinnPhong”改成“#pragma surfacesurf CustomBlinnPhong exclude_path:prepass”,同时在LightingCustomBlinnPhong函数来修改漫反射光的计算,来达到卡通渲染的效果。csharp view plaincopyprint?1. fixedNdotL=saturate(dot(s.Normal,lightDir);2. fixeddiff=NdotL*0.5+0.5;3. fixed3ramp=tex2D(_Ramp,float2(diff,diff).rgb;4. fixeddiffuse=s.Albedo*LightColor0.rgb*ramp;fixed NdotL = saturate(dot (s.Normal, lightDir); fixed diff = NdotL * 0.5 + 0.5;fixed3 ramp = tex2D (_Ramp, float2(diff, diff).rgb;fixed diffuse = s.Albedo * LightColor0.rgb * ramp;通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader3”):其显示效果如下:可以看出边缘光照的效果,同时还可以看出明显的明暗变化的卡通渲染效果。三、小结综上所述,本文已经给出了人物的几种基本渲染方法及其Shader实现,在这里我并没有去分析每种渲染效果的原理,而仅是从实际出发,直接给出对应的简单实现方法。如果想要对光照模型进行深入理解,可以Google搜索其原理进行了解。最后,给出各种渲染方法的对比图,显示如下:三:移动平台上的角色阴影制作 本文将重点介绍两种目前在移动平台上的主流阴影制作技术,同时也会简单介绍两种移动平台上相对较为高级的动态阴影生成方法。由于目前主流使用Unity3.x在移动平台上并不支持阴影的动态生成技术,所以目前最普遍流行同时性价比也最高的阴影生成方法有以下两种:1、 简单贴图法所谓简单贴图法即是直接在角色的角底附加一个阴影半透明贴图,并让其跟随角色一起运动,一般是将该阴影Object成为角色模型的子物体,该种阴影生成效果如下:阴影的Inspector视图如下:其中ShadowComponent是控制阴影的一个脚本,与其生成无关,故不再这里介绍。影响该应用生成的主要有两个部分,一个是Shadow网格,另外一个则是渲染所需要的材质“No Name”。需要注意的是,Shadow网格是一个平面,但不建议使用Unity自身生成的Plane,因为Unity生成的面数较多,可通过3DMax等建模工具来自行建模,如下所示:对于材质,最重要的则是Shader的书写,我将其列在下方,以方便大家使用:csharp view plaincopyprint?1. ShaderiPhone/SimpleShadow2. 3. Properties4. 5. _MainTex(MainTex,2D)=6. 7. 8. SubShader9. 10. TagsQueue=Transparent11. 12. Pass13. 14. BlendSrcAlphaOneMinusSrcAlpha15. 16. Color_clrBase17. 18. CullOff19. LightingOff20. SetTexture_MainTexcombinetexture,one-texture21. 22. 23. Shader iPhone/SimpleShadowProperties_MainTex (MainTex, 2D) = SubShaderTags Queue = Transparent PassBlend SrcAlpha OneMinusSrcAlphaColor _clrBaseCull OffLighting OffSetTexture _MainTex combine texture, one - texture 通过以上设置即可生成最简单的阴影效果,大家可以通过自己设定脚本来控制阴影的移动和变化等等。但是,该阴影生成方法有一个明显的“硬伤”,即该阴影只能适用于平坦的地面,一旦地面凹凸不平或有遮挡物,则会出现“穿帮”的效果,如下图所示,该方法生成的阴影对脚下的正方体完全没有影响,所以为了解决这种问题,投影生成法应运而生。2、 投影生成法该方法本质上来说是一种贴花(Decal)技术,即设定一个投影器,然后将阴影贴图投射到你想展现阴影的地方,该方法的优点在于投影效果不取决于被投影区域的几何形状,即被投影区域可以任意凹凸的曲面,也可以处理各种障碍物。该方法生成的阴影效果如下:下面我就具体介绍一下该阴影的生成方法:(1) 通过“GameObject-Create Empty”来创建一个空的物体,并取名为“Shadow Projector”。(2) 通过“Component-Effects-Projector”在该空物体上加入Projector组件,并通过平移、旋转和调整参数达到如下效果:(3) 然后在Material选项中拖入已经准备好的材质,即可投影出阴影,效果如下:我们看到,场景中不仅生成了阴影,同时角色的身体也“变黑”了,这是因为投影器的“Ignore Layers”设定为“Nothing”的缘故,我们将可忽略层设为角色的层“Player”,则可使角色不再被投影,效果如下:(4) 最终的Shadow Projector的Inspector视图如下:其中材质所用到的shader为:csharp view plaincopyprint?1. ShaderProjector/Multiply2. Properties3. _ShadowTex(Cookie,2D)=grayTexGenObjectLinear4. _FalloffTex(FallOff,2D)=whiteTexGenObjectLinear5. 6. 7. Subshader8. TagsRenderType=Transparent-19. Pass10. ZWriteOff11. FogColor(1,1,1)12. AlphaTestGreater013. ColorMaskRGB14. BlendDstColorZero15. Offset-1,-116. SetTexture_ShadowTex17. combinetexture,ONE-texture18. Matrix_Projector19. 20. SetTexture_FalloffTex21. constantColor(1,1,1,0)22. combinepreviouslerp(texture)constant23. Matrix_ProjectorClip24. 25. 26. 27. Shader Projector/Multiply Properties _ShadowTex (Cookie, 2D) = gray TexGen ObjectLinear _FalloffTex (FallOff, 2D) = white TexGen ObjectLinear Subshader Tags RenderType=Transparent-1 Pass ZWrite Off Fog Color (1, 1, 1) AlphaTest Greater 0 ColorMask RGB Blend DstColor Zero Offset -1, -1 SetTexture _ShadowTex combine texture, ONE - texture Matrix _Projector SetTexture _FalloffTex constantColor (1,1,1,0) combine previous lerp (texture) constant Matrix _ProjectorClip 通过以上的步骤,我们即可实现投影式的阴影生成方法。与第一种方法一样,可以设定一些特定脚本来控制该阴影的移动以及变化等等。另外,需要

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论