如何用unity3d素材构建mc那样的体素地图

温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
我是阿赵,请多多指教!
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
首先直接把脚本拖到某物体上面,运行,就会出现了上图所示的一个面片。这是因为为了方便大家测试,我在start里面调用了下面的SetTerrain方法。这个方法会创建一个默认的地形面板。长宽是100*100,段数是50*50,高度是-10米到10米的。 当然了,我们真正用的时候,是使用重载的SetTerrain方法自己制定长宽高和段数这些数值的,把start里面的方法注释掉就行了。&现在由于没有指定默认的地面材质和高度图,所以我写了个警告提示。&这两个变量就是材质和高度图了,大家可以自行想办法去赋值。我现在写成public只是为了方便赋值测试,最好还是写get/set方法赋值。还有一点,现在没有做地面的多通道材质,所以只是用了一个默认的shader。以后假如需要混合通道材质,改这个shader。好,先不管以后了,把一个有草地纹理的材质球付给脚本。&出来了一个草地&我随便的用黑白图刷了一个高度图,然后扔进脚本。&注意的是,作为高度图的图片,是需要设置读写权限的,不然获取不到像素的颜色&出现了一个小小的山坡了。&其实我这个脚本并不是必须针对黑白图的,我随便拿了一张木箱子贴图,一样可以做高度图的,这是因为我是做了灰度处理的,最后获取的是该图片像素点上的灰度值。&看,地形出来了。实际效果 功能是简单了点,这里提供了一点点的思路,有需要或者有兴趣的朋友可以参考一下做法,自行的扩展吧。源码:TerrainManager.csusing UnityEusing System.Cpublic class TerrainManager : MonoBehaviour {& & //材质和高度图& & public Material diffuseM& & public Texture2D heightM& & //顶点、uv、索引信息& & private Vector3[]& & private Vector2[]& & private int[]& & //生成信息& & private Vector2//长宽& & private float minHeight = -10;& & private float maxHeight = 10; & && & private Vector2& & private float unitH;& & //面片mesh& & private GameO// Use this for initializationvoid Start () {& & & & //默认生成一个地形,如果不喜欢,注销掉然后用参数生成& & & & SetTerrain(); }& & /// &summary&& & /// 生成默认地形& & /// &/summary&& & public void SetTerrain()& & { & & & && & & & SetTerrain(100, 100, 50, 50,-10,10);& & }& & /// &summary&& & /// 通过参数生成地形& & /// &/summary&& & /// &param name="width"&地形宽度&/param&& & /// &param name="height"&地形长度&/param&& & /// &param name="segmentX"&宽度的段数&/param&& & /// &param name="segmentY"&长度的段数&/param&& & /// &param name="min"&最低高度&/param&& & /// &param name="max"&最高高度&/param&& & public void SetTerrain(float width, float height, uint segmentX, uint segmentY,int min,int max)& & {& & & & Init(width, height, segmentX, segmentY,min,max);& & & & GetVertives();& & & & DrawMesh();& & }& & /// &summary&& & /// 初始化计算某些值& & /// &/summary&& & /// &param name="width"&&/param&& & /// &param name="height"&&/param&& & /// &param name="segmentX"&&/param&& & /// &param name="segmentY"&&/param&& & /// &param name="min"&&/param&& & /// &param name="max"&&/param&& & private void Init(float width, float height, uint segmentX, uint segmentY, int min, int max)& & {& & & & size = new Vector2(width, height);& & & & maxHeight =& & & & minHeight =& & & & unitH = maxHeight - minH& & & & segment = new Vector2(segmentX, segmentY);& & & & if (terrain != null)& & & & {& & & & & & Destroy(terrain);& & & & }& & & & terrain = new GameObject();& & & & terrain.name = "plane";& & }& & /// &summary&& & /// 绘制网格& & /// &/summary&& & private void DrawMesh()& & {& & & & Mesh mesh = terrain.AddComponent&MeshFilter&().& & & & terrain.AddComponent&MeshRenderer&();& & & & if (diffuseMap == null)& & & & {& & & & & & Debug.LogWarning("No material,Create diffuse!!");& & & & & & diffuseMap = new Material(Shader.Find("Diffuse"));& & & & }& & & & if (heightMap==null)& & & & {& & & & & & Debug.LogWarning("No heightMap!!!");& & & & }& & & & terrain.renderer.material = diffuseM& & & & //给mesh 赋值& & & & mesh.Clear();& & & & mesh.vertices =//,pos);& & & & mesh.uv =& & & & mesh.triangles =& & & & //重置法线& & & & mesh.RecalculateNormals();& & & & //重置范围& & & & mesh.RecalculateBounds();& & }& & /// &summary&& & /// 生成顶点信息& & /// &/summary&& & /// &returns&&/returns&& & private Vector3[] GetVertives()& & {& & & & int sum = Mathf.FloorToInt((segment.x + 1) * (segment.y + 1));& & & & float w = size.x / segment.x;& & & & float h = size.y / segment.y;& & & & int index = 0;& & & & GetUV();& & & & GetTriangles();& & & & vertives = new Vector3[sum];& & & & for (int i = 0; i & segment.y + 1; i++)& & & & {& & & & & & for (int j = 0; j & segment.x + 1; j++)& & & & & & {& & & & & & & & float tempHeight = 0;& & & & & & & & if (heightMap != null)& & & & & & & & {& & & & & & & & & & tempHeight = GetHeight(heightMap, uvs[index]);& & & & & & & & }& & & & & & & & vertives[index] = new Vector3(j * w, tempHeight, i * h);& & & & & & & & index++;& & & & & & }& & & & }& & & && & }& & /// &summary&& & /// 生成UV信息& & /// &/summary&& & /// &returns&&/returns&& & private Vector2[] GetUV()& & {& & & & int sum =Mathf.FloorToInt( (segment.x + 1) * (segment.y + 1));& & & & uvs = new Vector2[sum];& & & & float u = 1.0F / segment.x;& & & & float v = 1.0F / segment.y;& & & & uint index = 0;& & & & for (int i = 0; i & segment.y + 1; i++)& & & & {& & & & & & for (int j = 0; j & segment.x + 1; j++)& & & & & & {& & & & & & & & uvs[index] = new Vector2(j * u, i * v);& & & & & & & & index++;& & & & & & }& & & & }& & & && & }& & /// &summary&& & /// 生成索引信息& & /// &/summary&& & /// &returns&&/returns&& & private int[] GetTriangles()& & {& & & & int sum = Mathf.FloorToInt(segment.x * segment.y * 6);& & & & triangles = new int[sum];& & & & uint index = 0;& & & & for (int i = 0; i & segment.y; i++)& & & & {& & & & & & for (int j = 0; j & segment.x; j++)& & & & & & {& & & & & & & & int role = Mathf.FloorToInt(segment.x) + 1;& & & & & & & & int self = j +( i*role); & & & & & & & && & & & & & & & int next = j + ((i+1) * role);& & & & & & & & triangles[index] =& & & & & & & & triangles[index + 1] = next + 1;& & & & & & & & triangles[index + 2] = self + 1;& & & & & & & & triangles[index + 3] =& & & & & & & & triangles[index + 4] =& & & & & & & & triangles[index + 5] = next + 1;& & & & & & & & index += 6;& & & & & & }& & & & }& & & && & }& &&& & private float GetHeight(Texture2D texture, Vector2 uv)& & { & & &&& & & & if (texture != null)& & & & {& & & & & & //提取灰度。如果强制读取某个通道,可以忽略& & & & & & Color c = GetColor(texture, uv);& & & & & & float gray = c.//或者可以自己指定灰度提取算法,比如:gray = 0.3F * c.r + 0.59F * c.g + 0.11F * c.b;& & & & & & float h = unitH *& & & & & && & & & }& & & & else& & & & {& & & & & & return 0;& & & & }& & }& & /// &summary&& & /// 获取图片上某个点的颜色& & /// &/summary&& & /// &param name="texture"&&/param&& & /// &param name="uv"&&/param&& & /// &returns&&/returns&& & private Color GetColor(Texture2D texture, Vector2 uv)& & {& & & & Color color = texture.GetPixel(Mathf.FloorToInt(texture.width * uv.x), Mathf.FloorToInt(texture.height * uv.y));& & & && & }& & /// &summary&& & /// 从外部设置地形的位置坐标& & /// &/summary&& & /// &param name="pos"&&/param&& & public void SetPos(Vector3 pos)& & {& & & & if (terrain)& & & & {& & & & & & terrain.transform.position =& & & & }& & & & else& & & & {& & & & & & SetTerrain();& & & & & & terrain.transform.position =& & & & }& & }}&
阅读(21952)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
在LOFTER的更多文章
loftPermalink:'',
id:'fks_',
blogTitle:'Unity3D动态创建地形网格(一)',
blogAbstract:'\t最近一直都在搞flash3D,好像有点对不起Unity3D的朋友们了。这次简单的写一个动态创建地形网格的脚本给大家分享一下。\t这次是第一部分,仅仅实现了通过高度图动态生成地形的部分。假如以后有心情和时间,再来慢慢的补充多通道刷地形材质、动态刷地形和保存高度图等的功能吧。以前我都不喜欢公开脚本源码,都是一个个部分的单独讲解然后让朋友们自己去组合起来的,但最近时间实在是不多,所以还是直接提供源码,然后在源码上面写注释,大家自行的观看吧。源码在最下面。\t',
blogTag:'unity3d,地形,高度图',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:5,
publishTime:6,
permalink:'blog/static/',
commentCount:6,
mainCommentCount:4,
recommendCount:1,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'我是阿赵,请多多指教!',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}Monster Farm 开发日志(三)体素游戏美术心得 | indienova 独立游戏
HiMoEGame @indienova
Monster Farm 开发日志(三)体素游戏美术心得
作者:Lea Liu链接:/p/来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。大家好,又到了更新Monster Farm开发日志的时候,这次是由我大狸主讲。作为更文一定要又臭又长又啰嗦的强迫症,我已经看不下去前面 (Zed)@ (下文可能会习惯成自然地称他为萍萍)那两只写的名为开发日志实为撒娇秀基情实况的东东了……这次我得贡献一点有实质性的内容,不然搞基搞多了大家还以为我们做的不是Game而是Gayme呢……虽然很想分享一下我们后来建立游戏世界观、角色和剧情的过程,但想来想去我的工作这部分可能还是从头说起比较好,这次的日志我就谈谈我们如何一步步推进游戏美术风格的构建,将Voxel画风的游戏尽可能做得美型的心得吧。鉴于可能还有朋友不太清楚Voxel的概念,这里先科普一下:Voxel,就是Volume-Pixel的缩写,中文一般称体素,也就是体积像素。是一种把电脑中二维空间的最小单位——像素,空间化3D化了以后的概念。像素的最小单位可以看作是一个个小正方型,体素的最小单位也可以看作是一个个小正方体。用这种构成方式制作的模型就是体素模型,做成的游戏就是体素游戏。举例来说,我们最熟悉的马里奥,最早的像素风是这样的:转换成体素后就是这样的:如果把马里奥横板过关游戏做成体素风格的,它可能就是这样的:蛮酷的对不对?有一种很爽的Q萌感,用 的话说就是有浓烈的玩具感,是一种天然具有玩乐感觉的非常适合游戏的风格。所以一开始Erenyx找我做主美的时候,告诉我这是款voxel风格的游戏,并给我看了MagicaVoxel这软件自带的一个小萌妹的时候,我就瞬间被迷住了。欸这种短短的粗粗的方方的感觉,好像个萌萌的小玩具啊!多么符合老阿姨我的胃口!于是一口答应下来。然而没多久,随着初步尝试了制作和进行了一点深入的了解,我发现了体素游戏黑暗的一面……体素=丑?不不不!对于很多人来说,第一个走进他们视野的Voxel游戏就是Minecraft了。这款游戏绝对是我长这么大来最心水的游戏前Top3。最让我钦佩的是,这款游戏达成了一个游戏美术梦寐以求的成就:玩法和美术风格无缝结合。构成游戏画面的基本元素——方块,同时也是构成游戏玩法的基本元素,紧密结合不分你我。不像绝大多数游戏,玩法是玩法,画风么则随了个便,导致你辛苦做了个好玩法,分分钟就会被人拿去换皮九九八十一次冒充新游戏,欲哭无泪啊有木有!Minecraft则完全做到了画风和玩法绑定,换画风基本就是换玩法,所以现在即使是有仿MC的游戏,也多半根本改不掉MC那标志性的块块画风。敢抄玩法换皮?你会被人天天戳脊梁骨的:诶这不是MC吗?当然,渲染技术以后进步了MC也有可能被换皮,但至少……换皮冒充新游戏现在暂时是做不到了。这是游戏美术的浪漫!然而,在非美术人员的眼里可能就不是这样了。我不止一次听到人们对MC画风评价为“吃藕丑”。当初我在玩MC时,我爸刚好撞进屋来,看到的场景是这个样式的:我爸第一句话就是:这什么游戏?Dos游戏吗?画面怎么这么糙啊?你还玩这个?我该怎么跟他解释我不是在开Dos游戏怀旧,这是2011年的新游戏……因为我得承认这配色、这粗糙的像素块、这锯齿,确实跟这货……有异曲同工之效啊! (上为我小时候最喜欢的Dos游戏《Prehistoric》)甚至可以说……《Prehistoric》的画面细节都比MC精细多了呢……同样,也有不少朋友是这种看法:为什么?明明是这么萌的小方方小块块们,大家为何会觉得丑?不过在做Voxel游戏的时候,我们也确实发现了Voxel风格有很多处理不好,分分钟就会让颜值唰唰往下掉的陷阱。作为一个美术,当然是要和“丑”战斗到底的,我想我们首先得把这些会让游戏长残的因素一条一条揪出来,再一条一条消灭掉,誓死捍卫游戏的颜值!一:光效和渲染首先,Minecraft给人“丑”的感觉的原因,也许第一条就是“缺乏光效和渲染”。没办法MC动辄同屏百万千万级的方块,再开实时渲染真的要狗带的。然而很多渲染插件都证明了假如有高大上的渲染,《我的世界》将是个多么美丽的世界:Minecraft制作的冰火君临城和绝境长城,加了光影水反天气渲染插件。这和上面那张图是一个游戏吗?!这一点对于我们的游戏来说则好办得多。我们不需要玩家砌方块,模型都是预置的,所以不用实时渲染千千万万的方块,可以完全把方块转换成普通的模型,再去开渲染就好办的多。我们的技术美术萍萍在这方面能提供足够的支持,通过自己写Shader和寻找黑科技,顺利把游戏画面加了宛如美图秀秀滤镜一般的特效…… 以上来自去年12月的prealpha版本,我反正觉得这画面是磨过皮的。这是问题之一,托萍萍的福,应该不是什么大问题。二:狗牙问题现在看我们的造型,不管是房子还是角色,都基本遵循了方方的风格,但它最初不是这样的。大概是这样的:造型里有很多的圆弧型和曲线,比如树冠是圆形的,树干也是弧线型的,围栏也是圆形的。我知道你想说这也不算太丑啊(嘿嘿这点自信还是有的),但是因为这图的模型是缩小的,所以看着还好,如果是在游戏里的话,它实际看上去是这样的:放大了看,颗粒感十分明显,我觉得这也挺萌的,但可能在外人眼里,又是会觉得“很糙”的一种感觉。最要命的在这里:这些地方的边缘,因为像素风的原因,参差不齐像狗牙一样,Voxel风和Pixel一样,如果像素数不够,在创建圆形和弧线结构的时候就会非常丑,全是狗牙。就连Photoshop看到这些都会受不了,哭着打开Anti-alias软化掉……。但在游戏里,如果我们坚持采用这种圆形和弧形很多的造型,就无法避免狗牙。有人也许会说:加大像素数不就好了。确实我们也想过这个方法,尤其是萍萍一开始是有点想要那种传统像素RPG风格biu~地一下就变成了立体的效果。我一开始也觉得这也可以的吧,因为体素不就是把像素变立体吗?比如星露谷,不也是像素风吗?把这种像素风Biu~地一下给做成立体的就行了吧?后来才发现这个想法拿衣服了。体素风格是把传统像素风格的每个点都变成立方体,这就意味着同样的单元数,单个体素所占用的资源都是单个像素的平方。这就导致了同样的场景,体素能接纳的像素数要大大少于传统像素图。还是拿马里奥举个栗子:这几代马里奥里,前5个都是像素风,但像素和像素仍然是不一样的,第一个像素马里奥的像素数可能也就是第五个马里奥的五分之一(图上前两个马里奥都拉大了,本来应该是极小的)。而上面星露谷的这张图的像素数(尤其是场景的像素数)保守估计又比第五代像素马里奥大了五倍。它已经精细到快要脱离”像素画“的范畴了。前面我们看过的马里奥体素模型。可以看到即使只是第二代马里奥的像素数,转换成体素后的体素数量也已经让人犯密恐了。事实就是即使是很小的像素图转换成体素模型后都是蛮大的,这都将给制作过程带来很大压力(主要是我们的破电脑都带不动太大的体素模型)。所以这也是为什么我们经常见到的体素模型都只有很低的分辨率。星露谷那个精度的体素模型,真的是不太现实。传统模型和体素模型的区别,简单来说如下图所示前者是一个外壳,就像超市促销时外面挂的气球人偶,内里是空心的,而后者则是由一个个小盒子堆成的,就像超市促销时用商品盒子堆积起来的货品堆。所以Voxel模型的特点就是在你看不见的内部,也含有大量的冗余面,这也是为什么Minecraft默认画面那么低质量,却要消耗比3A大作还要多的资源的原因。当然,前面说过了,其实我们最后是会把体素模型的颗粒转换成面,变成传统模型的,也就是把货品堆变成充气模型,所以我们的体素模型在Unity里的模型只是“伪体素模型”,它们其实内里也是空心的,最终游戏的体积倒是不用过多担心。但问题是,建模阶段我们确确实实是要用体素建模的方式来做得,也就是实打实地一粒一粒地堆出模型。所以至少在建模阶段,我们要和MC一样面临体素模型所带来的大量冗余面的问题。而现有的体素软件……我不是针对谁,我是说在座所有的……都是渣渣……MagicaVoxel根本就不支持128*128*128以上大小的体素模型,这还能提高个毛分辨率啊!(摔!)所以我们只好放弃了这款软件。最后选择了Qubicle,虽然它的优化也是渣渣,似乎压根就不能发动显卡的优化功能,任你的电脑配置再高它也是不动如山……模型稍微大一些就连建个选区都要卡上几分钟,并且笔刷不能调、油漆桶只能单用不能配合选区,挤出工具基本是废的,还动不动就崩溃……但好歹它支持无限大的模型。现有的体素软件都太不成熟了,毕竟是个小众的风格。有的用就不错了,要啥自行车啊!通过这个软件,我们确实可以一定程度上提高模型的精度(只要适当地容忍做模型时的卡顿就行了……),但这个提高是有限的,仍然不足以高到抗锯齿。要彻底解决狗牙问题还得另想办法。低分辨率的体素模型碰到弧线和斜线全是狗牙,看来只能通过在设定美术风格的时候尽量少地使用斜线和弧线来解决问题。体素风格的特长还是在立方体,你看Crossy Road不就是么,虽然分辨率很低,但整体却不显得Low,还很Q很玩具。因为他们几乎完全摒弃了斜线和弧线,全用的立方体。这样我们只要全用立方体去构成不就行了,一个点的立方体和100个点的立方体看上去没差,妈妈再也不用担心我们有狗牙。嘿嘿计划通!只要坚持立方体原则,它像素多了少了不都是个方吗?不怕的。三、风格化VS代入感古往今来,有很多采用立方体构成万物的美美的艺术品。比如:比如纪念碑谷再比如FEZ方不是问题,学艺术的都知道一句话:宁方勿圆。只要君子爱方,方之有道,一样能非常漂亮。现在几何化、扁平化、抽象化的画面也是潮流,用方,不落伍!然而随后我们又发现,方还是有问题的(……)。因为把任何事物都抽象成方的,基本上也就等于我们的艺术风格将会高度抽象化,风格化。你也许会问,这有什么问题呢?好多游戏不都是这样吗?问题就在于,高度的抽象感、符号化、形式化、玩具化的画风,确实能非常好地去匹配那些带给人“纯粹的玩乐感”的,玩具一样的游戏。往往被应用于一些以玩法为核心,不涉及太多的代入感和感情要素的游戏。但假如是一个带有叙事元素,和一定感情要素的游戏,就不一定了。比如这两个房子,左面的房子比较风格化,抽象,右面的则极尽写实。那么现在我们有一个关于家国大义爱恨情仇的史诗级故事要选择舞台,你会选择哪个房子作为它的发生地呢?很显然,右边的场景更写实、更有沧桑感,更适合人们代入这个故事。而左边的房子,作为童话故事的舞台还可以,过于现实主义的故事放在这里,说实话不太合适,你将无法面对着一个Q萌的场景去沉浸入一个恩怨情仇的史诗大片。当然你确实可以挑战用童话的画风讲一个特现实特悲惨的故事,营造这种”反差萌“的间离感。比如Happy Tree Friends,可爱明亮的画风讲得全是血腥的故事。但你得承认,这个动画虽然猎奇,却没那么多让人不忍直视的感觉,用可爱的画风削弱故事的不适感并营造“反差萌”正是他们想要的。但如果你想要老老实实地营造沉浸感,去让这个故事带给人他本来该有的印象,而不是利用反差制造间离感,故事和视觉风格是一定要匹配的。换用到我们的游戏中来,我们本来一开始也决定了用很抽象,很风格化,一切皆方的画风,一是为了解决狗牙问题,二也是为了让我们的游戏画风更突出,更酷更有风格。但这时我们回头看了看我们的大纲,想起了我们的故事。这是一个带有一定的恋爱养成要素,而且一定程度上有一定讽刺性的故事。(具体内容到下一次日志会讲)恋爱养成要素?我知道你要是对着这样的角色,找到一点恋爱般的感觉应该还是不难的:但如果是这样的角色……虽说也很有风格很可爱吧,但如果你不是miku厨,甚至事先不知道这个角色,要说恋爱的感觉实在是有点强人所难……我知道有些Miku厨即使给他们一坨蓝绿色的橡皮泥他们也能坠入爱河的,但这是因为这些厨脑子里本身就有Miku酱完整的形象……所以我们也会考虑给体素角色加上立绘造型,方便大家把它们脑补成小美女小帅哥。但即使这样,假如立绘画的是很唯美,但游戏画面本身却过于抽象,这两者的画风就差得太多了,撮合不到一块儿去。所以游戏场景本身的抽象度还是不能过高。所以,举这个栗子想说的就是:过于抽象的画风不匹配我们的世界背景和故事。我们的游戏不是只要投入脑细胞玩解谜玩动作就行了,而是希望玩家和游戏世界有一定的感情共鸣和代入感。纪念碑谷,Fez这些游戏以玩法为导向的特点很鲜明,叙事上致力于渲染一些小清新小朦胧的情愫,所以采用高度风格化的画风很合适。而且我们却并不想挑战和打印机/胖次/昆虫/学园Handsome谈恋爱的那种游戏,只想老老实实做一款正常的带有一点恋爱要素的怪物养成和农场游戏。所以我们无法寄希望于玩家看着一堆不成人形的方块角色和极简单的方块建筑对这个世界产生认同感。过于抽象,抽象到让人无法沉浸和代入感情的画风恐怕也是不行的。好了,以上就是关于我们游戏的美术风格该走什么路线的一个漫长而艰难的思考过程。了解了这些种种的限制,接下来就该着手设计可用的概念了。既然过于精细的画风技术上实现不了,过于抽象的画风又不扣题,我们是真的有了前门拒狼后门进虎的感觉……此时我脑海中又浮现出了《游戏发展途上国》中的景象………………“Lea Liu请求挑战游戏美术方面的提升”,成功了当然皆大欢喜,失败了就要背上一头Bug哦……那个时候,我们的其实已经有了第一版prototype了。萍萍表示对原来的风格挺满意的,听说我要Boost非常伤感……那几天我隔着十米都能感觉到他怨念的气场射向我……。然而我和Zed讨论了以上存在的问题,要改风格决心已定了。究竟要怎么画出既保留了Voxel以立方体为主的造型特点,又能让画面适度地丰富,有一定的写实感和代入感,不至于过于抽象呢?当然首先想到的还是先把造型风格都改方,还是用主角的家的这间树屋举例:无论是树干房屋还是树冠,一律都放弃了圆弧和斜线,改用方形,甚至连屋顶都改为了平顶房。但是真是有种莫名的不爽感,这样的房子太丑,实在是不符合我的美学……于是还是适当地请回了斜线元素,屋顶仍然是斜坡。屋顶本身就有瓦片形成的阶梯状,看上去不会马上让人联想到狗牙,问题不大。这样房子的基本型定下来了,又在房子到底该有多少细节上纠结了一阵,最终还是搞出来了。只要不过多的使用圆弧和斜线,有一点点的话是可以容忍的。之前的树冠还是太像Fez了,找了一堆参考摸索了一阵,终于改为了给树冠贴花纹,细节量和装饰感都上去了,颜色也调整到更雅致鲜明。基础型从绝对的方改为了圆角方,在大部分地方对方形进行软化。感觉终于在风格化和代入感上达成了比较满意的平衡。这样,这张图包含了建筑的风格、树、植物的风格,基本奠定了游戏后来整体的风格。拿去问了一圈,大家基本还是喜欢这个新版的。不过有了这张平面图还没完,拿到游戏里能不能有好的效果又是另外一回事,于是 顶着Qubicle的卡顿把这个模型赶紧撸了出来,然后用PS模拟了一下最终的游戏效果,加了点虚拟的UI和渲染,看看3D化后的世界是怎样的。看样子是可以达到不错的效果的。萍萍看到这里,好像怨念终于没那么大了……呼,松一口气,脑内浮现了这个画面:挑战成功!贴几张制作进行到现在的画面表现,虽然还没完全实现概念图上的全部效果,但大体基调已经奠定得不错了。以上,基本就是Monster Farm的游戏美术风格是如何建立起来的全过程。经历了第一版概念---&prototype——&发现问题——&第二版概念的过程。虽然看似走了些弯路,但其实仔细想想也是游戏制作中的必经之路。毕竟初版概念的时候只是把自己脑中对这个游戏的想象具象化,而在技术上、游戏题材上对美术有什么要求和限制这个时候还不能完全搞清楚。随着制作的推进,肯定会遇到各种各样的问题,马上就会发现第一次的概念不足的地方。我们在确定修改美术概念的时候,主要考虑了以下几个方面:引擎、技术能否支持这个概念的表现概念实现的时候是否会有明显的瑕疵画面与我们想表达的世界观、故事背景是否匹配游戏的风格是否有特点、突出,能成为游戏显著的标志之一游戏美术这个工作和纯粹的画画不一样的地方在于,游戏美术很多时候都都要“戴着镣铐跳舞”,需要考虑到机能限制、题材限制,要用美术去支持玩法,要考虑人机交互,操作体验。统统考虑这些之后,还要做出鲜明醒目的风格来给游戏打上独特的标识,不过我个人反而觉得这正是干这个工作有趣的地方,仿佛也有一种游戏般心态:毫无限制和规则的创作和绘画,比不上这样在有限制和规则的情况下,运用个人学识和智慧尽可能地达成目标更有趣,这不正是玩游戏的精神吗?最后感谢TeamHiMoe全组成员,@ 的技术美术支援,关于大方向上的思考和支持 夜以继日地顶着卡顿做模型……美术这件事从来也不是主美一个人的成就。就这样。=============================================================如果您对Monster Farm的后续信息和更新感兴趣,欢迎关注我们的微博:@或本专栏:纽大游戏故事&
已有 0 人赞过
已有 2 读者收藏
&分享这篇文章
参与此日志的讨论
知乎的图片挂了,知乎有防盗链
您需要登录或者注册后才能发表评论
<div id="success-message" data-notify-position="top-right" data-notify-type="success" data-notify-msg=" 消息已经成功发送!">
<div id="failed-message" data-notify-position="top-right" data-notify-type="error" data-notify-msg=" 操作失败!请通知管理人员。">

我要回帖

更多关于 unity3d素材 的文章

 

随机推荐