Unity3D for VR 学习(11): 后期屏幕渲染特效(Image Effect)

Unite ShangHai 2016 Keynote中,《Adam》的图形技术介绍,令人印象深刻:可以与电影效果相媲美、近乎次时代大作、好莱坞大片效果的3分钟实时渲染的短片,淋漓尽致的展现了Unity 5.4的奋发图强,和对VR开发者的潜台词–“相信Unity 5.4,VR没错的。”

本文就Image Effect进行实践,所用版本是Unity 5.4.0b14 beta版本。

image

 

下载Image Effect插件

Unity内置的特效,已经于2015.12.10免费开源了:CINEMATIC IMAGE EFFECTS (PRE-RELEASE)

 

  • 下载方式2:bitbucket 开源社区   cinematic-image-effects          为了持续增强Image Effect的功能和提高性能,官方还设立一个论坛版块:

          Forums>Unity Community Support>Graphics>Image Effects

 

部分渲染特效实践

使用渲染特效,非常简单,直接在Camera添加组件即可—下载完Image Effect插件后,导入Unity即可使用。

image

 

Screen Space Reflection屏幕空间光线追踪反射(SSRR)倒影效果image
Screen Space Ambient Occlusion (SSAO)  屏幕空间环境遮挡特效 —模拟全景漫反射

image

 

反|抗锯齿(Anti Aliasing | SMAA).

image

 

Bloom 泛光 场景变得梦幻

image

色调映射 ToneMapping【HDR模式有用】–  [和Bloom混合使用]

clip_image001

深入学习文档

Unity自带的英文文档,非常好,下载Unity的时候直接安装一下,遇到问题,点击问号,即可打开本地的英文文档,便于深入快速学习。

image

 

然后,输入Image Effect关键字搜索,即可打开Unity内置提供的特效帮助–有图、有文字说明,学习还是挺方便的。

image

 

后期屏幕渲染原理

屏幕后期渲染,使用的是Graphics的Blit方法,他和相机的Render方法不同之处在于Blit在屏幕上做了一个和屏幕大小一样的平面,用第三个参数(材质—Shader)进行从当前面到新面的替代。 即Blit是在渲染一个平面,而Render在渲染一个物体。

Graphics.Blit函数

public static void Blit(Texture source, RenderTexture dest, Material mat);

 

MonoBehaviour.OnRenderImage函数

void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)

 

Shader文件:写一个顶点片段shader

#pragma vertex vert_img
#pragma fragment frag

 

备注:

  • 参考文档 《Unity 5.X 从入门到精通》
  • 参考文档 《Unity Shaders and Effects Cookbook》
  • demo Git地址:Shader_ImageEffects

Unity3D for VR 学习(9): Unity Shader 光照模型 (illumination model)

关于光照模型

所谓模型,一般是由学术算法发起, 经过大量实际数据验证而成的可靠公式

现在还记得2009年做TD-SCDMA移动通信算法的时候,曾经看过自由空间传播模型(Free space propagation Model),目的为了得出移动信号的传播损耗。当时是基于普通的PC实时运算,非常非常耗时–如北京五环内的传播模型渲染GIS图用了超过20分钟。

 

光照模型来源有2类:

  • 一类是基于学术论文的算法,如Lambert模型、Phong模型.
  • 另一类基于算法的变种–在实际生产实践中修正得到的模型,如HalfLambert模型、BlinnPhong模型.

 

光照模型公式:

surfaceColor = emissive + ambient + diffuse + specular

          物体表面的颜色是自发光(emissive)、环境反射(ambient)、漫反射(diffuse)和镜面反射(specular)等光照作用的总和。   每种光照作用取决于表面材质性质(例如亮度和材质颜色)和光源的性质(例如光的位置和颜色)。

一般而言,光照模型只考虑漫反射镜面反射

 

光照模型分类

当光照射到物体表面时,一部分被物体表面吸收,另一部分被反射,对于透明物体而言,还有一部分光穿过透明体,产生透射光。被物体吸收的光能转化为热量,只有反射光和透射光能够进入眼睛,产生视觉效果(物体呈现的亮度和颜色)。   所以,物体表面光照颜色由入射光、物体材质,以及材质和光的交互规律共同决定。

另外,光与物体最基本的交互方式就是反射,遵循反射定律:反射光与入射光位于表面法向两侧,对理想反射面(如镜面),入射角等于反射角,观察者只能在表面法向的反射方向一侧才能看到反射光

 

image

 

Unity内置光照模型

在Unity表面着色器(Surface Shader) ,Unity内置了2个光照模型,对于大部分场景选择使用即可。

源码路径:C:\Program Files\Unity\Editor\Data\CGIncludes\Lighting.cginc

Lambert 漫反射

fixed4 LightingLambert (SurfaceOutput s, UnityGI gi)

     粗糙的物体表面向各个方向等强度地反射光,这种等同地向各个方向散射的现象称为光的漫反射(diffuse reflection)。   产生光的漫反射现象的物体表面称为理想漫反射体,也称为朗伯(Lambert)反射体。Lambert 模型较好地表现了粗糙表面上的光照现象,如石灰粉刷的墙壁、纸张、黑板等。

 

BlinnPhong 镜面反射 (Jim Blinn 1977)

它是以Phong模型为基础的,效果是能让高光更加柔和,更平滑;但是真实感还没Phong模型强,主要是这个模型运算速度要快,即运算效率高。

fixed4 LightingBlinnPhong (SurfaceOutput s, half3 viewDir, UnityGI gi)

一个光滑物体被光照射时, 可以在某个方向上看到很强的反射光,这是因为在接近镜面反射角的一个区域
内,反射了入射光的全部或绝大部分光强,该现象称为镜面反射。诸如金属材质的反射光泽。  镜面反射认为光强与反射光线和视线的夹角相关。

其中在OpenGL 和Direct3D 渲染管线中,Blinn-Phong 就是默认的渲染模型。

 

一些光照模型概念:

  • Fresnel菲涅尔反射:在观察水面的时候,垂直看下去,清澈见底,看远处的水面,向镜子一样,这个就是菲涅尔效应。菲涅尔效应可以说是无处不在,不同的材质效果不同而已。
  • 镜面反射的颜色通常是材料的颜色而不是光源的颜色。
  • 塑料使用白色的镜面高光,漫反射成分大而镜面反射成分小。
  • 金属的反射一般发生在表面,漫反射分量很小,有时甚至可以忽略,粗糙度的值m也很小。
  • Cook-Torrance 模型: 用模型模拟了金属和塑料材质,考虑到了入射角变化时发生的颜色偏移。
  • Bank BRDF光照模型:BRDF就是双向反射分布函数的意思,它描述了入射光线在某个反射角度的反射光的相对能量。所以给定不同的BRDF函数,就能实现不同的光照效果,如各向异性光照效果–金属表面拉丝等效果。

