unity_unity3d - CSDN
unity 订阅
Unity是游戏引擎开发商 [1-2]  ,实时3D互动内容创作和运营平台 [3]  。 [2]  包括游戏开发、美术、建筑、汽车设计、影视制作在内的创作者运用Unity实现。 [2]  Unity提供一整套软件解决方案,可用于创作、运营和变现实时互动的2D和3D内容 [2]  ,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 [2]  2019年使用Unity制作的游戏和体验已在全球范围内覆盖将近30亿台设备 [4]  ,月均下载量超过30亿次 [5]  。并且其在2019年的安装量已超过370亿次。 [4]  全平台(包括PC/主机/移动设备)游戏中有一半都是基于Unity创作的。 [5]  Unity提供易用实时平台,开发者可以在平台上构建各种AR和VR互动体验 [5]  ,全球超过60%的AR和VR内容都用Unity制作。 [5]  2020年5月9日,Unity宣布收购加拿大技术服务公司Finger Food,拓展工业应用版图。 [6] 展开全文
Unity是游戏引擎开发商 [1-2]  ,实时3D互动内容创作和运营平台 [3]  。 [2]  包括游戏开发、美术、建筑、汽车设计、影视制作在内的创作者运用Unity实现。 [2]  Unity提供一整套软件解决方案,可用于创作、运营和变现实时互动的2D和3D内容 [2]  ,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 [2]  2019年使用Unity制作的游戏和体验已在全球范围内覆盖将近30亿台设备 [4]  ,月均下载量超过30亿次 [5]  。并且其在2019年的安装量已超过370亿次。 [4]  全平台(包括PC/主机/移动设备)游戏中有一半都是基于Unity创作的。 [5]  Unity提供易用实时平台,开发者可以在平台上构建各种AR和VR互动体验 [5]  ,全球超过60%的AR和VR内容都用Unity制作。 [5]  2020年5月9日,Unity宣布收购加拿大技术服务公司Finger Food,拓展工业应用版图。 [6]
信息
开发公司
Unity Technologies
类    别
创作引擎、开发工具 [2]
员工数
约3500名 [2]
CEO
John Riccitiello [7]
别    名
U3D、Unity3D
属    性
软件公司 [2]
成立时间
2004年 [4]
支持维度
2D、3D、VR、AR、MR [2]
外文名
Unity
编程语言
C# [2]
Unity基本介绍
Unity3D(7张) Unity [8]  引擎使开发者能够为超过20个平台创作和优化内容 [5]  ,包括iOS、安卓、Windows [2]  、Mac OS、索尼PS4、任天堂Switch [2]  、微软Xbox One、谷歌Stadia、微软Hololens、谷歌AR Core、苹果AR Kit、商汤SenseAR等等 [2]  。公司超过1400人规模的研发团队让Unity的技术跟随合作伙伴迭代 [5]  ,确保在最新的版本和平台上提供优化支持服务。 [5]  Unity还提供运营服务来帮助创作者 [2]  ,包括:Unity Ads广告服务、Unity游戏云一站式联网游戏服务、Vivox游戏语音服务、Multiplay海外服务器托管服务 [2]  、Unity内容分发平台(UDP)、Unity Asset Store资源商店 [2]  、Unity云构建等。 [2]  Unity在中国、比利时、芬兰、加拿大、法国、新加坡、德国等16个国家拥有44个办公室 [5]  ,创作者分布在全球190个国家和地区。 [5] 
收起全文
精华内容
参与话题
  • Unity入门:第一个游戏

    万次阅读 多人点赞 2018-02-02 22:12:12
    Unity官网提供了详尽的文档和丰富的教学视频,昨天跟着视频做了一个简单的3d游戏“roll-a-ball”。游戏涉及了许多Unity的基本知识,用来入门很不错。 这篇博文并不讲述整个游戏的制作流程,如果您感兴趣,可以访问...

    Unity官网提供了详尽的文档和丰富的教学视频,昨天跟着视频做了一个简单的3d游戏“roll-a-ball”。游戏涉及了许多Unity的基本知识,用来入门很不错。

    这篇博文并不讲述整个游戏的制作流程,如果您感兴趣,可以访问这里,如果访问遇到什么困难,在B站有一摸一样的视频

    这是完成以后的样子:


    运行效果:


    作为个人小结,下面写一些做这个游戏的收获:

    1、什么是Unity?

    一款游戏引擎,至于什么是游戏引擎,这里不展开。

    2、下载和安装

    官网:Unity官网

    作为学习用途,下载personal版即可。

    3、熟悉Unity界面

    进入Unity后,将会看到这样的界面:


    上图将界面划分成了5部分,下面分别解释每部分的功能:

    (1)Toolbar

    上面的按钮有不同的功能,比如左侧的第一个按钮可以用来移动场景中的物体,第二个按钮用来进行平移变换,第三个按钮用来进行旋转变换等。

    (2)Hierarchy window

    顾名思义,这个部分显示的是“层次结构”,场景中的对象都会被列到这个窗口中。当我们新建一个Unity项目时,Unity就会自动为我们添加两个东西:Main Camera和Directional Light,一个是相机,一个是光照。Hierarchy window上面有一个create按钮,点击这个按钮,我们可以看到一个包含了空对象、2d,3d对象、UI、光照、相机等在内的菜单,在这里你可以点击你想创建的东西。

    (3)Scene view

    这是游戏的场景,我们可以通过调整右上角的坐标系图案来调整观察场景的位置。

    (4)Inspector window

    当我们选中一个对象,打开Inspector window,这个对象的信息,例如所在的位置,平移了多少等等都会在这个窗口显示,当然也可以用这个窗口来调整场景中的对象,例如为了编辑方便,一开始我们会使用transform中的reset,将对象放置在坐标原点(0,0,0)。Inspector window最下面有一个Add Component按钮,通过这个按钮可以给对象增加其它的component,例如添加一条C#脚本等。

    (5)Project window

    这个窗口显示的是这个游戏使用的资源,通常我们会在这里建立一些文件夹,例如Scenes文件夹专门保存场景,Materials文件夹专门保存材质,Scripts文件夹专门保存脚本等。Project window上有一个不起眼的create按钮,这个按钮很有用,例如我们可以点击create->folder来新建一个文件夹等等。

    事实上,这只是Unity界面一个最基本的布局,你可以自己拖动这些window或者view来将它们放置在自己喜欢的位置,也就是说,操作界面是可以个性化的。其实上面漏掉了一个很重要的view:game view,如下图所示:


    这个view的按钮就在scene view旁边,上图中我已经将它拖动到了scene view下面,这个视图显示的是我们的游戏最终呈现给用户的样子,制作好一个游戏后,可以点击Toolbar中间那个表示Play的按钮进行试玩,游戏的运行情况就显示在这个视图中。

    为了方便编辑,我们常把Scene view和Game view并列在一起,就像上图一样,这样,在用Play试玩调试的时候可以不用频繁切换视图,从而节省了时间。

    4、怎么理解游戏中的几个脚本?

    Unity会自动为每个新建的C#脚本生成void Start()和void Update()两个方法,第一个在第一帧,也就是游戏刚开始时调用,第二个在画面更新时调用(准确地说是在渲染每一帧之前被调用)。

    在这个游戏中我们会用到三个脚本:

    (1)CameraController.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CameraController : MonoBehaviour {
    	public GameObject player;
    	private Vector3 offset;
    
    	void Start () {
    		offset = transform.position - player.transform.position;
    	}
    	
    	void LateUpdate () {
    		transform.position = player.transform.position + offset;
    	}
    }
    脚本的作用是当Player移动时,让相机也随着移动。

    这里有一个问题:要达到类似的效果,为什么不直接把Main Camera设置成Player的孩子?

    (2)PlayerController.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class PlayerController : MonoBehaviour {
    	public float speed;
    	public Text countText;
    	public Text winText;
    
    	private Rigidbody rb;
    	private int count;
    
    
    	void Start()
    	{
    		rb = GetComponent<Rigidbody>();
    		count = 0;
    		SetCountText();
    		winText.text = "";
    	}
    
    	void FixedUpdate()
    	{
    		float moveHorizontal = Input.GetAxis("Horizontal");
    		float moveVertical = Input.GetAxis("Vertical");
    		Vector3 movement=new Vector3(moveHorizontal,0.0f,moveVertical);
    		rb.AddForce (movement*speed);
    	}
    
    	void OnTriggerEnter(Collider other)
    	{
    		if (other.gameObject.CompareTag ("PickUp")) 
    		{
    			other.gameObject.SetActive (false);
    			count++;
    			SetCountText();
    		}	
    	}
    
    	void SetCountText()
    	{
    		countText.text = "Count:" + count.ToString ();
    		if(count>=12)
    		{
    			winText.text="You Win!";
    		}
    	}
    }

    这个脚本被添加到了叫做Player的小球上,Start函数用来做初始化,其中的getComponent用来获取刚体对象,也就是添加到叫做Player的小球上的那个RigidBody。为什么用FixedUpdate()不用Update()?因为FixedUpdate在做物理计算之前被调用,这个游戏中的碰撞属于physics的范畴,所以用FixedUpdate()。还有一个要注意的函数是OnTriggerEnter(),这个函数在对象碰到collider的时候会被触发,在这个例子中,我们给12个Pickup关联上了一个叫“PickUp”的Tag,当碰撞发生时如果发现Tag是PickUp,就deactivate这个PickUp(每个PickUp的is trigger需要勾选上)。教学视频中提到一个问题:除了要给PickUp的collider勾选is trigger,还要加上rigidbody(is kinematic),这是因为Unity计算所有collider的体积后把它们放在一个cache里,如果collier是静态的(static),这样做可以避免在每帧更新的时候重复计算,但是在我们这个游戏中,因为每次collider都在旋转,所以每次它的体积都会被重复计算,为了节省资源,可以把collider设置成动态的(dynamic=collider+rigidbody)。

    (3)Rotater.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Rotator : MonoBehaviour {
    
    	
    	// Update is called once per frame
    	void Update () {
    		transform.Rotate (new Vector3(15,30,45)*Time.deltaTime);
    	}
    }
    这里要用的是Update而不是FixedUpdate(和物理无关)。

    5、其他

    (1)prefab

    类似模板一样,可以将需要复用某个逻辑的一堆对象放到prefab文件夹中,这就可以对整体进行编辑、修改了。

    (2)快捷键

    例如ctrl+D用来duplicate

    (3)有不懂的查文档!!!

    展开全文
  • 基于Unity的游戏开发(上)

    万人学习 2019-06-24 11:55:37
    本课程是Unity游戏开发的入门课程,课程分为上、下两个部分。上篇主要讲述游戏的基本概念、Unity的开发环境、游戏资源的创建和使用等基础内容。
  • 深入浅出Unity3D——第一篇

    万人学习 2019-07-01 10:35:43
    Unity3D基础知识、游戏算法一网打尽。
  • Unity3D基本入门及功能介绍

    万次阅读 多人点赞 2017-06-10 22:44:17
    本章主要是 Unity3D 的基础快速入门篇,通过本章的学习,能让初学者们快速的掌握和 应用 Unity3D 软件。 本章导读 本章无论对于 Unity3D 初学者、或是以前从事建模工作的设计师、又或者是从事过 3D 编程的人群,...

    本章主要是 Unity3D 的基础快速入门篇,通过本章的学习,能让初学者们快速的掌握和
    应用 Unity3D 软件。
    本章导读
    本章无论对于 Unity3D 初学者、或是以前从事建模工作的设计师、又或者是从事过 3D
    编程的人群,在转向 Unity3D 的学习的时候,学习本章内容都极有必要的。通过本章节内容
    的学习,你可以迅速的掌握 Unity3D 的软件结构,各个板块具体的功能和作用以及场景制作
    流程等等。本章节可以说是全书的根基,只要你能把本章节的内容掌握熟悉,那在今后的日
    子里面开发任何的游戏可以说是事半功倍。这就像运动员们在小的时候打好了坚实的基础,
    再向今后的专业突破的时候,就感觉游刃有余,几乎不费吹灰之力就拿下任何一个项目。
    对于有一定 Unity3D 基础的人群而言,笔者也强力建议在有充足时间的情况下,耐心的
    阅读下本章节的内容。因为笔者时常在网上发现一些 Unity3D 早期的开发者,往往对一些 U
    nity3D 很基础性的功能莫不着头脑。这不能怨这些开发者的水品不够,而是有许多 Unity3D
    的功能在长期未被使用的情况下,被他们遗忘了,突然有一天需要使用的时候,就抓了狂,
    发了疯。
    另外笔者要在这里提醒一下建模设计师,可能你们在原先的行业里面已经将 3DS MA
    X、Maya 等建模软件摸索得相当熟练了,但游戏场景和影视场景还是存在很大的差异。首
    先最大的差异就在于灯效的实时性,游戏讲究的是动态灯光,追求与游戏者视觉互动;而影
    视灯光则是一种静态的逐帧灯光,所有效果都被渲染成一张张静态的连续图片,它们主要倾
    向与影迷们的观赏互动;前者比较主动,而后者相对来说比较被动。前者在使用灯效处理的
    时候受硬件的局限性大,面对的客户群体需要有所区分;后者在观赏灯效处理的时候,几乎
    不受任何计算机硬件的影响,面对的客户群体也比较广泛。

    1.1 界面入门


    如图 1-1 所示为 Unity3D 最经典 2 by 3 结构界面,上面呈现了 Unity3D 最为常用的几
    个面板,下面为各个面板的详细说明。
      Scene【场景面板】:该面板为 Unity3D 的编辑面板;你可以将你所有的模型、灯光、
    以及其他材质对象拖放到该场景中。构建游戏中所能呈现景象。
      Game【游戏面板】:与场景面板不同,该面板是用来渲染场景面板中景象的。该面
    板不能用作编辑,但却可以呈现完整的动画效果。
      Hierarchy【层次清单栏】:该面板栏主要功能是显示放在场景面板中所有的物体对
    象。
      Project【项目文件栏】:该面板栏主要功能是显示该项目文件中的所有资源列表。
    除了模型、材质、字体等,还包括该项目的各个场景文件。
      Inspector【监视面板】:该面板栏会呈现出任何对象的所固有的属性,包括三维坐
    标、旋转量、缩放大小、脚本的变量和对象等等。
      【场景调整工具】:可改变你在编辑过程中的场景视角、物体世界坐标和本地坐标
    的更换、物体法线中心的位子,以及物体在场景中的坐标位置,缩放大小等等。
      【播放、暂停、逐帧按钮】:用于运行游戏,暂停游戏和逐帧调试程序。
      【层级显示按钮】:勾选或取消该下拉框中对应层的名字,就能决定该层中所有物
    体是否在场景面板中被显示。
      【版面布局按钮】:调整该下拉框中的选项,即可改变编辑面板的布局。
      【菜单栏】:和其他软件一样,包含了软件几乎所有要用到的工具下拉菜单。
    除了 Unity3D 初始化的这些面板而外,你还可以通过“Add Tab”按钮和菜单栏中的“W
    indow”下拉菜单中,增添其他面板和删减现有面板。特别是“Window”下拉菜单中的“Li
    ghtmapping”和“Occllusion Culling”面板对游戏的后期优化尤为管用。除此而外还有用
    于制作动画文件的 Animation【动画面板】,用于观测性能指数的 profiler【分析器面板】,
    用于购买产品和发布产品的 Asset Store【资源商店】,用于控制项目版本的 Asset Server
    【资源服务器】,用于观测和调试错误的 Console【控制台面板】。
    在【菜单栏】中包含有八个菜单选项:分别是 File【文件】、Edit【编辑】、Assets【资
    源】、GameObject【游戏对象】、Component【组件】、Terrain【地形】、Window【窗口】、He
    lp【帮助】。这些是 Unity3D 中最标准的菜单选项卡,其各自又有自己的子菜单,表 1-1 中
    列出了各个菜单栏以及它们所包含的下拉菜单及其译名,仅供读者参考。

    主菜单  包含的子菜单

    File【文件】

    New Scene【新建场景】
    Open Scene【打开场景】
    Save Scene 【保存场景】
    Save Scene as…【场景另存为…】
    New Project… 【新建工程文件】
    Open Project… 【打开工程文件】
    Save Project 【保存工程文件】
    Build Settings… 【创建设置】(这里可以设置你的游戏将要以
    何种方式发布,发布的场景文件又包含那些)
    Build & Run 【创建并运行】(这里以“Build Settings”里设
    置好的方式,发布并运行游戏)
    Exit 【退出】

    Edit【编辑】

    Undo 【撤销上一步操作】
    Redo 【恢复被撤销的操作】
    Cut 【剪切】
    Copy 【拷贝】
    Paste 【粘贴】
    Duplicate 【复制】
    Delete 【删除】
    Frame Selected 【在编辑场景中最大化显示被选中的物体】
    Select All 【全选编辑面板中的所有物体】
    Preferences… 【首选参数设置】
    Play 【播放】(如果游戏已经开始播放,点此按钮代表停止播
    放)
    Pause 【暂停】
    Step 【逐帧播放游戏】
    Load selection 【载入所选】(与“Save selection”【存储所选】
    联合使用,你可以把它理解为一个临时的快捷键,帮你快速的
    找到特定的以被存储的物体对象。)
    Save selection 【存储所选】(与“Load selection”【载入所选】
    联合使用,你可以把它理解为一个临时的快捷键,帮你快速的
    找到特定的以被存储的物体对象。)
    Project Settings 【工程文件设置】(包含了该工程项目的“Inp
    ut”【热键】、“Tags”【标签管理】、“Audio”【音频设置】、“Ti
    me”【时间设置】、“Player”【播放器设置】、“Physics”【默认仿
    真物理设置】、“Quality”【播放质量参数设置】、“NetWork”【网
    络工作参数设置】、“Editor”【编辑器设置】)“Script Execution
    Order”【脚本编译顺序设置】
    Render settings 【渲染设置】(默认渲染参数设置,包括环境光,
    周围的雾化程度,环境颜色等等一系列参数的设定)
    Network emulation 【网络仿真】(由于你制作的游戏将会在不
    同的网络环境中工作,所以需要这个参数来模拟不同的网络工
    作环境)
    Graphics emulation 【图形卡仿真】(由于你制作的游戏将会在
    不同的图形卡环境中工作,所以将需要这个参数来模拟不同硬
    件条件下的游戏显示质量)
    Snap settings 【捕捉设置】(和 3Ds Max 的“栅格和捕捉设置”
    类似。)

    Assets 【资源】

    Create 【创建】(包含有“Folder”【文件夹】、“JavaScript”【Ja
    vaScript 编程脚本】、“C# Script”【C#编程脚本】、“Boo Script”
    【Boo 编程脚本】、“Shader”【着色语言】、“Prefab”【预置物体】、
    “Material”【材质】、“Animation”【动画】、“Cubemap”【立方
    体贴图】、“Lens Flare”【镜头光晕】、“Custom Font”【自定义
    字体】、“Render Texture”【渲染纹理】、“Physic Material”【物
    理材质】、“GUI Skin”【用户图形界面皮肤】)
    Show in Explor 【显示项目资源所在的文件夹】
    Open【打开选中的资源】
    Delete【删除选定资源】
    Import New Asset... 【导入新的资源】
    Import Package...【导入资源包】
    Export Package... 【导出资源包】
    Select Dependencies 【选择相关联的文件】
    Export compressed audio file... 【导出压缩的音频文件】
    Refresh 【刷新】
    Reimport 【重新导入选中的资源】
    Reimport All 【重新导入所有的资源文件】
    Sync MonoDevelop Project 【与 Mono 项目文件同步】

    GameObject【游戏项目】

    Create Empty【创建空的游戏对象】
    Create Other 【创建其他组件】(包含了“Particle System”【粒
    子系统】、“Camera”【摄像机】、“GUI Text”【图形用户界面文
    本】、“GUI Texture”【图形用户界面图片】、“3D Text”【3D 文
    字】、“Directional Light”【平行光】、“Point Light”【点光源】、
    “Spotlight”【聚光灯】、“Cube”【立方体】、“Sphere”【球】、“C
    apsule”【胶囊】、“Cylinder”【圆筒】、“Plane”【平面】、“cloth”
    【布料】、“Audio Reverb Zone”【声音回响区域】、“Ragdoll..”
    【布娃娃系统】、“Tree”【植被树系统】、“Wind Zone”【风的区
    域】)
    Center On Children 【归位到子物体中心点】
    Make Parent 【创建父集】(必须选择两个以上的物体才能使用
    该命令,最先被选中的物体为父级对象,其余的对象都为该对
    象的子集)
    Clear Parent 【取消父集】(取消被选中物体与它上一个父级之
    间的父子级关系)
    Apply Changes To Prefab 【改变影响预制物体】(如果你在场
    景中编辑的物体是从资源面板拖拽出的预制物体,默认的情况
    下,你在场景面板中对物体做出的改变不会影响原先的预制物
    体,除非你点击该按钮)
    Move To View 【移动物体到“Scene”视窗的中心点】
    Align With View 【移动物体到“Scene”视窗的中心点,并且
    与显示口正对齐,物体中心位于显示口的中心点】
    Align View to Selected 【移动“Scene”视窗与物体对齐,并
    且显示口的中心点位于物体的中心】

    Component【组件】

    Mesh 【网格】(“Mesh Filter”【网格填充】、“Text Mesh”【文
    字网格】、“Mesh Renderer”【网格渲染】、“Combine Children”
    【合并子物体】)
    Particles 【粒子系统】(能打造出非常棒的流体效果,是制作烟
    雾、激光、火焰等效果的首选。“Ellipsoid Particle Emitter”【
    椭球粒子发射器 】,“Mesh Particle Emitter”【面片粒子发射器】,
    “Particle Animator” 【粒子动画】, “World Particle Collider” 【世
    界粒子碰撞机】,“Particle Renderer”【粒子渲染器】,“Trail Re
    nderer”【蔓延渲染】)
    Physics 【物理系统】(可使物体带有对应的物理属性)
    Audio 【音频】(可创建声音源和声音的听者)
    Rendering 【渲染】
    Miscellaneous 【杂项】
    Scripts 【脚本】(Unity 内置的一些功能很强大的脚本)
    Image Effects【图形渲染效果】(仅限专业版)
    Character【角色控制器】
    Camera-Control 【摄像机控制】

    Terrain【地形】 

     Create Terrain 【创建地形】
    Import Heightmap - Raw... 【导入高度图】
    Export Heightmap - Raw... 【导出高度图】
    Set Resolution... 【设置分辨率】
    Create Lightmap... 【创建光影图】
    Mass Place Trees... 【批量种植树】
    Flatten Heightmap... 【展平高度图】
    Refresh Tree and Detail Prototypes 【刷新树及细节模型】

    Window【窗口】

    Next Window 【下个窗口】
    Previous Window 【前一个窗口】
    Layouts 【布局】
    Scene 【场景窗口】
    Game 【游戏窗口】
    Inspector 【监视窗口】(这里主要指各个对象的属性)
    Hierarchy 【层次窗口】
    Project 【项目文件窗口】
    Animation 【动画窗口】(用于创建时间动画的面板)
    Profiler 【性能探测窗口】
    Asset Store 【资源商店】
    Asset Server 【源服务器】
    Lightmapping 【灯影视图窗口】
    Occlusion Culling 【遮挡剔除窗口】
    Console 【控制台】

    Help【帮助】

    About Unity... 【关于 Unity】
    Enter serial number... 【输入序列号】
    Unity Manual 【Unity 手册】
    Reference Manual 【参考手册】
    Scripting Manual 【脚本手册】
    What’s New 【最新功能】
    Unity Forum 【Unity 论坛】
    Unity Answers 【Unity 在线答疑】
    Unity Feedback 【Unity 使用信息反馈】
    Welcome Screen 【欢迎窗口】
    Check for Updates 【查看升级】
    Release Notes 【发行说明】
    Report a bug【软件缺陷反馈】

    展开全文
  • C# For Unity系列之入门篇

    万人学习 2020-07-13 14:36:00
    学习好Unity,其先决条件是一定要有稳固、扎实的编程基础!课程 《C# For Unity系列之入门篇》配套学习资料链接:http://pan.baidu.com/s/1gflxreN 密码:sou5;刘老师讲Unity学员群(2) 497429806 ...
  • unity中实现镜子效果

    千次阅读 2018-02-26 08:16:05
    上一篇介绍了有关镜子的制作,有关理论部分的内容我会在后续相关的文章中陆续介绍,莫急,我先趁着自己脑子还是对此技术比较热,趁热打铁尽早把实现部分先写出来。上一章的介绍制作的镜子其实只是一个取巧的方法,并...

    本文转载自http://blog.csdn.net/zhangxiao13627093203/article/details/52403186

    上一篇介绍了有关镜子的制作,有关理论部分的内容我会在后续相关的文章中陆续介绍,莫急,我先趁着自己脑子还是对此技术比较热,趁热打铁尽早把实现部分先写出来。上一章的介绍制作的镜子其实只是一个取巧的方法,并不能做到实时的反射出实物,但是思路还是比较有意思的。

    
    

    还是废话不多说先上图,我用的Unity版本5.3.3

    二、Unity中制作原理

    1、简单说明:其实这个原理就是用一个摄像机去拍镜子上面的物体将得到的图像投影给Plane,最后主摄像机就能看到Plane上物体的镜像,所以关键的部分就是计算摄像机上的投影矩阵和主摄像机的投影矩阵的关系,因为站在不同的角度看(主摄像机转动或移动)镜像是要跟着偏移的

    2、创建一个Camera作为镜像摄像机,将下面计算摄像机的投影平面的脚本代码拖到这个Camera上

    using UnityEngine;
    using System.Collections;
    [ExecuteInEditMode]
    public class ViewPlane : MonoBehaviour {
        public GameObject mirrorPlane;                      //镜子屏幕
    
        public bool estimateViewFrustum = true;
        public bool setNearClipPlane = false;               //是否设置近剪切平面
    
        public float nearClipDistanceOffset = -0.01f;       //近剪切平面的距离
    
        private Camera mirrorCamera;                        //镜像摄像机
        // Use this for initialization
        void Start () {
            mirrorCamera = GetComponent<Camera>();
    
        }
    
        // Update is called once per frame
        void Update () {
    
            if (null != mirrorPlane && null != mirrorCamera)
            {
                //世界坐标系的左下角
                Vector3 pa = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, -5.0f));
    
                //世界坐标系的右下角
                Vector3 pb = mirrorPlane.transform.TransformPoint(new Vector3(5.0f, 0.0f, -5.0f));
    
                //世界坐标系的左上角
                Vector3 pc = mirrorPlane.transform.TransformPoint(new Vector3(-5.0f, 0.0f, 5.0f));
    
                //镜像观察角度的世界坐标位置
                Vector3 pe = transform.position;
    
                //镜像摄像机的近剪切面的距离
                float n = mirrorCamera.nearClipPlane;
    
                //镜像摄像机的远剪切面的距离
                float f = mirrorCamera.farClipPlane;
    
                //从镜像摄像机到左下角
                Vector3 va = pa - pe;
    
                //从镜像摄像机到右下角
                Vector3 vb = pb - pe;
    
                //从镜像摄像机到左上角
                Vector3 vc = pc - pe;
    
                //屏幕的右侧旋转轴
                Vector3 vr = pb - pa;
    
                //屏幕的上侧旋转轴
                Vector3 vu = pc - pa;
    
                //屏幕的法线
                Vector3 vn;
    
                //到屏幕左边缘的距离
                float l;
    
                //到屏幕右边缘的距离
                float r;
    
                //到屏幕下边缘的距离
                float b;
    
                //到屏幕上边缘的距离
                float t;
    
                //从镜像摄像机到屏幕的距离
                float d;
    
                //如果看向镜子的背面
                if (Vector3.Dot(-Vector3.Cross(va, vc), vb) < 0.0f)
                {
                    //
                    vu = -vu;
                    pa = pc;
                    pb = pa + vr;
                    pc = pa + vu;
                    va = pa - pe;
                    vb = pb - pe;
                    vc = pc - pe;
                }
    
                vr.Normalize();
                vu.Normalize();
    
                //两个向量的叉乘,最后在取负,因为Unity是使用左手坐标系
                vn = -Vector3.Cross(vr, vu);
    
                vn.Normalize();
    
                d = -Vector3.Dot(va, vn);
                if (setNearClipPlane)
                {
                    n = d + nearClipDistanceOffset;
                    mirrorCamera.nearClipPlane = n;
                }
                l = Vector3.Dot(vr, va) * n / d;
                r = Vector3.Dot(vr, vb) * n / d;
                b = Vector3.Dot(vu, va) * n / d;
                t = Vector3.Dot(vu, vc) * n / d;
    
                //投影矩阵
                Matrix4x4 p = new Matrix4x4();
                p[0, 0] = 2.0f * n / (r - l);
                p[0, 1] = 0.0f;
                p[0, 2] = (r + l) / (r - l);
                p[0, 3] = 0.0f;
    
                p[1, 0] = 0.0f;
                p[1, 1] = 2.0f * n / (t - b);
                p[1, 2] = (t + b) / (t - b);
                p[1, 3] = 0.0f;
    
                p[2, 0] = 0.0f;
                p[2, 1] = 0.0f;
                p[2, 2] = (f + n) / (n - f);
                p[2, 3] = 2.0f * f * n / (n - f);
    
                p[3, 0] = 0.0f;
                p[3, 1] = 0.0f;
                p[3, 2] = -1.0f;
                p[3, 3] = 0.0f;
    
                //旋转矩阵
                Matrix4x4 rm = new Matrix4x4();
                rm[0, 0] = vr.x;
                rm[0, 1] = vr.y;
                rm[0, 2] = vr.z;
                rm[0, 3] = 0.0f;
    
                rm[1, 0] = vu.x;
                rm[1, 1] = vu.y;
                rm[1, 2] = vu.z;
                rm[1, 3] = 0.0f;
    
                rm[2, 0] = vn.x;
                rm[2, 1] = vn.y;
                rm[2, 2] = vn.z;
                rm[2, 3] = 0.0f;
    
                rm[3, 0] = 0.0f;
                rm[3, 1] = 0.0f;
                rm[3, 2] = 0.0f;
                rm[3, 3] = 1.0f;
    
                Matrix4x4 tm = new Matrix4x4();
                tm[0, 0] = 1.0f;
                tm[0, 1] = 0.0f;
                tm[0, 2] = 0.0f;
                tm[0, 3] = -pe.x;
    
                tm[1, 0] = 0.0f;
                tm[1, 1] = 1.0f;
                tm[1, 2] = 0.0f;
                tm[1, 3] = -pe.y;
    
                tm[2, 0] = 0.0f;
                tm[2, 1] = 0.0f;
                tm[2, 2] = 1.0f;
                tm[2, 3] = -pe.z;
    
                tm[3, 0] = 0.0f;
                tm[3, 1] = 0.0f;
                tm[3, 2] = 0.0f;
                tm[3, 3] = 1.0f;
    
                //矩阵组
                //
                mirrorCamera.projectionMatrix = p;
                mirrorCamera.worldToCameraMatrix = rm * tm;
    
    
                if (estimateViewFrustum)
                {
                    //旋转摄像机
                    Quaternion q = new Quaternion();
                    q.SetLookRotation((0.5f * (pb + pc) - pe), vu);
                    //聚焦到屏幕的中心点
                    mirrorCamera.transform.rotation = q;
    
                    //保守估计fieldOfView的值
                    if (mirrorCamera.aspect >= 1.0)
                    {
                        mirrorCamera.fieldOfView = Mathf.Rad2Deg *
                           Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude)
                           / va.magnitude);
                    }
                    else
                    {
                        //在摄像机角度考虑,保证视锥足够宽
                        mirrorCamera.fieldOfView =
                           Mathf.Rad2Deg / mirrorCamera.aspect *
                           Mathf.Atan(((pb - pa).magnitude + (pc - pa).magnitude)
                           / va.magnitude);
                    }
                }
            }
        }
    }
    
    3、创建一个Plane作为镜子,这个Plane的Shader必须要是一个能接受贴图的,所以这里可以自行使用Unity自带的Shader,我选择了Unlit/Texture

    4、将下面的代码赋给2中创建的Camera,将主摄像机给MainCamrea变量,镜子Plane赋值给MirrorPlane变量,

    using UnityEngine;
    using System.Collections;
    [ExecuteInEditMode]
    public class Mirrors2 : MonoBehaviour {
    
        public GameObject mirrorPlane;//镜子
        public Camera mainCamera;//主摄像机
        private  Camera mirrorCamera;//镜像摄像机
        // Use this for initialization
        void Start () {
            mirrorCamera = GetComponent<Camera>();
    
        }
    
        // Update is called once per frame
        void Update () {
    
            if(null!=mirrorPlane&&null!=mirrorCamera&&null!=mainCamera)
            {
                //将主摄像机的世界坐标位置转换为镜子的局部坐标位置
                Vector3 postionInMirrorSpace = mirrorPlane.transform.InverseTransformPoint(mainCamera.transform.position);
    
                //一般y为镜面的法线方向
                postionInMirrorSpace.y = -postionInMirrorSpace.y;
    
                //转回到世界坐标系的位置
                mirrorCamera.transform.position = mirrorPlane.transform.TransformPoint(postionInMirrorSpace);
            }
        }
    }
    
    5、如果是刚创建的Camera的投影梯形一定是非常规则的如图所示,勾选这个Camera

    上的ViewPlane脚本上的setNearClipPlane,这个时候其实是在设置这个Camera的近剪切屏幕,使得这个平面尽量与镜子Plane平面重合,如图所示,这个还不是完全的重合,可以通过调整参数nearClipDistanceOffset来调整,默认的-0.01其实就是我已经调

    整好了的参数,只要勾选setNearClipPlane就会自动调整到与镜子平面重合,如图所示


    6、最后创建一个RenderTexture,这个Texture就是用来将镜像摄像机投影出来的图像信息传递给镜子Plane的中间变量,所以将这个Texture分别托给Plane的Shader材质中的Texture和镜像摄像机中的TargetTexture。最后设置这个Texture的分辨率,我设置成了1024×1024,默认的是256×256,这样的会造成镜像模糊,如图所示


    设置成1024×1024之后就如第一章图所示,清晰度比较高。

    三、总结

    1、缺点:镜子不能有自己的贴图、不能实现多面镜子同时相互反射(还有待发现)

    2、相比上一篇的优点:可以实时的反射所有在镜面上的物体,可以改变物体的光照和贴图

    3、什么不是Shader,一句Shader代码都没有怎么还是Shader的案例,跟Shader有毛关系?是的,的确没有一句Shader的代码,然而使用C#代码控制其实都是Shader里面的参数,比如投影矩阵的计算,尤其是此处的投影区域有不规则倾斜的情况。

    后续待…

    原文转载请注明出处点击打开链接

    工程文件下载地址点击打开链接

    展开全文
  • Unity&Shader案例篇-镜子1

    千次阅读 2016-11-15 17:01:39
    废话不多说先上效果图,我使用的是在Unity5.3.3版本。 一、原理 1、首先要准备的素材是三个,对没错,就是三个因为镜子里面的那个物体其实是实物的复制体而已;一个Plane作为镜子,还有一个实物和虚物体。 2...

        废话不多说先上效果图,我使用的是在Unity5.3.3版本。


    一、原理

    1、首先要准备的素材是三个,对没错,就是三个因为镜子里面的那个物体其实是实物的复制体而已;一个Plane作为镜子,还有一个实物和虚物体。

    2、新建一个材质使用下面的Shader代码,并将此材质球赋给那个虚物体
    Shader "Custom/Cg shader for virtual objects in mirrors" {
            Properties{
                    _Color("Virtual Object's Color", Color) = (1, 1, 1, 1)
            }
                    SubShader{
                    Tags{ "Queue" = "Transparent+20" }
     
                    Pass{
                    Blend OneMinusDstAlpha DstAlpha
     
                    CGPROGRAM
     
    #pragma vertex vert 
    #pragma fragment frag
     
    #include "UnityCG.cginc"
     
                    uniform float4 _Color;
            uniform float4x4 _WorldToMirror;
     
            struct vertexInput {
                    float4 vertex : POSITION;
            };
            struct vertexOutput {
                    float4 pos : SV_POSITION;
                    float4 posInMirror : TEXCOORD0;
            };
     
            vertexOutput vert(vertexInput input)
            {
                    vertexOutput output;
     
                    output.posInMirror = mul(_WorldToMirror,
                            mul(_Object2World, input.vertex));
                    output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
                    return output;
            }
     
            float4 frag(vertexOutput input) : COLOR
            {
                    //如果镜子里的物体出来了就剔除掉
                    if (input.posInMirror.y > 0.0)
                    {
                            discard;
                    }
            return float4(_Color.rgb, 0.0);
            }
     
                    ENDCG
            }
            }
    }

    3、另外在建一个材质使用下面的Shader代码,并将此材质球赋值给实物体

    Shader "Unlit/Cg shader for Real objects"
    {
            Properties{
                    _Color("Virtual Object's Color", Color) = (1, 1, 1, 1)
            }
       SubShader {
          Pass {
             CGPROGRAM
     
             #pragma vertex vert 
             #pragma fragment frag
                    uniform float4 _Color;
             float4 vert(float4 vertexPos : POSITION) : SV_POSITION 
             {
                return mul(UNITY_MATRIX_MVP, vertexPos);
             }
     
             float4 frag(void) : COLOR
             {
                return float4(_Color.rgb, 1.0);
             }
     
             ENDCG
          }
       }
    }

    4、建立一个镜子的材质并将下面的Shader代码赋给作为镜子的那个面板

    Shader "Unlit/Mirrors"
    {
    	Properties{
    		_Color("Mirrors's Color", Color) = (1, 1, 1, 1)
    	}
    		SubShader{
    		Tags{ "Queue" = "Transparent+10" }
    		// draw after all other geometry has been drawn 
    		// because we mess with the depth buffer
    		//确保在所有的真实物体渲染之后再渲染
    
    		// 1st pass: mark mirror with alpha = 0
    		Pass{
    		CGPROGRAM
    
    #pragma vertex vert 
    #pragma fragment frag
    
    		float4 vert(float4 vertexPos : POSITION) : SV_POSITION
    	{
    		return mul(UNITY_MATRIX_MVP, vertexPos);
    	}
    
    		float4 frag(void) : COLOR
    	{
    		return float4(1.0, 0.0, 0.0, 0.0);
    	// this color should never be visible, 
    	// only alpha is important
    	}
    		ENDCG
    	}
    
    		// 2nd pass: set depth to far plane such that 
    		// we can use the normal depth test for the reflected geometry
    		Pass{
    		ZTest Always
    		Blend OneMinusDstAlpha DstAlpha
    		//==float4 result = float4(1.0 - pixel_color.a) * fragment_output + float4(pixel_color.a) * pixel_color;
    
    		CGPROGRAM
    
    #pragma vertex vert 
    #pragma fragment frag
    
    		uniform float4 _Color;
    	// user-specified background color in the mirror
    
    	float4 vert(float4 vertexPos : POSITION) : SV_POSITION
    	{
    		float4 pos = mul(UNITY_MATRIX_MVP, vertexPos);
    		pos.z = pos.w;
    		// the perspective division will divide pos.z 
    		// by pos.w; thus, the depth is 1.0, 
    		// which represents the far clipping plane
    		return pos;
    	}
    
    		float4 frag(void) : COLOR
    	{
    		return float4(_Color.rgb, 0.0);
    	// set alpha to 0.0 and 
    	// the color to the user-specified background color
    	}
    		ENDCG
    	}
    	}
    }
    


    5、最后新建一个C#脚本,代码如下,将此代码赋给虚物体,并将Plane和虚物体拖动赋值给里面的对应两个变量

    using UnityEngine;
    using System.Collections;
     
    [ExecuteInEditMode]
    public class PlacingTheVirtualObj : MonoBehaviour {
     
        public GameObject objectInFrontOfMirror;
        public GameObject mirrorPlane;
     
        // Use this for initialization
        void Start () {
         
        }
     
        // Update is called once per frame
        void Update() {
            if (null != mirrorPlane)
            {
                //这句话决定了镜子里的物体是否可见
                GetComponent<Renderer>().sharedMaterial.SetMatrix("_WorldToMirror",mirrorPlane.GetComponent<Renderer>().worldToLocalMatrix);
                if (null != objectInFrontOfMirror)
                {
                    //将实物的颜色值赋给镜中的物体
                    Color realColor = objectInFrontOfMirror.GetComponent<Renderer>().material.GetColor("_Color");
                    GetComponent<Renderer>().material.SetColor("_Color", realColor);
     
                    transform.position = objectInFrontOfMirror.transform.position;
                    transform.rotation = objectInFrontOfMirror.transform.rotation;
                    transform.localScale =
                       -objectInFrontOfMirror.transform.localScale;
                    //new Vector3(0.0f, 1.0f, 0.0f)为表面的法线方向
                    transform.RotateAround(objectInFrontOfMirror.transform.position,mirrorPlane.transform.TransformDirection( new Vector3(0.0f, 1.0f, 0.0f)), 180.0f);
                  Vector3  positionInMirrorSpace  =
                       mirrorPlane.transform.InverseTransformPoint(objectInFrontOfMirror.transform.position);
                    positionInMirrorSpace.y = -positionInMirrorSpace.y;
                    transform.position = mirrorPlane.transform.TransformPoint(
                       positionInMirrorSpace);
                }
            }
        }
    }

    原文地址点击打开链接转载请注明出处

    工程下载地址点击打开链接

    展开全文
  • Unity&Shader案例篇-镜子2

    千次阅读 2016-11-15 17:03:04
    一、前言上一篇介绍了有关镜子的制作,有关理论部分的内容我会在后续相关的文章中陆续介绍,莫急...还是废话不多说先上图,我用的Unity奔波5.3.3 二、Unity中制作原理 1、简单说明:其实这个原理就是用一个摄像机去拍镜
  • Unity3D Shader:镜子的效果

    千次阅读 2018-10-09 20:24:03
    Shader部分代码: Shader "Custom/FanShe" { Properties{ _MainTex("Albedo",2D) = "white"{} _MainTint("Diffuse Color",Color)=(1,1,1,1) ...Reflection Amount&
  • Unity技巧】Unity中的优化技术

    万次阅读 多人点赞 2014-12-26 22:12:00
    除此之外,还参考了Unity Cookie中的一个教程。这篇文章旨在简要地说明一下常见的各种优化策略。不过对每个基础有非常深入地讲解,需要的童鞋可以自行去相关资料。影响性能的因素首先,我们得了解,影响游戏性能的...
  • Unity构建真实地形的几种方法

    万次阅读 2018-07-11 09:43:47
    Unity构建美国西海岸真实地形在进行3D游戏开发的时候,尤其是战争题材或者模拟飞行类型的游戏,经常要构建真实的地形地貌。今天小编将带领大家学习几种Unity3D中常见的并且非常好用的真实地形构建方法。方法1:利用...
  • using UnityEngine; using System.Collections; using System.Collections.Generic; [System.Serializable] ...public class BarrackGroupInfo { ...public BarrackGroupType barrackGroupType;...public List barrack
  • Unity开发环境搭建

    千次阅读 2018-11-12 17:56:51
    Unity开发环境搭建序言Unity 序言 工欲善其事必先利其器,想做开发,肯定得先选号工具,我们来看下,你需要什么:Unity和Microsoft Visual Studio,怎么样?简单吧!就两样工具你就能开发了,这简单的背后,是强大的...
  • UnityHub使用方法教程和简介

    万次阅读 2018-10-16 23:51:15
    UnityHub简介 Unity Hub是最新推出的用于简化工作流程的桌面端应用程序。它提供了一个用于管理Unity项目、简化下载、查找,卸载以及安装管理多个Unity版本的工具。   Unity Hub v1.1的主要功能: Unity编辑器...
  • Unity 3D - Unity中文手册( 圣典 )

    万次阅读 2017-03-22 14:45:17
    Unity圣典
  • Unity 所有版本下载地址

    万次阅读 2018-05-02 11:06:26
    unity 官网所有版本下载地址: http://unity3d.com/get-unity/download/archive
  • unity3D中添加字体

    万次阅读 2017-04-20 16:51:41
    如何在unity3D中添加字体,在unity3D中Assets下添加自己的字体
  • Unity Hub许可证激活问题

    万次阅读 多人点赞 2020-02-18 12:16:45
    去官网下了个Unity2019.1.02f,然后打开的时候又要我下一个Unity Hub2.0.0,很迷,不知道这个是干嘛的,了解了一下才知道,原来这个就是个管理Unity版本的软件,也就是我们可以在自己电脑上安装多个Unity版本,然后...
  • Unity——退出程序代码

    万次阅读 2017-06-06 21:49:04
    在退出按钮的点击事件中添加以下代码: Application.Quit(); 即可实现退出程序的功能。
  • unityhub下载地址

    万次阅读 2019-07-01 10:12:58
    https://store.unity.com/cn/download?ref=personal
1 2 3 4 5 ... 20
收藏数 241,448
精华内容 96,579
关键字:

unity