
又被人翻出来了,很多人私信我怎么学VR,我很欣慰,时隔我回答那个问题两年后,在2017回归冷静的VR元年里,还有这么多的人喜欢VR,想尝试做些什么。
从2014年底VR(虚拟现实)被cardboard开始带进人们的生活后,VR这两个字母可以说是红极一时,从一开始的养在深闺人未识到后来暴风妖股惊爆眼球,3大头显各显神通,毫无疑问VR在这两年里掀起了一股浪潮。很多人知道我在做VR后,就开始问我,怎么学VR?此时的你,或许刚刚听说VR这个名词,觉得好奇,想尝试下,或许刚刚从体验馆里出来,激动不已,说这就是我想做的,又或者已经久经阵仗,各类游戏挥手既能通关,觉得没一个能打的,想自己上马……不管你出于怎样的动机,但当你抱着一腔热血想踏入VR开发的领域,这时候你就可以……先来个冰桶冷静冷静了。
仅有一腔热情是不成的,你需要面对一些残酷的现实:刚刚过去的2016年里资本由年初的疯狂到年末的迅速冷静,伴随的是众多浑水摸鱼的公司的消亡,这个由资本催生的迅速膨胀的行业将在2017年回归冷静。不会再出现只会逻辑代码的蹩脚程序猿就能拿高薪做主程,不会再出现玩过几个VRDemo就口若悬河宣称自己有个惊世Idea让大家来搞一波,不会再出现拿着个三流Demo就能拿上一大笔融资胡天海地忽悠一堆投资人……仿佛又回到了2014年前,这个行业只需要,也只留得下真正想做事的人。
假如以上没有吓到你,依然一心想在这个行业做出一些价值,那么,恭喜你,你即将踏入一个充满希望和未来的世界,你将会接触到一些前沿的科技,解决一些行业的痛点,甚至如乔布斯那般,引爆一个技术奇点,开启新一轮的科技革命。
那么,即将踏上征程的你,请先检查手边的工具,搭建属于自己的武器:
1、一台PC是必不可少的,笔记本或者台式都行,性能需要高一点,有个独显就行,当然要比610M这种垃圾好一点,不要问我怎么知道的……
2、一个VR头显,可以是三大头显,也可以是MoblieVR,甚至用纸折个cardboard也能正常工作。不过为了较好的体验,不卡的手机,加上带着舒服点的国产盒子就可以了。假如你有三星的手机,可以尝试GearVR,专门针对VR做了优化,再假如你有小米5以上的新款手机,甚至可以多花200块钱买个小米VR,提前感受下DreamVR的体验,虽然是缩水版……
3、假如手边还有空余的外设,比如飞行摇杆,体感设备,那当然是多多益善了,虽然你一时半会是用不上他们的。
有了1、2两点,就可以进行VR的学习了。
首先在开发之前,至少应该对VR这个概念有个深刻的了解,这时候我推荐看我的叨逼文:
VR的前世今生系列
,有点长2W多字,讲了下VR相关的历史,看看就好,嫌长可以直接跳过。
一些行业内的大神的博客或者知乎也是非常值得关注的,比如:
我看他教程学会unity的真·老司机
康拓耶夫
生命不息创业不止的老司机
许荣雨
焰火工坊的
娄池
特能侃的交互设计师
胡痴儿
以及刚毕业就义无反顾跳坑的后起之秀:
王星杰
等等,知乎上藏着很多大神有待大家去发掘,在诸位大触面前,我这只萌新只能瑟瑟发抖。
接下来就是正式的开发之路了。踏出第一步总是艰难的,点开百度,搜索VR开发,你会发现你的屏幕充斥着“7天快速上手”,“21天从入门到精通”等等诸如此类的文章,这些文章有一个共通点就是提到了游戏引擎。作为目前主流的VR解决方案,学习一款热门的游戏引擎是较为快速的上手方案了。这类引擎已经集成了大量的新特性支持对VR的开发,甚至鼠标点点就能做出一个应用。
详见:
VR内容设计的整个工作流程是怎样的,需要get哪些新技能?
通常采用的引擎有unity,unreal engine 和cryengine,可以说是三款最热门的商用引擎了。假如你刚刚接触开发,我建议学习unity,目前来说,unity是使用最广泛,资料最多,素材最多的引擎,你可以很快上手,并用丰富的素材做出一个大概的Demo。假如有建模和美术基础,可以尝试unreal engine,这是一个对美术友好的引擎,你大可一行代码不写,像做材质一样控制程序逻辑。假如你有一定的基础,又敢于尝试,cryengine也是不错的选择(吗?)
一些入门教程供您参考:
雨松MOMO的Unity研究院我那太监了的UE入门教程
实践一般都是有着某种方向和目的,一个渐进的道路是从简单的全景图片做起,找张全景图丢进引擎,找段代码绑定陀螺仪和视角,发布个VR版本的APP,一个最简单的VR应用就诞生了。接着就开始熟悉VR的各种理论,双目视觉,场景交互,灯光,材质,渲染,物理等等都有待探索学习。
具体的引擎学习不再阐述,只要明白一点:
常到相关社区逛逛对新人来说很有用,这里推荐几个:
Gad-腾讯游戏开发者平台游戏蛮牛
虚幻中国社区
值得一提的是,一些非常有用的资源会加快你学习的速度,比如官方的VR Demo,第三方插件VRtoolKit等。
当你学会使用某一款引擎后,你可以更深入的尝试了,对于刚出道没多久的菜鸟们,混迹于各种各样的行业,接触行业应用,尝试用VR解决一些需求,熟悉团队协作,开发流程,接触各种行业解决方案。
一些热门的行业有:游戏开发设计,房地产建筑表现,影视动画,新媒体艺术,教育医疗等等。各行各业都有自己的圈子,此处就不在赘述。
一些已经开始在各个行业内耕耘的企业,注意:此图出自某位大神的答案,一时半会找不到链接了,哪位找到麻烦告知替换:
当在这个行业摸爬滚打了一段时间后,开始发现自己已经能够胜任某一方的工作,你开始不满足现状,会进行更加深入的尝试。
这期间你会意识到基础的重要性,于是你啃完了 图形学相关,高级编程技术,人机工程学,人机交互设计等等:
打好了基础才能进行进行更深入的尝试,通过理解不同的渲染方式,实现更加细腻的画面表现,酷炫的特效,高级光影效果等等。(渲染这块我比较坑,属于菜逼中的战斗鸡,而且说实话,动辄几万十几万的工程量,不如自己看论文实现……)
这里有本大触的书可以看,能试读到第五章,我反正觉得,6翻了:
thegibook| 《全局光照技术:从离线到实时渲染》(2017年出版)
还有个牛逼的论坛:OpenGPU
或者你可以尝试一些新的表现形式,研究交互,各种各样的人机交互技术,语音识别,动作捕捉,人脸识别。
VR交互设计理念:
胡痴儿的VR/AR界面设计汇总
VR游戏界面设计︱怎么做到实用又逼真?
又或者你不满足引擎给你提供的功能,开始修改底层,甚至自己创造各种各样的轮子,成为一只高级码农。
游戏程序员的学习之路(中文版)
当然你也有可能突发奇想,想创造一个虚拟的生物,于是你转而研究人工智能。
有一天你发现硬件对你的束缚越来越大,转而研究硬件,从驱动到机械结构,突破各种各样的物理界限。当你发现机械已经无法支撑你的产品,你开始研究生物技术,企图直接在人脑中构造你的VR帝国,最终,你创造了一个新的人机交互模式,人们称它为:黑客帝国。
最后,当你产品出货亿万,覆盖整个星球,整个世界都在你的麾下瑟瑟发抖,这时候,记得给我定制上一打妹纸哟。
NSMutableDictionary *targetMutableDictionary = [mutableDictionary1 copy][targetMutableDictionary addEntriesFromDictionary:mutableDictionary2]
/*------------------------------------创建可变字典------------------------------------*/
//创建
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]
//添加字典
[dictionary setObject:@"One" forKey:@"1"]
[dictionary setObject:@"Two" forKey:@"2"]
[dictionary setObject:@"Three" forKey:@"3"]
[dictionary setObject:@"Four" forKey:@"4"]
NSLog(@"dictionary:%@",dictionary)
//删除指定的字典
[dictionary removeObjectForKey:@"3"]
NSLog(@"dictionary:%@",dictionary)
========================================================================
NSDictionary *dict
for(NSString * akey in dict)
{
//........
}很好用
1.创建不可变词典
[NSDictionary dictionaryWithObjectsAndKeys:..] : 使用键值对儿直接创建词典对象,结尾必需使用nil标志结束。
[NSDictionary initWithObjectsAndKeys:..] :使用键值对儿初始化词典对象,结尾必需使用nil标志结束。
[dictionary count]: 得到词典的长度单位。
[dictionary keyEnumerator]: 将词典的所有KEY储存在NSEnumerator中,NSEnumerator很像Java语言 中的迭代器,使用快速枚举可以遍历词典中所有储存KEY值。
[dictionary objectEnumerator]: 将词典的所有value储存在NSEnumerator中,用法和上面差不多可用来遍历KEY对应储存的Value值。
[dictionary objectForKey:key]: 通过传入KEY对象可以拿到当前KEY对应储存的值
#import <UIKit/UIKit.h>
#import "MyClass.h"
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
//添加我们的测试代码
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"雨松MOMO",@"name",@"15810463139",@"number", nil]
//得到词典的数量
int count = [dictionary count]
NSLog(@"词典的数量为: %d",count)
//得到词典中所有KEY值
NSEnumerator * enumeratorKey = [dictionary keyEnumerator]
//快速枚举遍历所有KEY的值
for (NSObject *object in enumeratorKey) {
NSLog(@"遍历KEY的值: %@",object)
}
//得到词典中所有Value值
NSEnumerator * enumeratorValue = [dictionary objectEnumerator]
//快速枚举遍历所有Value的值
for (NSObject *object in enumeratorValue) {
NSLog(@"遍历Value的值: %@",object)
}
//通过KEY找到value
NSObject *object = [dictionary objectForKey:@"name"]
if (object != nil) {
NSLog(@"通过KEY找到的value是: %@",object)
}
int retVal = UIApplicationMain(argc, argv, nil, nil)
[pool release]
return retVal
}
2.创建可变词典对象
NSMutableDictionary 是NSDictionary的子类,所以继承了NSDictionary的方法。
[NSMutableDictionary dictionaryWithCapacity:10] : 创建一个可变词典初始指定它的长度为10.,动态的添加数据如果超过10这个词典长度会自动增加,所以不用担心数组越界。推荐用这种方式
[NSMutableDictionary initWithCapacity:10] :只是初始化一个词典的长度为10。
[dictionary setObject:@"雨松MOMO" forKey:@"name"] :向可变的词典动态的添加数据 ,这里的key是name ,值是雨松MOMO。如果词典中存在这个KEY的数据则直接替换这个KEY的值。(易混的地方,慎重!)
[dictionary removeAllObjects..] : 删除掉词典中的所有数据。
[dictionary removeObjectForKey..] :删除掉词典中指定KEY的数据 。
#import <UIKit/UIKit.h>
#import "MyClass.h"
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
//添加我们的测试代码
//创建词典对象,初始化长度为10
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:10]
//向词典中动态添加数据
[dictionary setObject:@"雨松MOMO" forKey:@"name"]
[dictionary setObject:@"15810463139" forKey:@"number"]
//通过KEY找到value
NSObject *object = [dictionary objectForKey:@"name"]
if (object != nil) {
NSLog(@"通过KEY找到的value是: %@",object)
}
int retVal = UIApplicationMain(argc, argv, nil, nil)
[pool release]
return retVal
}
=====================================================================
//创建不可改变的词典
NSDictionary * dictionary
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"good lucky",@"why",@"bye bye",@"how",nil]
//里面的元素个数是奇数(不包括最后的 nil)的话是不可以的,偶数才行,因为是 id key 一组一组对应的
//输出词典的数量
NSLog(@"词典的数量= %lu",[dictionary count])
/*得到词典中所有的键值的过程 NSEnumerator 用来遍历集合中每一处索引的对象*/
//*******************************遍历数据字典
//先得到里面所有的键值 objectEnumerator得到里面的对象 keyEnumerator得到里面的键值
NSEnumerator * enumerator = [dictionary keyEnumerator]//把keyEnumerator替换为objectEnumerator即可得到value值(1)
//定义一个不确定类型的对象
id object
//遍历输出
while(object = [enumerator nextObject])
{
NSLog(@"键值为:%@",object)
//在这里我们得到的是键值,可以通过(1)得到,也可以通过这里得到的键值来得到它对应的value值
//通过NSDictionary对象的objectForKey方法来得到
//其实这里定义objectValue这个对象可以直接用NSObject,因为我们已经知道它的类型了,id在不知道类型的情况下使用
id objectValue = [dictionary objectForKey:object]
if(objectValue != nil)
{
NSLog(@"%@所对应的value是 %@",object,objectValue)
}
}
//*******************************遍历数据字典
//创建可改变的词典 它是动态的
//需要我们初始化一个空间大小,用dictionaryWithCapacity
NSMutableDictionary * mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:5]
//这里我们给的空间大小是5,当添加的数据超过的时候,它的空间大小会自动扩大
//添加数据,注意:id key 是成对出现的
[mutableDictionary setObject:@"good lucky" forKey:@"why"]
[mutableDictionary setObject:@"bye bye" forKey:@"how"]
//输出 不用遍历就得到键值和value的方法,allKeys和allValues
NSLog(@"输出所有键值=%@",[mutableDictionary allKeys])
NSLog(@"输出所有的value=%@",[mutableDictionary allValues])
//动态体现在可以动态的添加数据 现在修改键值是why的value值,
//然后在打印就会发现value是改变了,但是NSDictionary却不可以修改
[mutableDictionary setObject:@"good" forKey:@"why"]
NSLog(@"输出所有键值=%@",[mutableDictionary allKeys])
NSLog(@"输出所有的value=%@",[mutableDictionary allValues])
//动态删除
//删除指定键值的数据
[mutableDictionary removeObjectForKey:..]
//删除所有数据
[mutableDictionary removeAllObjects]
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)