参考文档:

Unity3D for VR 学习(7): 360°全景照片

    在VR应用中,有一个相对简单的虚拟现实体验,那就是360°全景照片浏览器, 他可以使得手机拍照的”全景”照片,  得以”恢复”当时拍照的场景全貌,  这个创意的确比单纯的2d图片更有震撼力一些,故本文就制作360全景照片的过程进行简单小结。

image

 

Step 1:预期需求

可以通过手机的陀螺仪,在魔镜中查看360°图片;不用依赖任何蓝牙输入,仅通过Gaze Input进行选择下一张360°图片(盯着缩放图2s,进度条旋转完成后,就切换图片;用Gear VR的磁铁触发功能也可以实现选择下一张图片)。

 

Step 2: 准备材料

硬件:暴风魔镜4  + 小米Note顶配版(2K屏幕)

SDK:魔镜手柄、反畸变SDK_Unity版,或者 Google cardboard-unity,本文使用的是Googe CardBoard

 

Step 3: 创建材质球

360°照片,展开看就是一个投影的2D照片,这个在初中学习世界地理的时候将类似投影球形地图到2维平面上,原理类似,只不过一个360°照片的投影失真会小很多. 

为了复原,需要建立一个3D Object\Sphere, 我们通过把图片贴到这个球体上,从内侧看效果。 然后拖放照片到Sphere上,球体放大10倍; 这个时候,发现一个问题在Game视图中看不到东西了,因为Camera没有在球心位置,修改Camera坐标为(0,0,0)位于球心。

我们依然看不到图片,因为Spere默认用的是Unlit/Transparent Shade,他为了渲染高效,把背面给剔除了,而在这里,我们洽洽需要渲染背面,故得从新写个shade–关闭cull off。

image

DoubleSided.Shader文件

Shader "Unlit/DoubleSided"
{
    Properties
    {
        _Color("Main Color", Color) = (1,1,1,1)
        _MainTex("Texture", 2D) = "white" {}
    }
        SubShader
    {
        //Ambient pass
        Pass
        {
            Name "BASE"
            Tags {"LightMode" = "Always" /* Upgrade NOTE: changed from PixelOrNone to Always */}
            Color[_PPLAmbient]
            SetTexture[_BumpMap]
            {
                constantColor(.5,.5,.5)
                combine constant lerp(texture) previous
            }
        SetTexture[_MainTex]
    {
        constantColor[_Color]
        Combine texture * previous DOUBLE, texture *constant
    }

        }

        //Vertex lights
        Pass{
        Name "BASE"
        Tags {"LightMode" = "Vertex"}
        Material
    {
        Diffuse[_Color]
        Emission[_PPLAmbient]
        Shininess[_Shininess]
        Specular[_SpecColor]
    }

        SeparateSpecular On
        Lighting On
        cull off
        SetTexture[_BumpMap]
        {
            constantColor(.5,.5,.5)
            combine constant lerp(texture) previous
        }
        SetTexture[_MainTex]
        {
            Combine texture *previous DOUBLE, texture *primary
        }
    }

    }

        FallBack "Diffuse", 1
}

 

替换了新的Shade后,效果好了很多了,唯一有问题的是我们看到的照片是反的,故修改Spere的.Z为-10.

image

 

通过在Unity.Editor上Play效果,已经很不错了,至此完成了大部分的工作,下面开始”移植”到VR设备上

 

Step 4: 添加VR Camera

先禁用掉默认的MainCamera、light。

然后添加VR摄像机—导入Google的CardboardSDKForUnity.unitypackage后,拖入CardboardMain.prefab到场景中。 这时候点击Play启动UnityEditor,即可看到双VR Camera的效果,点击调试快捷键:Alt + 移动鼠标,即可看到模拟的陀螺仪效果。

这个时候打包为apk,安装到手机,用真机的陀螺仪体验,效果更酷。

 

Step 5: 添加Gaze-and-Tap 用户界面

完成《Step 4: 添加VR Camera》后,实际上已经完成了360°全景照片功能,但是这个仅仅是一个demo,有一个致命的痛点:只有1张照片,如果我有4张照片,每次独立打包为一个apk,这显然不合理。 故需要做一些VR交互。

这里,我们添加4个Plane,通过上面章节的《Unity3D for VR 学习(5): VR Gaze Input》,期望可以实现通过Gaze一个Plane 3s,然后能够切换新的照片功能。

添加Plane,坐标修改如下:

image

添加一个脚本,实现响应EventSystem,可通过2种办法

方法1: 添加Event Trigger脚本,响应PointerEnter、PointerExit等方法,如图

image

方法2:脚本直接继承IPointerDownHandler、IPointerExitHandler等接口,这个看起来更符合程序员胃口

 

我们通过控制Plan的Color.a来实现高亮选择,代码如下

public void SetGazeAt(bool gazeAt)
    {
        Debug.Log("SetGazeAt: " + gazeAt);
        Renderer render = this.GetComponent<Renderer>();
        Color cor = render.material.color;
        cor.a = gazeAt ? 1f : 0.5f;
        render.material.color = cor;
    }

 

另外,当Gaze 2s后,会动态替换material的Texture来实现替换360°照片,代码如下

public void OnClick()
{
    Renderer renderSrc = this.GetComponent<Renderer>();
    Renderer renderDst = pano.GetComponent<Renderer>();
    Texture tex = renderSrc.materials[0].GetTexture("_MainTex");
    renderDst.materials[0].SetTexture("_MainTex", tex);
}

 

备注:

360°全景照片,非常大,有好几M,这个对手机app来说会造成文件太大,实际商用中,需要采用AB(AssetBundle)实现动态从网络侧更新360图片,那样会更酷一些(轻量级)。

 

本文用到的完整的 demo Git地址: Git.OSChina.net

 

昨天网上一个朋友问了一个VR问题:

可否像3D Max那样,动态替换材质,如替换房间地板材质,实现全景照片替换?

回答:不行,只能动态替换整个的全景照片;我昨晚细细思索,好像还是不行,除非建立3D模型,采用动态换装才能实现动态换360°照片中的大树、地板吧。

Unity3D项目实战笔记(5):延时功能的几种实现

我所做过的系统,分单机版系统(2005年)、CS系统(2010年)、实时系统(2015年),各个系统均有“延时”功能:定时调度的; 本博客说的是实时系统中的延时功能(基于Unity3D游戏引擎)。

image

 

在Unity3D中,新建的脚本会默认继承MonoBehaviour,其中Update函数会被引擎自动调度,如在我的电脑上,Update函数被调用的周期为0.012s。

