【游戏开发实战】小岛城堡里的常春藤,听新发剖析Unity案例知识点
文章目录
- 一、前言
- 二、效果演示
- 三、常春藤生成器工具下载
- 四、 工具使用
- 1、创建根节点:lvy GameObject
- 2、创建配置文件:lvy Profile Asset
- 3、贴图与材质球
- 4、绘制常春藤
- 5、修改叶子颜色
- 6、修改叶子大小
- 7、修改叶子密度
- 8、修改根茎粗细
- 9、修改生长长度
- 10、修改分支概率
- 11、删除已绘制的常春藤
- 五、拓展知识解答
- 1、常春藤的Mesh资源存放在哪里
- 2、如何删除无用的Mesh
- 3、如何获取鼠标投射到物体表面的位置
- 4、场景中的水面是怎么做的(半透明和反射效果)
- 5、场景中的天空是怎么做的
- 6、场景中的草是怎么做的,为什么它会摇啊摇
- 六、结束语
一、前言
嗨,大家好,我是新发。
记得初中的时候语文课本里有一篇名字叫《最后一片叶子》的文章,作者是著名的短篇小说家欧·亨利。
《最后一片叶子》又叫《最后一片常春藤叶》,文中讲述了老画家贝尔曼为了鼓励贫病交加的青年画家顽强地活下去,在风雨之夜挣扎着往墙上画了一片永不凋零的常春藤叶。他为此用生命绘制的杰作付出了生命的代价,但青年画家却因此获得勇气而活了下来的故事。
常春藤寓意着希望、朝气蓬勃,也象征着忠诚,还代表着和不朽的青春,因为它一年四季都是常绿的,所以很多人喜欢在阳台上种常春藤,显得格外有生气。本文,我就来证明一下常春藤的魔力,我将在Unity
中演示制作常春藤的过程,并讲解其中涉及到的一些技术知识点。
二、效果演示
场景,我希望是在一个优美的岛屿城堡,我找到了一个不错的场景,如下:
注:喜欢这个城堡场景资源的同学,可以自行从这里下载:https://assetstore.unity.com/packages/3d/props/exterior/low-poly-brick-houses-131899
在窗户上绘制生成常春藤,如下:
对比下前后效果,是不是有了常春藤之后,瞬间生机盎然了~
三、常春藤生成器工具下载
我使用的是Github
的这个工具:hedera,这个工具可以很方便地在场景中制作并生成常春藤一样的植物,感兴趣的同学可以下载从GitHub
上下载来学习。
GitHub
地址:https://github.com/radiatoryang/hedera
四、 工具使用
1、创建根节点:lvy GameObject
点击菜单Hedera / Create / Create New lvy GameObject
,
此时会生成一个lvy Group
节点,它身上会带一个lvyBehavior
组件,我们下面生成的常春藤就是在这个节点之下生成的。
2、创建配置文件:lvy Profile Asset
上面我们可以看到,lvyBehavior
组件需要指定一个配置文件,这个配置文件用于配置常春藤生成的规则与相关参数。
工具已经帮我们做好了几个配置,在Runtime/lvyProfiles
目录中,
为了演示,我创建一个新的,点击Create new lvy Profile Asset...
按钮,
将其保存到Runtime/lvyProfiles
目录中,
生成后选中它,可以在Inspector
视图中看到配置的参数,
参数说明:
参数 | 说明 |
---|---|
Length | 生成长度,可以设置上下限,从这个范围内进行随机 |
Branch Chance % | 生成分支的概率 |
Random Spread % | 随机分布率 |
Branch Thickness | 根茎的粗度 |
Leaf Size Radius | 叶子大小 |
Leaf Density % | 叶子密度 |
Leaf Colors | 叶子颜色 |
Brahcn Material | 根茎的材质 |
Leaf Material | 叶子的材质 |
3、贴图与材质球
我们需要先准备常春藤的贴图(包括根茎+叶子),例:
制作根茎和叶子的材质球:
材质球设置如下(根茎+叶子):
给lvy Profile Asset
设置根茎和叶子的材质球,
4、绘制常春藤
选中lvy Group
,点击Start Painting lvy
按钮,
然后把鼠标移到Scene
视图中,即可看到有个蓝紫色的圈圈投射在物体表面上,
此时按住鼠标滑动即可生成常春藤,
5、修改叶子颜色
我们看到绘制出来的叶子颜色是 白/绿/黄 的,
这是因为在lvy Profile Asset
中设置的叶子颜色是这样的:
我们可以将其修改成我们想要的其他颜色,比如改成这样:
重新绘制出来的叶子颜色如下:
6、修改叶子大小
调整Leaf Size Radius
可以修改叶子的大小,
我们把叶子大小调小,调整参数后可以点击Re-mesh Visible
按钮,就会根据调整后的参数重新运算~
调整前是这样:
调整后是这样:
7、修改叶子密度
调整Leaf Density %
可以修改叶子密度,
我们把叶子密度调大,如下:
8、修改根茎粗细
我们觉得根茎有点粗,
想调细一点,调整Branch Thickness
,把根茎调细,
如下:
9、修改生长长度
调整Length
可以修改生长长度,
我们测试下最小值和最大值的效果,调整为最小值,此时绘制常春藤不会自动继续生长,
效果如下:
现在,我们把Lehgth
调为最大值,
因为它生长力太强了,所以我在地面上演示,感受一下,
10、修改分支概率
我们看到生长过程中的分支概率比较低,我们可以调整Branch Chance %
来修改分支概率,
我们把分支概率调到最大值,感受一下,
11、删除已绘制的常春藤
假设我们要删除这条常春藤,并不是直接delete
它的GameObject
,
而是先选中它所在的Group
,
然后点击对应的垃圾桶按钮,
如果一个Group
下有多条常春藤,则会会显示多个item
,
五、拓展知识解答
1、常春藤的Mesh资源存放在哪里
我们点开常春藤的节点,可以看到一个根茎节点和一个叶子节点,
工具帮我们生成了根茎和叶子的Mesh
,这些Mesh
文件会自动存放在场景所在目录的同名目录中,
它是序列化在一个.assset
文件中的,
根茎的Mesh
,
叶子的Mesh
,
思考:它是如何将网格资源序列化到asset文件中的?
解答:
需要序列化的类继承ScriptableObject
,例:
public class IvyDataAsset : ScriptableObject
{//...
}
通过ScriptableObject.CreateInstance
创建序列化文件,例:
public static IvyDataAsset CreateNewDataAsset(string mainFolder, string sceneName, string path)
{if ( !AssetDatabase.IsValidFolder(path) ) {var folderGUID = AssetDatabase.CreateFolder( mainFolder, sceneName );path = AssetDatabase.GUIDToAssetPath(folderGUID);}IvyDataAsset asset = ScriptableObject.CreateInstance<IvyDataAsset>();AssetDatabase.CreateAsset(asset, path + "/HederaData.asset");AssetDatabase.SaveAssets();return asset;
}
然后在IvyDataAsset
中定义需要序列化的内容,
// IvyDataAsset.cspublic class IvyDataAsset : ScriptableObject
{public IvyDictionary meshList = new IvyDictionary();[System.Serializable]public class IvyDictionary : SerializableDictionary<long, Mesh> { }[System.Serializable]public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver{[SerializeField]private List<TKey> keys = new List<TKey>();[SerializeField]private List<TValue> values = new List<TValue>();// ...}
}
关于Unity的类的序列化,还可以参见我早先写的这篇文章:《unity 类的序列化》
如果我们想要自定义Inspector
界面的内容,我们还可以写对应的Editor
类,重写OnInspectorGUI
函数,例:
// IvyDataAssetEditor.cs[CustomEditor( typeof(IvyDataAsset))]
public class IvyDataAssetEditor : Editor
{public override void OnInspectorGUI() {var data = (IvyDataAsset)target;// ...}
}
2、如何删除无用的Mesh
选中HederaData
文件,点击Cleanup Unreferenced Meshes
按钮,接口自动清理无用的Mesh
资源。
对应的逻辑:
// IvyDataAssetEditor.csif ( GUILayout.Button(content) ) {var allReferencedMeshes = data.meshList.Values.ToList();for ( int i=0; i<allSubassets.Length; i++ ) {if (!allReferencedMeshes.Contains((Mesh)allSubassets[i])) {Object.DestroyImmediate(allSubassets[i], true);}}EditorUtility.SetDirty(data);AssetDatabase.SaveAssets();
}
3、如何获取鼠标投射到物体表面的位置
上面我们看到,鼠标移到Scene
视图中,可以看到有个蓝紫色的圈圈投射在物体表面上,这个是如何实现的呢~
用的是射线检测接口:
public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction);
例:
// IvyEditor.cspublic void MousePosition ()
{// 射线Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);RaycastHit hit;// 射线检测if (Physics.Raycast(ray.origin, ray.direction, out hit, Mathf.Infinity, ivyBehavior.profileAsset.ivyProfile.collisionMask, QueryTriggerInteraction.Ignore)) {mousePos = hit.point + hit.normal * 0.05f;mouseNormal = hit.normal;Handles.color = Color.blue;// 绘制线圈DrawThiccDisc(mousePos, hit.normal, Mathf.Max(0.1f, ivyBehavior.profileAsset.ivyProfile.ivyStepDistance));// 绘制法线Handles.DrawLine(mousePos, mousePos + hit.normal * 0.25f);}
}// 绘制线圈
void DrawThiccDisc(Vector3 mousePos, Vector3 normal, float radius)
{var originalColor = Handles.color;Handles.color = new Color( originalColor.r, originalColor.g, originalColor.b, 0.4f);Handles.DrawSolidDisc( mousePos, normal, radius);Handles.color = originalColor;Handles.DrawWireDisc(mousePos, normal, radius - 0.01f );Handles.DrawWireDisc(mousePos, normal, radius );Handles.DrawWireDisc(mousePos, normal, radius + 0.01f );
}
注:我之前写了一篇文章,《使用Unity ShaderGraph实现在模型上涂鸦的效果,那么,纹个手吧》,里面也用到了射线检测,感兴趣的同学可以打开阅读以下~
4、场景中的水面是怎么做的(半透明和反射效果)
先创建一个空白的平面(Plane
)作为水底,
再创建一个平面作为水面,
为水面创建一个材质球,
材质球设置为半透明模式(Transparent
),设置一下颜色,提高光滑度(Smoothness
),
这样,水面就具有半透明效果,同时也可以反射天空的影像,我们创建个Cube
测试一下,
5、场景中的天空是怎么做的
场景中的天空是用天空盒做的,我们需要先准备720
度天空全景图,可以把自己想象成坐在一个正方体的内部,这六张图就是对应正方体里面的6
个面(前后左右上下),
创建一个材质球,shader
使用Skybox/6 Sided
,然后设置前后左右上下6
个面的贴图,
最后,把材质球拖到Scene
视图空白处即可,或者点击菜单Window / Rendering / Lighting
,
点击Environment
标签页,设置天空盒材质球即可,
我上一篇文章《[原创] 用Unity等比例制作广州地铁,广州加油,早日战胜疫情(Unity | 地铁地图 | 第三人称视角)》里面也用到了天空盒:
更多免费天空盒资源下载:
https://assetstore.unity.com/packages/2d/textures-materials/sky/fantasy-skybox-free-18353
https://assetstore.unity.com/packages/2d/textures-materials/sky/8k-skybox-pack-free-150926
https://assetstore.unity.com/packages/2d/textures-materials/sky/customizable-skybox-174576
https://assetstore.unity.com/packages/vfx/shaders/free-skybox-extended-shader-107400
https://assetstore.unity.com/packages/2d/textures-materials/sky/farland-skies-cloudy-crown-60004
6、场景中的草是怎么做的,为什么它会摇啊摇
场景中的草一摇一摇的,这是怎么做的呢~
这里用到了Unity
的地形编辑器Terrain
,草是地形的一部分,我们把环境中其他物体隐藏起来,只留下地形,如下:
所以我们需要先创建一个地形,在Hierarchy
视图空白处右键鼠标,点击菜单3D Object / Terrain
,
此时就可以创建一个地形物体,
它身上会带一个Terrain
组件,我们点击Place Details
按钮(第四个按钮,我圈出来那个),我们就可以在地形上刷出细节物体,通常用来做草。
不过这个时候我们什么也刷不出来,这是因为我们还没有设置笔刷图片,
我们先准备一张草的图片,如下:
点击Edit Details...
按钮,
点击Add Grass Texture
按钮,
设置Detail Texture````为刚刚的草的图片,点击
Add```按钮,
其他参数说明:
参数 | 说明 |
---|---|
Detail Texture | 选择一张花或者草的贴图 |
Min Width、Max Width、Min Height、Max Height | 单个草物体的最大最小的宽高值 |
Noise Spread | 添加一点分布随机度 |
Healthy Color | 草的健康颜色(会被tint到贴图的上部) |
Dry Color | 草的干枯颜色(会被tint到贴图的底部) |
Billboard | 是否以永远面向摄像机的单面形式生成单个草物体,如果选否的话就会以十字交叉双平面方式来生成单个草物体 |
这样草的笔刷图片就制作好了,
这样就可以刷出草地啦~
如果想要删除草地,只需要按住Ctrl
键不放,鼠标一刷,就可以把对应的草地删除了~
这些草之所以会摇啊摇,是因为有风,Terrain
组件的设置里可以设置风的大小等参数,如下:
细心的朋友应该注意到了,这个草堆并不是地形刷出来的,为什么它也会摇啊摇,
这个是通过shader
的顶点着色器来控制的,例:
// FoliageShader.shaderfloat random(float3 p)
{return frac(43758.5453 * sin(dot(p, float3(12.9898, 78.233, 45.5432)) % 3.14159));
}// 顶点着色器
void vert(inout appdata_full v)
{// 随机偏移float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;float3 offset = _Intensity * (sin(worldPos.xyz + _Time.y * _WindSpeed) + _Randomness * random(worldPos));// 设置顶点坐标偏移v.vertex.xyz += offset;
}
六、结束语
好了,就先写这么多吧,如果有什么疑问,欢迎留言或私信~
最后,晒下我小屋的常春藤~
【游戏开发实战】小岛城堡里的常春藤,听新发剖析Unity案例知识点相关推荐
- 【游戏开发实战】Unity快速搭建体素风格关卡地图(Tile3D | 我的世界 | Voxel | 场景 | 编辑器)
文章目录 一.前言 二.本文最终效果 三.MAST工具基本操作 1.工具下载:Modular Asset Staging Tool(MAST) 2.导入工具:Import 3.创建场景:Scene 4 ...
- iOS cocos2d 2游戏开发实战(第3版)---你的第一个游戏!
2019独角兽企业重金招聘Python工程师标准>>> 随着苹果公司不断地创新与发展,新的iPhone 5.iPad 4以及iPad mini产品相继问世,包括iOS与Xcode在内 ...
- HTML5 Canvas游戏开发实战 PDF扫描版
HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...
- 《HTML5 Canvas游戏开发实战》——2.1 绘制基本图形
本节书摘来自华章计算机<HTML5 Canvas游戏开发实战>一书中的第2章,第2.1节,作者:张路斌著, 更多章节内容可以访问云栖社区"华章计算机"公众号查看. 2. ...
- 从踩坑到填坑|淘宝Web 3D应用与游戏开发实战
导读:本文是淘宝前端技术专家--徐乾伟(烧鹅)分享的淘宝 Web 3D 应用与游戏开发实战,这个话题在业界被谈及得比较少.今天将会从移动.3D.游戏三种交叉的话题来和大家探讨.接下来和小编一起从初试 ...
- HTML5游戏开发实战
<HTML5游戏开发实战> 基本信息 原书名:HTML5 Games Development by Example: Beginner's Guide 作者: (美)Makzan 译者: ...
- 微信小游戏开发实战教程14-闯关模式的实现
这是微信小游戏开发实战系列的第14篇. 本文主要内容是介绍精致1010闯关模式的设计和实现思路. 如果你没有任何的游戏开发经验,欢迎阅读我的"人人都能做游戏"系列教程,它会手把手的 ...
- 【Unity】动作游戏开发实战详细分析-15-可扩展的战斗系统
[Unity]动作游戏开发实战详细分析-15-可扩展的战斗系统 系统设计 攻击信息传递 通常情况下,伤害.属性.判定都会被封装到类中,在触发动画事件后将战斗信息发送给受击者. 我们可以结合Unity碰 ...
- 微信小游戏开发实战教程12-广告的开通和接入
微信小游戏开发实战系列的第12篇, 本节内容主要包括:如何尽快的开通广告功能,以及如何将广告接入到微信小游戏中. 如果你没有任何的游戏开发经验,欢迎阅读我的"人人都能做游戏"系列教 ...
最新文章
- shell介绍,命令历史,命令补全和别名 ,通配符, 输入输出重定向
- 箱线图怎么判断异常值_原创【六西格玛工具解读】02——箱线图(Boxplot)
- 如何利用1%推广费用提高50%的用户增长
- linux系统中使用oracle透明网关连接db2数据库,Linux系统中使用Oracle透明网关连接DB2数据库...
- Linux运维工程师面试题第三套
- android代码获取应用名称,Android获取应用程序名称(ApplicationName)
- 如何把Kubernetes config view里的base64编码过后的secret信息还原
- 富士通成功开发全球最快的36量子位量子模拟器
- 【Java】Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方
- 【干货】推荐系统解构.pdf(附下载链接)
- 输入防插错过压保护电路
- MOTO me525 DEFY 2.2 刷机全程详细指导
- php smarty框架案例,PHP框架_Smarty
- MRAM学习笔记——3.SOT-MTJ SPICE model解析
- Bootstrap 格栅 row-cols-X row-cols-3 row-cols-5
- hue oozie rerun使用问题记录
- Android TabLayout设置选中状态标题字体大小,粗细
- Date.getTime() 方法
- projectManager
- java方法传参机制
热门文章
- 【Echarts系列】Vue2项目如何引入echarts
- The Log: What every software engineer should know about real-time data's unifying abstraction
- 跨平台开发方案的三个时代
- 如何在SAP 分析云中使用类似Excel的表格 | 易拓科技
- Simulink模型生成C语言
- Linux 【权限,粘滞位】
- 第一讲:个人建站云服务器选择
- Keil5 点击Debug Setting 使软件奔溃的解决方法
- 华为路由器hilink怎么用_路由器是华为HiLink协议的连接中心
- 空号筛选接口的原理和优势