那么Unity3D中,仅有通过Update函数来实现延时功能吗?  还有无其他的实现呢?

怎么才能让一个界面只显示1秒之后 然后再执行其他的操作~

比如 游戏的胜利界面 只让他显示一秒 然后执行其他操作

 

答案是有的,下面就用过的几种延时功能(定时器)一一列出来:

延时功能

是否继承MonoBehaviour

备注

Update函数

配合使用的函数:

Timer.timer

Invoke

配合使用的函数:

CancelInvoke

InvokeRepeating

IsInvoking

Coroutine

配合使用的函数:

StartCoroutine

StopAllCoroutines

StopCoroutine

DOTween (HOTween v2)

Assetstore 商业授权

VisionTimer.VP_Timer

Assetstore 商业授权

 

下面的几个例子,我们在ShowA函数中,延时5s调用ShowB函数,通过代码看看各个实现方法的异同。

为了方便,我仅截取部分关键代码,是否继承MonoBehaviour等自行添加即可。

 

  • Update函数 实现定时器

    float m_timer = 0;
        void Update ()
        {
            m_timer += Time.time;
            if (m_timer >= 5)
            {
                ShowB();

                m_timer = 0;
            }

        }
       
        private void ShowB()
        {

        }

    Update函数实现定时器,几乎是学习Unity3D必修的功课。 但是,在实战项目中需要维护m_timer这个变量,且从设计角度看,代码写得有些不整齐。

 

  • Invoke函数 实现定时器

    GameController.Get().CancelInvoke();

    GameController.Get().Invoke("ShowB", 5f);

    private void ShowB()

    {

    game.ShowCardInTurn();

    }

    Invoke是MonoBehaviour提供的函数,可以延时调用函数,且可以通过CancelInvoke控制调度器的停止。 但是,Invoke的调用是在运行时生效的,对于ShowB函数,很容易导致在代码审查阶段被误杀—函数删除后,编译不会报错,你可能会误认为这个函数是废弃的函数。

 

  • Coroutine 协成 实现定时器

    private IEnumerator ShowA()
        {
            yield return new WaitForSeconds(5);

            ShowB();
        }
       
        private void ShowB()
        {

        }

    使用协成的WaitForSeconds可以实现定时器,使用起来比较简单。

 

  • DOTween 实现定时器

    DOTween动画插件,是在Unity 4.6时代,为了弥补UGUI无动画脚本的先天不足而云起的商业插件,当然雨松MoMO的《UGUI研究院之界面中使用DoTween(七)》对普及DOTWeen功不可没。

private void ShowA()
    {
        GameObject go;

        go.transform.DOMoveZ(0.1f, 5f)
            .OnComplete(new TweenCallback(ShowB));
    }
   
    private void ShowB()
    {

    }

DOTween的主要作用不是为了做延时调度用的,但是其带有这个功能,且思想非常酷。

 

  • VP_Timer 实现定时器

    vp_Timer.Handle Timer = new vp_Timer.Handle();

    vp_Timer.In(5, new vp_Timer.Callback(() =>

    {

    Timer.Cancel();

    ShowB();

    }), Timer);

    VP_Timer是某天下午,在网上搜索中,无意找到了,其简洁的用法,着实让人眼前一亮。 目前项目中,涉及的地方超过10处,极大的方便了延时功能的实现,非常不错。 也为项目节约了大量的时间。

    谢谢给我普及这个插件的博主啦: 《Unity时钟定时器插件——Vision Timer源码分析之一》。

      上面的几种方法,在实战Unity3D项目中,均有所涉及,我本人用的比较多的是DOTWeen和VP_Timer,这2个不依赖继承MonoBehaviour,相对比较灵活,且其是商业项目,封装还是挺给力的。

      如果大家还有其他实现方法,也欢迎分享,我们共同提高、进步。

      我用过的源码管理工具们(SCM)

      源码管理工具是什么? 这个问题对研发中的兄弟姐妹而语,是天天使用,用来吃饭的东西嘛:

      代码管理、协作开发、代码合并、代码分支、代码标签、代码比较、版本化工具。。。。。。

      故,源码管理工具有很多产品(svn, cvs, hg, git 等),其功能类似,各有特色。

      结合个人所使用过的SCM,我简单小结一下:

        1. 他是一种文件管理系统
        2. 他是研发团队交流的重要契约
        3. 他是队员彼此信任的核心之一
        4. 他是你取得进步的见证者之一
        5. 他是你觉得不孤独的利器之一
        6. 下面就我个人使用的源码管理工具列举一下,有些流水账,各位请继续忍忍:

      • VSS:2005年

      • 我最早使用的一个源码管理工具,VSS全程是Visual SourceSafe,其属于微软的一款产品。但是刚从一名工人自学编程,进入研发团队,还觉得挺难的:团队协作、checkIn、CheckOut等概念,那个时候,还不太理解做这些事情到底是为什么。

        VSS最大的一个特点就是可以和开发环境Visual Studio进行无缝结合,我记得2005年我用的Visual Studio 是2005版本, .Net 1.1框架。 网上找了个图片,记忆中的VSS的界面大概是这个样子的,中规中矩的WindowForm风格:

      image

       

      • TFS:2006年

      • 团队发展到一个新的阶段,人多了起来,需要提 bug,需要提 需求, 需要分配任务,这个时候为了复用已有的VS技能,故升级到了VS完美结合的TFS(Team Foundation Server,这个也是微软出品的)。其功能强大:完整的软件生命周期工具、支持敏捷开发、可配置自定义查询、可定制Daily Builder等功能。

      截图如下,我现在还记得TFS有一个很重要的特性是有lock功能,只能独占编辑。当时公司的SCM在内网搭建,外网无法访问,我们出差去保定,只能手工选择文件为可编辑,修改完毕后,等回公司后,再花1天时间合并、提交代码。

      image

       

      • SVN:2009年

      • SVN(Subversion) ,是一个开源软件,崛起的速度很快,好像是 CVS(Concurrent Version System)的替代和升级版本。SVN起来的一个很重要原因是自由软件开发的协作网如SourceForge.net提供了SVN的访问方式。很大程度上,我对SVN熟悉是从一个乌龟的logo开始的:

      image

       

      SVN截图如下,完美的和Windows文件系统集成,SVN会非常方便进行源码管理:更新、提交很方便;其处理代码冲突也非常方便编辑。

      image

       

      • Git:2014年

      自打离开研发队伍后,业余玩点代码,没有源码托管的可真难受啊。

      又懒得自己搭建源码服务器,开始尝试了微软的TFS Online,但是,网速那个慢,无法忍受。当看到国内Git免费托管盛行,就学习了Git方式(我用的是非命令行的,还是乌龟的tortoisegit)。所幸,Git到处有,国外著名的是Github(任意多个public的代码库,private收费)和bitbucket (免费提供1个private和任意多个public的代码库)。国内的如https://gitcafe.com/, 以及我最近1年在使用的http://git.oschina.net/–速度快、private免费、可团队协作等。

      目测,Git因为是目前最火的、最流行的源码管理工具了吧。

      git这么火,不仅仅是其免费、开源;还源于其血统和传奇:Linux创始人Linux Torvalds 花了短短几天写出来的,据说;自那以后,Linux就在Git下进行源码管理,加之,基于Linux的Android火的厉害。

      image  image

       

      • Perforce:2015年

      • 头次听说Perforce源码管理工具,是看《游戏引擎框架》这本书,听说在游戏行业,用的很多,当时并未走心。第二次听说是li口头告之的, 大名鼎鼎的EA用的就是这个产品,但是还没有反应上来是啥–误以为是performance,用于测软件性能的工具,呵呵。

        回家查询了一下,原来Perforce不是默默无名之辈,其是Unity默认支持的文件管理系统之一,使用免费、开源的P4Connect即可在Unity中提及、获取代码。同时Perforce也提供了VS的插件P4VS:P4VS – Perforce Plugin for Visual Studio

      花了约1.5天,看了一下官方文档和网友整理的博客《[SCM]软件配置管理》;自己下载Perforce工具–20人以下是免费的,动手在Windows 7上搭建了Perforce服务器。

      配置Perforce服务:

      image

      在Project视图使用菜单:

      image

      不过,有时候,偶尔会有这样的错误,比较恼火:

      image

      昨晚处理一个问题:

      Client ‘roger.wang_codepiao-PC_5688’ can only be used from host ‘codepiao-PC’.

      本地建立workspace,不要指定host:

      image

       

      对源码管理工具,没有太多个人的喜好,都是团队的协同工具之一。

      总之,在概念和操作上大同小异,熟练掌握即可。 对研发而言,天天会用到,无他,唯手熟尔。

      如当熟练掌握一种源码管理工具,再要学习新的,1、2天就能上手了。如下图是SVN和Perforce的对比图:

      image

       

       

      同类型的几篇博客链接:

      Unite Beijing 2015大型活动

      摘要:2015年,我做的最疯狂的事情:网友见面会—去北京参加Unite Beijing 2015大会。

      正文:记得,上次在北京参加大型活动还是2008年前–传统电信行业的巅峰时期;那时移动互联网、Android、IOS还是萌芽状态。 七年过去了,IT行业翻天覆地的巨大变化,传统电信行业在慢慢的陨落,与此同时,移动互联网确在快速的崛起。

      我个人做为技术从业者,在经历了三天的《Unite Beijing 2015 》活动后,感触颇深,故筑以作文以记之。

       

      First Day:4月18日 (周六)

      关键词:2015 第三届游戏蛮牛杯、人数近500人

      image

      现在的北京,与4年前不可同日而语:超先进的地铁系统,北京西站不用出站,换乘地铁可达城里任何地方。

      这张图是在地铁4号线拍照的,本来要拍地铁手游广告的,但是广告旁边站了PLMM,我不敢拍,只能拍了我左侧的这张图—“让您的凌云之旅尽享卓越”

       

      image

      记忆中的地铁8号线的青花瓷–依旧美丽。

       

      image

      天气不算好,远处拍一张鸟巢吧。

       

      image

      气势磅礴的《国家会议中心》

       

      imageimage

      Unite大会首日有免费的VR Day和收费的新手训练营

       

      image

      超过200个座位的新手训练营,瞬间就爆满了

      备注:我打听了一下我周围的学员,5人中有4人是自费从外地(陕西、重庆、上海、苏州、成都)赴京参加学习的。

       

      image

      和Unity全球副总合影,倒不是对洋人崇拜(我好歹也是外企嘛。)

      是因为一个洋人,千里迢迢,从美国飞过来,对中国人民的技术盛会这么鼓励,呵呵。

      备注:左侧的黑黑的小伙子,重庆大学大一学生,首次离家,独自来京参加大会。

       

      image

      下午果断去鸟巢东侧,游戏蛮牛的盛会—《2015 第三届 游戏蛮牛杯》,参加社区活动。

       

      image

      游戏蛮牛创始人,社区人称崇慕老爷子。  看起来,一点也不老嘛。

      备注:他是来自黑土地松花江边的东北大汉,平易近人、谈吐豪爽。

       

      image

      在优弧的鼎力帮助下,我带着大包大包的礼品,也坐在VIP座位。

      我左侧是Unity社区有名气的孙广东,和他交流后得知,原来,他不是广东人。

       

      image

      我首次听到关于VR、AR的演讲—Unity亚太技术总监郭振平先生激情演讲

       

      image

      游戏蛮牛宣布,2015.4正式启动VR的生态社区建设:http://www.heirenlei.com/

       

      image

      这头牛,很合蛮牛社区的团队士气。

      备注:游戏蛮牛社区的小聚:社区工作人员为了筹备本次大会,辛苦了近1个月,是得好好放松放松。 我有幸见证了这个小小的历史,也看到了社区活跃的身影–韩国泡菜、跳跳、野猪、随风、小阿哥、优弧、版主郭磊等。 抱歉蛮牛妹子太美了,名字给忘了。

      其中,野猪在社区人称猪哥,用自己精通的兵法阐述了千年前的《田忌赛马》战例:他先用小碗喝,等大家都晕天黑地的,再奋力大腕满酒的满场敬酒….。

      不亏齐国人也。

      “俺是鲁国的”猪哥怒吼一嗓子。他的这句经典台词,多亏随风给翻译为普通话,才使得满场乐哈哈 (猪哥满口河南话,实际老家是山东的)。

       

      Second Day:4月19日 (周日)

      关键词:Unity KeyNote、人数5000人+

      image

      来自成都的LGY,他是Unity之Taikr社区的出色的优秀学生

      他有很励志的故事:没有什么高学历,年仅19岁,自费过来学习。

      和他交流很受鼓舞:Stay hungry,Stay foolish。

       

      image

      我作为微软阵营的GCDN版主,自然很关注微软动态。 本次微软对外仅一个主题:Windows 10.

       

      image

      Windows 10的3个One。

       

      image

      主办方Unity的展台,本次是Unity 5在中国首秀。

      Unity 5一个重要的特色是个人版完全免费了。

       

      image

      Keynote入口处,人头攒动。

       

      image

      Unity 大中华区boss 符国新(Allan)做主题分享,其中重点提到Developer—10年前微软的鲍尔默也曾提过。

       

      image

      今年恰逢Unity公司创始10周年,出现在大屏幕上的是三位创始人的照片。

       

      image

      keynote结尾处,allan表示感谢:2012~2015,Unity业务在国内增长10倍,大中华区也面临很多挑战,特别感谢参会和关注Unity的大家。

       

      imageimage

      非常高兴的和Unity创始人David Helgason 合影留念

      备注:头次参加签名售书活动–朋友圈里很多朋友问过我签名的真伪。我对老天爷发誓,这个签名真的是David面签的,不是我乱画的啊。

       

      image

      下午的教育专场,我偷跑进去–非教育行业不得入内的。为了和CSDN资深编辑唐小引亲切接触。

      去年的文章《近匠》Wijmo 5 CTO:从Web到移动,我的25年编程生涯,使得本已经奄奄一息的HTML 5产品,扶摇直上——下次看到唐小引的文章,记得点赞吧。

      备注:朋友圈有人问,为啥不拍正面? 你看过赌神电影吧,女神是随便拍的吗?

       

      image

      丰富的技术专场话题—100%由Unity大中华区技术支持提供分享。

       

      imageimage

      技术会场人气火爆—-左侧图是我席地而坐在听课时候拍照的;右侧图是课程休息占了个座位后拍的

       

      image

      一次精彩的大会,后面有整个团队默默无闻的付出,这个速写器,是一个会务组的mm在会场角落,安静的用文字捕捉会场的每一个细节。

       

      image

      游戏开发者之夜,我美美的吃了一顿免费的晚餐。

      boss、大牛在场上精彩分享–第一个session都结束了,我还端着盘子在吃—-美味佳肴也。

       

      Last Day:4月20日 (周一)

      关键词:VR&AR 体验、人数3000左右

      image

      平生第一次看到3D游戏画面,效果惊艳、目不暇接。 我特意上4楼看了2次,美得让你窒息。

       

      image

      体感和AR技术在教育行业的项目,试用了一下,很酷。

       

      image

      高通的AR解决方案–提供SDK,可以拍摄物体分析并3D效果叠加。

       

      image

      制作人,类似产品经理的角色。

       

      image

      Sony的添田先生,非常厉害。全场40分钟,普通话演讲和问答,能流利说中文的老外不是一般的牛。

       

      image

      郭亮,独立制作人,曾经程序,曾经画画,后来做了独立游戏,目前玩的正酣。

       

      image

      游戏行业,有主程分享的场,肯定100%人气爆满。

       

      image

      大型游戏的设计,上百人团队协作,对协同、配合的要求非常高。

       

      image

      Leap Motion && Oculus, so cool.

       

      image

      老朋友–Kinect。

       

      image

      别看LGY乐呵呵的,通过它面前的这个电脑,他可以用眼神玩切水果玩呢–一种追踪眼球的体感技术。

       

      image

      AR的的眼镜,能看到前方物体,实现AR和现实的叠加。

       

      image

      Windows 10,居然能在树莓派上运行。

       

      image

      游戏周边产物—CosPlay,把我吓了一大跳。

       

      image

      Unity官方社区高人气的大牛们,Call of Unity。

      其中我身上黑色的Call of Unity T恤是来自广东的小七mm赠送给我—-谢谢了。

       

      image

      近3天朋友圈刷爆的Unite、Unity关键词。 摘选几个分享出来。

       

      小结:

       

      • Time Changing。记得我上次在鸟巢照相留念是2008年8月21日北京奥运会(飞人刘翔弃跑那天)。
      • 网友见面会的最高法则,记着网名就行,真名非常容易和网名之间混淆。可惜,我连个网名都没有 微笑
      • 手机的拍照功能真的重要-如抢拍、合影留念、远距离拍照PPT做笔记等。
      • 各大企业市场推广,几乎放弃微薄,目前微信服务号和朋友圈是企业几乎唯一的营销方式。
      • IT垂直社区在崛起,老资历的综合类IT社区在打烊,如微软TechEd大会去年最后一次后,今年已经关闭。
      • 社区的灵魂是人情味,温度是外在的表现。再次感谢蛮牛游戏优弧亲自电话给我导航,担心我在北京迷路
      • Unity公司,是近年国际巨头公司罕见的重视大中华区的公司,其创始人和副总们专程从美国飞北京参会。
      • 接地气的中国梦,多年前人才观是名校、高学历、外企;如今更看重个人才华、勤奋、汗水、创业公司
      • 多和正能量的朋友交流,假以时日,你必获益。如种下一颗种子,先勤劳的浇水、锄草、施肥。
      • 年轻真好。稚嫩的身影,18、19岁,千里迢迢的,自费参加技术大会,我已经看到了多名未来的星星们。

       

       

      晚上就要回西安看儿子了。他会伸出胖乎乎的小手给我说–“爸爸,给我买好吃了吗?  多多的,要。”

       

      王文刚于天津钢管公司(大无缝)生活区

      2015年5月21日

      C#程序员整理的Unity 3D笔记(十六):Unity 3D的UI-OnGUI、NGUI、UGUI们

      UI对用户交互而言,非常重要,尤其类似Unity 3D这种重用户交互体验的游戏行业,更甚。

      然刚开始学习,首先了解的是OnGUI–基于代码实现UI。这个我私下和朋友吐槽了不少:

      OnGUI土的掉渣、绘制UI效率低下–Dock、Anchors等等很难调试,在C#下竟然用代码控制UI–真是疯了!

       

      UI需要快速响应需求设计,要立竿见影达到效果:WYSWYD(所见即所得)才是正道嘛!

       

       

      • Unity 3D 原生的OnGUI

      OnGUI is called for rendering and handling GUI events. 即只要继承MonoBehaviour ,则可使用OnGUI函数,如做一些DeBug输出调试,OnGUI还是很方便的。

      image

      • 第三方UI控件套包—NGUI

        NGUI是第三方商业UI套包,目前最新版是

        Latest Version: 3.8.0 (February 9th, 2015) ,售价95美金。自打NGUI问世,就以第三方UI套件之王而傲立于世,对整个Unity 3D的UI生态圈具有举重若轻的作用,其脚本丰富,表现出色,如TDTK就支持NGUI绘制UI。

       

      • Unity 3D 4.6始原生的UGUI (Unity GUI)

      升级到Unity 4.6后,一下子被新的UI系统镇住了—-UGUI不错:UGUI的使用简洁、符合Visual Studio 程序员的风格,布局采用Web从上往下的流式渲染,基于先后的顺序。

      image

       

      image

       

       

      附录1–简述第三方的NGUI和Unity 3D 4.6原生的UGUI列表

      Item

      UGUI

      NGUI

      初次印象

      命名简约

      官方集成

      使用便捷

      玩转脚本

      明间英雄

      强大社区

      按钮和滚动条

      系统原生

      clip_image002

      Canvas
      分三类–

      1. screen-overloap【default】

      2. screen-camera

      3. word position

      UI Root

      默认添加了一个摄像机–必须有

       

      添加一个Button,在UGUI很容易看到效果,但是NGUI下,需要设置一下position(可能是Unity 4.6的bug)

      事件

      EventSystem (TriggerType)

      Set OnClick event

      Add Collider component

      Add Script component

      Set OnClick event

      Dock

      image

      Rect Transform

       

      clip_image005

      widget属性,pivot,depth和size

      Anchors–高级可设置多个参照Transform

      美化

      动画由Animation、Animator结合完成

      依靠贴图、Font、动画实现

      美化

      动画由NGUI自带的TWeen脚本完成

      依靠贴图、Font、动画实现美化

      显示文本

      Text

      Label

      显示图片

      Image

      Sprite

      快捷键

      Ctrl + T工具栏,用于move、rotate、dock等。

      右键菜单和自定义工具栏配合

      总结

      2014年后U3D的新手,直接上手学习UGUI吧。

       

      UGUI的Empty GameObject比较方便

       

      UGUI的组件思想好-Grid Layout、Text Effect

      历史遗留产物,还会火几年.

      2011~2014年是NGUI的黄金时期。

       

      UGUI.drag drop 需要自己写,而NGUI提供了强大的脚本不用写代码即可完成类似事情

       

      附录2:Unity UI设计的原则

       

      为了提高效率,我们要做的就是减少drawCall的调用次数,减少batch的次数。

       

      附录3:小道消息

       

      Unity 4.6 开始支持UGUI,且从Unity 4.6.2开始支持IOS 64位,故猜测2015.2月起是UGUI的一个重要的里程碑—UGUI免费、开源、原生,这3个Tag的属性,没有道理不火。

      NGUI的作者Michael “ArenMook” Lyashenko在2012.11~2013.12左右,去Unity 公司工作了约1年时间,即UGUI是基于NGUI做出来的–所谓“青出于蓝而胜于蓝”。另外,从tasharen官网看,其作者对NGUI的重心也有所转移.

       

      参考博客:

      C#程序员整理的Unity 3D笔记(十五):Unity 3D UI控件至尊–NGUI

      C#程序员整理的Unity 3D笔记(十四):Unity 3D的UGUI小结

      C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想

      如果你接触过《设计模式》、软件架构的编程思想,就会知道优秀的设计“组合优于继承的”【这句话很简短,但开始学习OOP的不太好理解】。

            如果你接触过《设计模式》、软件架构的编程思想,就会知道优秀的设计准则:“组合优于继承的”。

            这句话很简短,但开始学习OOP的时候,真切的是—-不太好理解(以我个人当初学习为例)。

       

      OOP的继承思想

      image

      在设计主角(Player)的时候,为了能够复用A、B、C的功能,我开始把A、B、C按照继承来写,多了一些Virutal\Override\Protected等修饰符,功能没有任何问题,就是有些别扭。如Start、Update方法,只能在A中采用模板方法处理,万一B、C、Player中直接用了Start、Update方法,会导致奇奇怪怪的问题;同时在继承的基类中,无形之间多了一些包袱,对于Player不得不使用A、B、C的函数、变量(非private的)。

      整个关系变为了:

      • Player is a A
      • Player is a B
      • Player is a C

      心理上疙疙瘩瘩的,总觉得有点别扭。

       

      OOP的组合思想

      image

      以前使用组合思想较多的是构建树、树叶模型,例如电信中的网元模型。这种思想,属于Unity 3D的核心思想–组件。在Player、A、B、C中可自由使用Start、Update函数(请不考虑执行顺序,脚本组件的先后顺序外部可调整,但是意义不大),最重要的是,关系理顺了—主角变成更积极、主动。

      • Player have a A
      • Player have a B
      • Player have a C
        在Unity 3D中,可复用的几乎全部为封装为了组件,eg: transform、rigibody、render、camera、***.cs脚本;为了配合方便的使用非内置的组件,可使用gameObject.AddComponent<T>()、gameObject.GetComponent<T>()来添加、获得组件(一般是自定义的脚本)。

       

      这里我举一个实际的例子,在《Unity 3D手机游戏开发》第二版的“太空射击游戏”中,有一个需求,需要给游戏中可复用的GameObject添加自动销毁的功能(通过时间计时器,或者触发器添加),代码很简单,不到100行,要添加的GameObject有5、6个,虽然工作量不大,但总不能每个都拷贝一遍代码吧。

      开始我是按照OOP继承做的,

      image

       

      看了几天,很不爽,后来重构为如下图:

      image

      这样使得自动销毁组件的功能发挥的更加灵活、机动,即不必拘泥于静态的继承思想来实现。

      从这个重构过程中,我学到Unity 3D组件思想的闪闪发光……

      附录:完整的自动销毁组件代码:

      public class AutoDestoryComponent : MonoBehaviour
      {
          #region ICanCache
          public ParticleSystem[] m_pss = null;
          public int m_life = 1; //3条命
          public float m_AutoDeadTime = 3;//3s自动销毁

          private int m_life_Base = 3; //3条命【恢复用】
          private float m_AutoDeadTime_Base = 3;//3s自动销毁【恢复用】【-1:表示不自动销毁,如Enemy】

          void Update()
          {
              //需要自动销毁
              if (m_AutoDeadTime_Base >= 0)
              {
                  m_AutoDeadTime -= Time.deltaTime;

                  if (m_AutoDeadTime <= 0)
                  {
                      InnerDead();
                      return;
                  }
              }

              if (m_life <= 0)
              {
                  InnerDead();
              }
          }

          /// <summary>
          /// 设置自动销毁数据
          /// </summary>
          /// <param name="life_base">默认生命值</param>
          /// <param name="autoDeadTime_base">-1不自动销毁;其他数据代表销毁时间(单位s)</param>
          public void SetBasePara(int life_base = 1, float autoDeadTime_base = -1)
          {
              m_AutoDeadTime = m_AutoDeadTime_Base = autoDeadTime_base;
              m_life = m_life_Base = life_base;
          }

          //是否启用
          public bool IsUse { get; set; }
          //死后位置
          public Vector3 DeathPosition
          {
              get
              {
                  return new Vector3(2000, 2000, 2000);
              }
          }

          //复活
          public void Init(Vector3 position, Quaternion rotation)
          {
              transform.gameObject.SetActive(true);
              transform.position = position;
              transform.rotation = rotation;
              IsUse = true;
              foreach (ParticleSystem item in m_pss)
              {
                  item.Play(true);
              }

              //有些绕
              m_life = m_life_Base;
              m_AutoDeadTime = m_AutoDeadTime_Base;
          }

          private void InnerDead()
          {
              IsUse = false;
              transform.position = DeathPosition;
              foreach (ParticleSystem item in m_pss)
              {
                  item.Stop(true);
              }

              this.gameObject.SetActive(false);
          }
          #endregion
      }

       

       

      包括系统自带的Audio、Transform、Camera、Image、Button等等。GameObject是一个容器,没有Image的GameObject,只要新建一个空的GameObject,添加Image Component极为Image GameObject对象的。

      也即是在Unity3D中,很少用GameObject.ID的概念,而是用GameObject.Tag、GameObject.name来区分不同的GameObject,且Tag、name不唯一。

       

      结论:在Unity3D中,万事万物都是Component。

      C#程序员整理的Unity 3D笔记(十一):unity3d中脚本生命周期(MonoBehaviour lifecycle)

      脚本自带函数执行顺序,看看下图即可明白。唯一需要注意的是,要注意函数字符的大小写—这个是C#程序员容易被坑的地方之一。

       

      clip_image002

      最先执行的方法是Awake,这是生命周期的开始,用于进行激活时的初始化代码,一般可以在这个地方将当前脚本禁用:this.enable=false,如果这样做了,则会直接跳转到OnDisable方法执行一次,然后其它的任何方法,都将不再被执行。

      如果当前脚本处于可用状态,则正常的执行顺序是继续向下执行OnEnable,当然我们可以在另外一个脚本中实现这个脚本组件的启动:this.enable =true;

      再向下执行,会进行一个判断,如果Start方法还没有被执行,则会被执行一次,如果已经被执行了,则不会再被执行。这是个什么意思呢?我们可以在某个脚本中将组件禁用this.enable=false,再启用时会转到OnEnable处执行,这时继续向下走,发现Start执行过了,将不再被执行。比如说:第一次启用时,将怪物的初始位置定在了(0,0,0)点,然后怪物可能会发生了位置的变换,后来被禁用了,再次启用时,不会让怪物又回到初始的(0,0,0)位置。

      继续向后执行,就是FixedUpdate了,然后是Update,再然后是LateUpdate,如果后面写了Reset,则会又回到Update,在这4个事件间可以进行循环流动。

      再向后执行,就进入了渲染模块(Rendering),非常重要的一个方法就是OnGUI,用于绘制图形界面。当然,如果你使用了NGUI,这个生命周期的事情你就不用考虑了。

      再向后,就是卸载模块(TearDown),这里主要有两个方法OnDisableOnDestroy。当被禁用(enable=false)时,会执行OnDisable方法,但是这个时候,脚本并不会被销毁,在这个状态下,可以重新回到OnEnable状态(enable=true)。当手动销毁或附属的游戏对象被销毁时,OnDestroy才会被执行,当前脚本的生命周期结束。

      脚本自带函数执行顺序如下:将下面脚本挂在任意物体运行即可得到

      Awake ->OnEable-> Start -> -> FixedUpdate-> Update  -> LateUpdate ->OnGUI ->Reset -> OnDisable ->OnDestroy

      • 1.Awake:用于在游戏开始之前初始化变量或游戏状态。在脚本整个生命周期内它仅被调用一次.Awake在所有对象被初始化之后调用,所以你可以安全的与其他对象对话或用诸如GameObject.FindWithTag()这样的函数搜索它们。每个游戏物体上的Awake以随机的顺序被调用。因此,你应该用Awake来设置脚本间的引用,并用Start来传递信息Awake总是在Start之前被调用。它不能用来执行协同程序。
      • 2.Start:仅在Update函数第一次被调用前调用。Start在behaviour的生命周期中只被调用一次。它和Awake的不同是Start只在脚本实例被启用时调用。你可以按需调整延迟初始化代码。Awake总是在Start之前执行。这允许你协调初始化顺序。在所有脚本实例中,Start函数总是在Awake函数之后调用。
      • 3.FixedUpdate:固定帧更新,在Unity导航菜单栏中,点击“Edit”–>“Project Setting”–>“Time”菜单项后,右侧的Inspector视图将弹出时间管理器,其中“Fixed Timestep”选项用于设置FixedUpdate()的更新频率,更新频率默认为0.02s。
      • 4.Update:正常帧更新,用于更新逻辑。每一帧都执行,处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同)FixedUpdate,每固定帧绘制时执行一次,和update不同的是FixedUpdate是渲染帧执行,如果你的渲染效率低下的时候FixedUpdate调用次数就会跟着下降。FixedUpdate比较适用于物理引擎的计算,因为是跟每帧渲染有关。Update就比较适合做控制。
      • 5.LateUpdate:在所有Update函数调用后被调用,和fixedupdate一样都是每一帧都被调用执行,这可用于调整脚本执行顺序。例如:当物体在Update里移动时,跟随物体的相机可以在LateUpdate里实现。LateUpdate,在每帧Update执行完毕调用,他是在所有update结束后才调用,比较适合用于命令脚本的执行。官网上例子是摄像机的跟随,都是在所有update操作完才跟进摄像机,不然就有可能出现摄像机已经推进了,但是视角里还未有角色的空帧出现。
      • 6.OnGUI:在渲染和处理GUI事件时调用。比如:你画一个button或label时常常用到它。这意味着OnGUI也是每帧执行一次。
      • 7.Reset:在用户点击检视面板的Reset按钮或者首次添加该组件时被调用。此函数只在编辑模式下被调用。Reset最常用于在检视面板中给定一个默认值。
      • 8.OnDisable:当物体被销毁时 OnDisable将被调用,并且可用于任意清理代码。脚本被卸载时,OnDisable将被调用,OnEnable在脚本被载入后调用。注意: OnDisable不能用于协同程序。
      • 9.OnDestroy:当MonoBehaviour将被销毁时,这个函数被调用。OnDestroy只会在预先已经被激活的游戏物体上被调用。注意:OnDestroy也不能用于协同程序。

      C#程序员整理的Unity 3D笔记(十):Unity3D的位移、旋转的3D数学模型

      遇到一个想做的功能,但是实现不了,核心原因是因为对U3D的3D数学概念没有灵活吃透。故再次系统学习之—第三次学习3D数学.

       

      本次,希望实现的功能很简单:

      image

      如在小地图中,希望可以动态画出Player当前的位置、z的朝向:用3条线、z轴正向、30°旋转、-30°旋转。

      问题是:0点可以获得,P1点? P2点是未知的。

      我尝试了2个小时,结果不竟如人意,少于沮丧。

      image

       

      不得不,再次花点时间系统的学习3D数学:

      1 位移–向量和点:

      •    点: 点和向量在数学上是一致的,实际生活中点的概念比较好理解,坐标点来定位–南二环、北二环。   【点用(3,4,5)圆括号来标示,简称P】
      •    向量:“俗称增量”,有大小和方向,如”往前1步走。 左转90度”. 往前走,直到碰到墙,你才会停下来—在这之前,你无法准确获得碰到墙的点的坐标或者你和墙的距离                                              【向量用<3,4,5>尖括号来标示,简称V】
      • 在U3D中,统一用Vector3对象来表达向量和点,这个也是导致新手晕头转向的一个很重要的原因; 一个技巧,凡是在API中用position、Point的,V3肯定代表是点;凡是Vector、direction的是向量;多看官方的API手册,写得很明白。

      做个游戏,列表出你用过的Vector3的API,分析分析用到的Vector3是向量(V)还是点(P)

      需求

      API

      向量(V)

      (P)

      备注

      平滑位移

      Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta);

      P

       

      平滑位移

      Vector3 Slerp(Vector3 from, Vector3 to, float t)

      P

       

      新的坐标点

      this.m_transform.position = pos;

      P

      符合常规思维

      变动一次坐标

      m_transform.Translate(new Vector3(rx, 0, -m_Speed * Time.deltaTime));

      V

      可认为是增量

      求方向

      Vector3 relativePos = this.m_transform.position – m_Player.position;

      V

      向量减法,较难理解

      设置新坐标点

      lineRenderer.SetPosition(0,this.gameObject.transform.position);

      m_NavAgent.SetDestination(this.m_Player.transform.position);

      P

      符合常规思维

      新的位置

      pointer.transform.position = hitInfo.point + (transform.position – hitInfo.point) * 0.01f;

      P、V

      力的叠加?

      求距离

      float dis = Vector3.Distance(v1, v2);

      float f1 = (v1 – v2).sqrMagnitude;

      float f3 = (v1 – v2).magnitude;

      P、V

      Distance用点即可

      向量减法也可以

      缩放正向

      Vector3 v3 = this.m_transform.forward * 200f;

      V

      V的数乘

      射线检测

      Ray r = new Ray(source, dest);

      Physics.Raycast(r, out hit, 1000, m_ShootMask)

      V、P

      Source:P

      Dest:V

      加一个力

      rigidbody.AddForce (0, 10, 0);

      V

       

       

      依据这个游戏,可以整理出目前用到的有4个组件(含Vector 3)会发生位移:

      位移常用的4个组件和Vector3

      组件

      函数

      Unity 圣典的API说明

      是否

      用过

      transform组件

      translate函数

      向某方向移动物体多少距离【默认local坐标系】

      或者相对某物体移动

      yes

       

      Position属性

      在世界空间坐标transform的位置

      Yes

      RigidBody组件

      [FixedUpdate函数]

      Velocity属性

      刚体的速度向量

      Unity 官方demo Done用的很酷

      Yes

       

      AddForce函数

      添加一个力到刚体。作为结果刚体将开始移动。

      yes

       

      MovePosition函数

      移动刚体到position

       

      NavMeshAgent组件

      SetDestination函数

      设置自动Path目标点

      yes

      CharacterController

      组件

      Move函数

      一个更加复杂的运动函数,每次都绝对运动

      yes

       

      SimpleMove函数

      以一定的速度移动角色

       

      Vector3向量

      Lerp函数

      两个向量之间的线性插值。

      “像弹簧一个跟随目标物体”

       
       

      Slerp函数

      球形插值在两个向量之间

      “在日出和日落之间动画弧线”

       
       

      MoveToward函数

      当前的地点移向目标

      和Vector3.Lerp相同,maxDistanceDelta限速

       
       

      SmoothDamp 函数

      随着时间的推移,逐渐改变一个向量朝向预期的目标。

       

       

      我的几个向量相关的问题:

      • 如何判断A向量和B向量是否同方向?
      • 如何判断A向量和B向量前、后、左、右?
      • 如何判断A向量和B向量的夹角?
      • 向量的减法貌似比加法更有用一些?
      • Vector.Forward和this.transform.Forward都表达local坐标系,那么数值为什么不一样呢?

       

      2 旋转–Quaternion、eulerAngles、Quaternion.Euler

        

      旋转在3D中是比较复杂的,在Unity 3D中一般用Quaternion来进行旋转, 旋转仅涉及向量的概念(向量的方向),请思考对于坐标点或者零向量旋转有无意义?

      而按照Unity 3D API官方的说法,仅有约7个方法或者操作符比较常用,且占99%的概率,我截止目前还没有用到这么多,我用到的Quaterniong约有4个函数。

      旋转常用7个API:

      Quaternion API

      Unity 圣典的API说明

      是否

      用过

      Quaternion.LookRotation

      创建一个旋转,沿着forward(z轴)并且头部沿着upwards(y轴)的约束注视。也就是建立一个旋转,使z轴朝向y轴朝向up。 常用的是transform.LookAt

      yes

      Quaternion.Angle

      返回a和b两者之间的角度。

       

      Quaternion.Euler

      返回一个旋转角度,绕z轴旋转z度,绕x轴旋转x度,绕y轴旋转y度(像这样的顺序)。

      yes

      Quaternion.Slerp

      球形插值,通过t值from向to之间插值。

       

      Quaternion.FromToRotation

      从fromDirection到toDirection创建一个旋转。

       

      Quaternion.identity

      返回恒等式旋转(只读)。这个四元数对于“无旋转”:这个物体完全对齐于世界或父轴。

      yes

      Quaternion.operator *

      由另一个四元数来旋转一个旋转角度,或由一个旋转角度来旋转一个向量

      yes

       

      我的几个旋转相关的问题:

      1 Quaternion.LookRotation和Vector3.RotateTowards的区别?

      2 Quaternion.Angle和Vector3.Angle的区别?

      3 Quaternion.LookRotation和transform.LookAt的区别?

      [官方回答:   大多数时间你可以使用transform.LookAt代替

                        Quaternion.LookRotation]

      4 如何实现2个GameObject face to face,即Z轴相对?

       

       

       

      磨刀不误砍柴工: 经过一周的复习、反复验证,果然在系统学习3D 数学后,要实现的功能可以了,如下:

      image

       

      参考博客:

      坐标系的简介:C#程序员整理的Unity 3D笔记(八):Unity 3D坐标系介绍

      宣雨松的博客:http://www.xuanyusong.com/archives/1977

      总结:

      据说80%、90%Unity 3D程序员是自学的,大多数是看看书、实战视频、源码分析;而科班出生的同学会有3D数学这门核心课–估计占一个学期、会有作业等。为了赶上科班同学的水平,花点时间,补补数学知识,会使得自己少走一些弯路。一句话:”3D数学模型很关键。“