• 六年前第一次接触《魔兽世界》的时候,被其绚丽的画面所折服,一个叫做贫瘠之地的地方,深深印在我的脑海里。当时在艾泽拉斯大陆还不能使用飞行坐骑,试想一下孤身...回到正题,在Unity中要创建这样的效果并不困难,用
    六年前第一次接触《魔兽世界》的时候,被其绚丽的画面所折服,一个叫做贫瘠之地的地方,深深印在我的脑海里。当时在艾泽拉斯大陆还不能使用飞行坐骑,试想一下孤身一人在银色的月光下赶路,可能还有你的战斗小伙伴,静谧的夜晚,皎洁的月光,一起走过了六年……即便是现在回想起来,浮现在脑海中的不是T123456S123456,而是十字路口的夜空。

    img?s=JtQEHzpkn&l=y.jpg 

    回到正题,在Unity中要创建这样的效果并不困难,用专业一点的术语讲就是只需要创建一个天空盒,并给予它天空纹理即可。通俗一点来讲,就是在我们的前面几章创建的地形四周罩上一个立方体盒,并把盒子上面添上星空的照片就搞定了。有软件可以将魔兽世界的素材提取出来,然后加以利用到我们自己的游戏中。

    不过这一章我并不准备讲述这些,因为主题是为了把天空盒和镜头光晕的知识点整理一下,如果有时间,我会另写一篇关于如何使用强大的”Wow Model Viewer”来导出魔兽世界的模型、贴图等素材,并导入到Unity中。其实具体操作并不困难,心急的朋友们可以去google code下载这个软件:http://code.google.com/p/wowmodelviewer/downloads/list

    Unity自带了好几种天空盒,从白天到黄昏再到夜晚,拿来做场景练习已经完全够用了。要使用天空盒素材,只需要导入Skyboxes素材包即可(至于如何导入可以参考我之前的笔记,每次都重复一遍略显蛋疼^_^)。导入成功后可以在项目资源面板的“Standard Assets->Skyboxes”目录下看到好多天空盒素材,Unity已经把盒子都造好了,我们直接拿来用就OK,非常人性化。

    接下来要把天空盒素材添加到游戏场景里,有两种添加天空盒的方法,这里先写比较容易理解的一种,另外一种将在以后写预设和组件的时候再解释。

    点击主菜单“Edit(编辑)->Render Settings(渲染设置)”,检视面板视图里就会出现渲染设置选项了,注意有个Skybox Material(天空盒材质)选项,点击它右边的小圆圈,就会弹出选择天空盒材质的对话框。单击任意一个材质球,设计视图中会立即提供预览,双击则表示确认使用,相当便捷。

    img?s=eFObiruD6&l=y.jpg 

    光这样是不够的,还记得之前添加的”线性光”吗?没错,就是那个“无限远、无限大类似于太阳的手电筒”^_^。它现在正静静地躺在层次面板中默默地燃烧自己,照亮世界,它不叫雷锋,它的名字叫做Directional light。这个名字有点拗口,选中它并按快捷键F2修改,换成Sun,就把它当作游戏里的太阳。细心的朋友会发现,太阳光的方向和天空盒上那个假的太阳的方向不一定会一致,可能导致太阳的位置和影子的位置有悖现实,所以必须手动调整,让它们重合。

    这里提供一种便捷的方法,首先在设计视图中拖动视角,让镜头中心对准天空盒上的太阳,然后在渲染设置中临时将天空盒设置为无(为了方便调整Sun的角度,否则天空盒太亮看不清楚)。然后选中Sun并使用旋转工具(快捷键E),将光线的方向正对自己,然后再将天空盒恢复即可。这样一来就不会闹太阳和影子在同一个方向的笑话了。

    img?s=3gNTAhpFD&l=y.jpg 

    玩过摄影的朋友应该都有这么个常识,当把镜头着阳光时,可能会出现一个或者多个七彩光环的光晕现象。百度一下光晕,发现全是关于某个游戏的@_@,好不容易找到张照片,就委屈一下大妈您嘞。右上角就是传说中的光晕啦。导入Unity自带的素材包“Light Flares(闪光)”,选中线性光“Sun”,在Sun的检视面板中找到Flare属性,选择一个光晕图片(我选的是50 mm Zoom),当当当当~看看天上的太阳,是不是耀眼多了?

    img?s=Seob85mhX&l=y.jpg  

    img?s=dd0BUOjVy&l=y.jpg 

    完成光晕之后顺便把迷雾之类的设置也了解一下吧,所谓“欲穷千里目,更上一层楼”,放在当今城市里已经不太合适了。因为污染呀,各种细小的粉尘漂浮在空气中,平时可能难以察觉,但是当举目远眺的时候就会发现远处根本就是一片迷茫嘛,跟大雾天一样的。在Unity的渲染设置中可以方便地调节这种迷雾的效果,甚至可以改变颜色和浓度等等:

    • Fog(是否启用迷雾效果)
    • Fog Color(迷雾的颜色)
    • Fog Mode(迷雾模式) 可以选择“Linear(线性)”、“Exponential(指数性)”、“Exp2(指数性2)”三种渲染模式,具体动手尝试一下即可,差别不是很大。
    • Fog Density(迷雾浓度)
    • Linear Fog Start(线性迷雾起始距离)
    • Linear Fog End(线性迷雾终止距离) 当选择线性的迷雾模式时,这两个参数表示了相对于镜头的迷雾的范围。在这个范围内迷雾的浓度会被平均化,也就是说当范围很小的时候,远处的物体会很清晰,近处的物体反倒一点都看不见。
    • Ambient Light(环境光) 调节这个颜色会影响到整个游戏场景的光线,比如调成粉红色的话……就好暧昧啊 哈哈。
    • Skybox Material(天空盒材质)
    • Halo Strength(光环强度,没弄明白)
    • Flare Strength(光晕强度)
    • Halo Textrue(光环贴图,没弄明白)
    • Spot Cookie(光斑?没弄明白)
    img?s=L2IO3B2YU&l=y.jpg 

    最后上张效果图,骄阳似火闷得慌啊哈哈~看来下一章非得加点水不可了:)
    展开全文
  • Unity3D基础知识学习笔记 1、基础知识: 标题栏 菜单栏 工具栏:变换工具、gizmos切换、播放控件、层列表、布局列表 功能窗口 2、资源及资源类型:在project里面能够create的资源。project面板可以对资源进行组织...

    Unity3D基础知识学习笔记

    1、基础知识:
    标题栏
    菜单栏
    工具栏:变换工具、gizmos切换、播放控件、层列表、布局列表
    功能窗口

    2、资源及资源类型:在project里面能够create的资源。project面板可以对资源进行组织管理,创建资源,搜索资源。

    3、模型和角色动画:

    角色动画创建过程时:创建角色模型、骨骼设置、蒙皮、烘焙动画。 
    maya、3dmax创建的模型、动画,用插件输出(fbx、obj)或者软件自己的格式(max、blend),unity自身转换。
    maya、3dmax创建的模型、动画,需要把IK/FK动画烘焙为关键帧动画,然后导入到unity中,才能识别。关键帧动画能够节省很多计算资源,因为IK/FK运动学动画是每一帧都会涉及到运动学计算的。

    maya、3dmax创建的模型、动画,可以全部导入到unity中,然后分割;或者按照一定的命名规则,先分割再导入到untiy中。

    4、材质和着色器:
    材质和着色器都是属于资源类型,在project面板中create,或者外部导入,纹理即图片,不能使用unity创建,但是可以通过ps等图形处理软件创建编辑之后,导入到unity中使用。
    Mesh Renderer组件:包含材质、着色器、纹理(贴图)的选项和参数设置
    可以这样理解:纹理+着色器=材质
    2D纹理:一张2D贴图
    movie纹理:视频(mov/mpg/mpeg/mp4/avi/asf)通过quick time导入之后,被unity自动转换为ogg theroa格式。即动画纹理,之后可以像普通纹理一样使用。

    5、声音文件:
    声音资源存放于project面板中,可以通过component中的audio listener和audio source组件进行使用。

    6、prefab预设:

    prefab预设:就是把设计好的游戏物体存为一个备份,当需要生成多个实例化物体时可以直接拷贝使用,避免了重复造轮子的问题。
    重用性和运行实例化:创建预设的instance
    实例的继承性:修改预设属性,所有的实例会跟着改变。
    实例的重载:单独修改实例,则只会对此实例生效。

    7、游戏物体使用组件来丰富功能,组件使用project里面的资源来设置属性。

    8、scene视图操作;
    透视模式persp、正交模式iso
    snap移动,按住ctrl键拖动物体,以一定的增量来移动。
    表面移动,ctrl+shift拖动物体,一个物体在另一个物体表面移动。
    顶点吸附:v键激活移动物体顶点,选择好之后拖动,可在另一个物体的顶点上移动。

    9、灯光和摄像机:
    灯光类型:spot(聚光灯)、directional(方向光)、point(点灯光)、area(区域光)

    10、unity脚本的使用:
    5*Time.deltaTime:每秒5度或者5米,和unity的帧速率无关。deltaTime记录了上一帧执行完成的时间。 1/FPS 这里的FPS是实时变化的。

    11、C#脚本:test01.cs test02.cs
    test01.cs引用test02.cs变量
    需要把变量定义为public static类型,然后可以直接引用 test02.var;test02.cs
    可以在test02中定义方法(读写变量的实现),然后在test01中调用test02的方法即可实现
    在test02中定义静态方法public static test02 instance;并在Awake中赋值为this,在test01中调用此方法test02.instance.var即可
    test01和test02属于同一个GameObject:直接调用getcomponent获取脚本组件
    test01和test02不属于同一个GameObject:可以通过定义test02所属GameObject的tag,然后在test01中FindGameObjectWithTag或者直接在test01中Find而不定义tag

    12、GameObject的获取:
    通过脚本里面定义public的GameObject的变量,然后在Inspector面板中拖动另一个GameObject获取
    通过在脚本里面Find函数实现(直接Find或者给GameObject定义tag,然后通过Findtag来获取)

    13、脚本使用:
    脚本里面的时间控制:
    time类
    yield WaitForSecond(5);//等待5s钟之后再次返回执行。
    脚本里面的随机数产生:random类
    脚本物体间通信方式:
    GameObject.SendMessage:向自身的脚本中发送消息。参数为函数名和函数的参数
    GameObject.BroadcastMessage:向自身及子物体的脚本中发送消息
    GameObject.SendMessageUpwards:向自身及父物体的脚本中发送消息
    使用delegate委托特性来实现。

    用一段代码来理解事件/委托机制的用法:下面的代码是点击中文,显示中文名字,点击英文,显示英文名字:

    using UnityEngine;
    using System.Collections;
    
    public class TestDelegate : MonoBehaviour
    {
    
        //定义一个委托(格式是不是很类很像),用来指向我们某个函数。(c++里面的指针函数)
        //param参数是名字
        private delegate void DebugString(string param);
    
        /// <summary>
        /// 输出中文名字
        /// </summary>
        public void DebugNameOfChina(string str)
        {
            Debug.Log("中文名字:" + str);
        }
    
        /// <summary>
        /// 输出英文名字
        /// </summary>
        public void DebugNameOfEnglish(string str)
        {
            Debug.Log("English Name:" + str);
        }
    
        //定义一个委托的变量事件
        private DebugString handlerDebugString;
    
    
        void OnGUI()
        {
            if (GUILayout.Button("输出中文名字"))
            {
                //我想输出中文名字的话就给handlerDebugString  赋值成输出中文名字的这个函数DebugNameOfChina
                handlerDebugString = DebugNameOfChina;
                handlerDebugString("丁小未");
            }
            else if (GUILayout.Button("Debug English Name"))
            {
                //我想输出英文名字的话就给handlerDebugString  赋值成输出中文名字的这个函数DebugNameOfEnglish
                handlerDebugString = DebugNameOfEnglish;
                handlerDebugString("DingXiaowei");
            }
        }
    }

    14、物理引擎:碰撞器与触发器、射线碰撞检测
    collider组件、rigidbody组件。
    constant force组件:世界坐标系方向力,局部坐标系方向力,世界坐标系扭矩力,局部坐标系扭矩力
    在脚本里面使用rigidbody类,和力有关的,需要放到FixedUpdate里面更新。
    能检测碰撞发生的方式有两种,一种是利用碰撞器,另一种则是利用触发器。
    碰撞器:一群组件,它包含了很多种类,比如:Box Collider(盒碰撞体),Mesh Collider(网格碰撞体)等,这些碰撞器应用的场合不同,但都必须加到GameObjecet身上。
    触发器,只需要在检视面板中的碰撞器组件中勾选IsTrigger属性选择框。
    碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。
      当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;
      当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。
    两个物体碰撞,可以不要rigidbody存在,但必须要有collider组件存在。只要勾选了is Trigger,就会进入OnTriggerEnter方法。
    如果想实现两个刚体物理的实际碰撞效果时候用OnCollisionEnter,Unity引擎会自动处理刚体碰撞的效果。如果想在两个物体碰撞后自己处理碰撞事件用OnTriggerEnter。

    发送一条射线:physics.Raycast(),出参为RayCastHit类型变量 hit.collider.gameObject

    15、物理引擎:joint关节组件
    joint关节组件依赖于rigidbody刚体组件
    hinge joint铰链关节:开关门、两个物体弹簧等
    fixed joint固定关节:两个物体的脱离效果
    spring joint弹簧关节:
    character joint角色关节:实际是一个球形关节,常用在人模型关节处,所以称为角色关节
    configurable joint配置关节:极高的可配置性,可以配置出以上所有关节的效果

    16、mecanim动画系统:
    MAYA或3DMAX(角色建模、骨骼设置、蒙皮、动画、烘焙)->导出到unity中->动画分割(如果是一个完整的动画)->
    mecanim系统专门为人类模型资源提供了一套avatar系统。
    avatar的创建过程:分析导入角色资源骨骼结构,与mecanim提供的标准骨骼结构对比,最后转换或标志位mecanim可以识别的骨骼结构。通过avatar的创建,可以实现角色之间的retargeting(角色资源的重用)
    在角色资源的输入配置中,Rig的Animation Type选择Humanoid,选择Apply之后自动生成Avatar,之后可以通过configure avatar手动调整。
    可以调整关节的mapping映射、调整muscles的运动范围
    body mask身体遮罩:在输入配置的animation中,有mask选项,目的是让身体的某部分运动失效。这样减少动画曲线的数量,减少计算量,优化CPU和内存的性能。
    retargeting:只要角色创建了avatar,不同角色之间的animator controller就可以重用,这就是retargeting的原理。在animator组件中进行设置。
    动画片段设置:有些动画效果只播放一遍,有些需要循环播放。在角色输入的animations中设置。
    root motion:角色的移动重心,勾选上就运用到scene的实例中,角色就可以运动,否则角色没有重心指向,不能运动。通过root motion就可以使用角色动画驱动角色运动。
    root motion的脚本控制:如果不勾选,又想让角色运动,则需要用脚本控制,一是在角色片段中创建curve曲线,二是在animator状态机中添加变量,三是创建脚本,重写方法OnAnimatorMove。
    blendtree:几个类似的动画片段复合为一个动画片段,在动画状态机里面创建。比如(左走,直走,右走动画片段可以融合为一个blendtree)
    嵌套blendtree可以实现走到跑的切换效果。
    blendtree的参数设置:1D 2D效果
    mecanim动画层的使用:使用层、身体遮罩、权重等设置,可以实现两个层的动画同时播放的效果,比如一边跑一边射击。
    mecanim反向运动学运用:可以让角色去精确的抓取物体。脚本里面需要重写OnAnimatorIK,在动画层中,打开IK Pass选项。
    mecanim目标匹配:通过animator.MatchTarget函数,可以实现角色攀爬的效果,定位到某个具体目标上。
    一般性角色动画:非人类角色动画,也可以使用mecanim动画系统,唯一区别是avatar不可配置。
    脚本实现角色跟随效果。
    脚本实现群组动画效果。

    17、输入与控制:
    输入接口:input类
    float h = Input.GetAxis("Horizontal");
    float v = Input.GetAxis("Vertical");
    判断输入值,然后控制player的移动
    getaxis、getkey、getbutton、getjoystick等函数。
    注意:unity GUI事件在一帧中可能触发多次。OnGUI函数可能在一帧中执行多次。

    18、角色控制器:CharacterController组件
    角色控制常规方式:rigidbody、角色控制器(最常用)
    角色控制器内置一个capsule collider,所以可以进行碰撞检测。
    角色控制器+第一人陈视角可以实现漫游效果。

    19、粒子系统:particle system
    创建:直接创建一个粒子系统GameObject或者先创建一个Empty的对象,再添加粒子系统组件。
    粒子系统功能十分强大,可以创建出各种需要的特效。

    20、树:
    Tree component
    可以使用程序自动生成,但是如果手动调节过后,一些参数将不再可调。
    树的基本属性、树干的基本属性、树叶的基本属性、树与地形的配合使用。

    21、地形引擎:Terrian
    地形工具栏十分重要。下面的操作都是基于工具栏来选择和设置。
    地形创建与绘制:注意海平面flatten的设置才能产生凹地效果。
    地形纹理和材质的选择和使用。
    地形中添加树木、植被。
    地形工具栏中最后一项是地形设置。包括基本的地形分辨率显示,树木植被显示,风等效果的设置。
    可以使用插件EasyRoads3D来创建公路效果。

    22、GUI图形用户界面:
    UGUI和NGUI学习。


    展开全文
  • Unity3d学习笔记

    2020-07-10 17:56:12
    unity中的脚本类均继承自MonoBehaviour Time.deltaTime 游戏中一帧的时间 假如1秒运行60帧,则一帧为1/60秒;假如游戏运行时卡顿,帧数变为30帧,则一帧为1/30秒 Time.timeScale 时间伸缩,类似于视频中的倍速...

    Unity中的脚本类均继承自MonoBehaviour


    Time.deltaTime

    • 游戏中一帧的时间(秒)
    • 假如1秒运行60帧,则一帧为1/60秒;假如游戏运行时卡顿,帧数变为30帧,则一帧为1/30秒

    Time.timeScale

    • 时间伸缩,类似于视频中的倍速播放
    • 当timeScale=1时,时间为正常倍速。当timeScale=0,时间静止,可以用于暂停游戏。
    • 假如timeScale=0.5,则原来需要1秒来执行完的动画,特效等,现在需要1/timeScale=2秒来执行完成
    • timeScale不会影响Update()和LateUpdate(),只会影响FixedUpdate()

    Time.time

    • 游戏开始运行到现在经历的时间(秒),该变量会受到时间伸缩的影响

    Time.realtimeSinceStartup

    • 游戏开始运行到现在实际经历的时间(秒),该变量不受时间伸缩的影响

    Time.timeSinceLevelLoad

    • 关卡加载完成到现在的时间(秒)

    Time.fixedDeltaTime

    • 固定的时间间隔(秒)

    Time.maximumDeltaTime

    • 游戏开始到现在最耗时的一帧(秒),可用于游戏优化

    Time.smoothDeltaTime

    • 游戏开始到现在平均一帧的时间

    Time.frameCount

    • 游戏的帧计数

    void Awake() 

    • 脚本初始化时被调用

    void Start()

    • 脚本被绑定到物体上时调用

    void Update()

    • 每一帧的时间调用一次,会因为电脑卡顿而导致调用间隔变大

    void LateUpdate()

    • 在Update()执行完后调用

    void FixedUpdate()

    • 固定间隔时间调用一次,不会随着电脑性能变化而变化

    transform.position

    • 游戏物体在世界坐标系中的位置

    transform.localPosition

    • 游戏物体相对父节点的位置

    transform.eulerAngles

    • 游戏物体在世界坐标系中的旋转(欧拉角)

    transform.localEulerAngles

    • 游戏物体相对父节点的旋转(欧拉角)

    transform.rotation

    • 游戏物体在世界坐标系中的旋转(四元数)

    transform.localRotation

    • 游戏物体相对父节点的旋转(四元数)

    transform.localScale

    • 游戏物体自身的缩放

    transform.up

    • 物体的上方向量

    transform.forward

    • 物体的正前方向量

    transform.parent

    • 父节点物体的transform

    transform.localToWorldMatrix

    • 本地坐标系变换到世界坐标系的矩阵

    transform.worldToLocalMatrix

    • 世界坐标系变换到本地坐标系的矩阵

    transform.root

    • 层级关系中的根节点的transform组件

    transform.childCount

    • 子孙节点的数量

    transform.lossyScale

    • 全局缩放比例(只读)

    transform.Translate(Vector3 translation , Space relativeTo = Space.Self)

    • 按指定的方向移动一个物体
    • 参数1:位移的向量;参数2:参照的坐标系(Space.Self,Space.World)

    transform.Rotate(Vector3 eulers , Space relativeTo = Space.Self)

    • 按指定的欧拉角旋转物体
    • 参数1:欧拉角;参数2:参照的坐标系(Space.Self,Space.World)

    transform.RotateAround(Vector3 point, Vector3 axis, float angle)

    • 一个物体围绕另一个物体旋转
    • 参数1:被围绕物体的位置坐标;参数2:轴向量;参数3:旋转的角度

    transform.LookAt(Vector3 position)

    • 让物体朝向某一个位置
    • 参数1:朝向的位置坐标

    transform.TransformDirection(Vector3 direction)

    • 把一个方向从局部坐标系变换到世界坐标系
    • 参数1:方向向量

    transform.InverseTransformDirection(Vector3 direction)

    • 把一个方向从世界坐标系变换到局部坐标系
    • 参数1:方向向量

    transform.TransformPoint(Vector3 position)

    • 把一个点从局部坐标系变换到世界坐标系

    transform.InverseTransformPoint(Vector3 position)

    • 把一个点从世界坐标系变换到局部坐标系

    transform.DetachChildren() 

    • 和所有子物体解除父子关系

    transform.Find(string n)

    • 按名字来查找子物体,没有找到就返回null

    transform.IsChildOf(Transform parent)

    • 判断自身是否是另一个对象的子物体

    Quaternion.LookRotation(Vector3 forward, Vector3 upwards = Vector3.up)

    • 使游戏物体转向
    • 参数1:物体转向的向量;参数2:向上的方向向量

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

    • 从当前地点移动到目标点,且每次移动的最大长度不超过maxDistanceDelta
    • 参数1:当前的位置;参数2:目标位置;参数3:每次移动时的最大长度
    • 返回值为current加上maxDistanceDelta后的位置,如果超过了target,就返回target

    Vector3.Lerp(Vector3 a, Vector3 b, float t)

    • 根据t计算a到b之间的差值,t的取值范围为[0,1]
    • 当t=0时,返回值为a;当t=1时,返回值为b

    Vector3.Distance(Vector3 a, Vector3 b)

    • 计算两个位置之间的距离,返回值类型为float

    void OnTriggerEnter(Collider c)

    • 当有物体进入触发器时调用

    void OnTriggerExit(Collider c)

    • 当有物体离开触发器时调用

    void OnTriggerStay(Collider c)

    • 当有物体停留在触发器内时调用

    void OnCollisionEnter(Collision c)

    • 当有物体进入碰撞器时调用

    void OnCollisionExit(Collision c)

    • 当有物体离开碰撞器时调用

    void OnCollisionStay(Collision c)

    • 当有物体停留在碰撞器内时调用

    getComponent<Type>()

    • 获取游戏物体上type类型的控件

    getComponents<Type>()

    • 获取游戏物体上所有的type类型的控件,返回Component[]

    GetComponentInChildren<Type>()

    • 采用深度优先搜索,返回第一个遍历到的游戏物体和它子物体上的Type类型的控件

    GetComponentsInChildren<Type>()

    • 采用深度优先搜索,遍历游戏物体和它子物体上所有的Type类型的控件,返回Component[]

    GameObject.Find("GameObject/obj")

    • 根据名字或路径来查找物体对象

    GameObject.FindWithTag("player")

    • 根据标签tag来查找物体对象

    GameObject.FindGameObjectsWithTag("player")

    • 查找所有使用该标签tag的对象,返回GameObject[]

    Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask,               QueryTriggerInteraction queryTriggerInteraction)

    • 使游戏物体发出射线,来检测碰撞体
    • 参数1:射线的初始位置向量;参数2:射线的方向
    • 参数3:包含被检测到的物体的信息;参数4:射线的最远射程;
    • 参数5:需要检测的图层;参数6:是否检测触发器

    layerMask = 1<<n:检测第n层(0层为Default层)

    layerMask = ~1<<n:检测除第n层之外的图层

    LayerMask.GetMask("Player", "Default"):检测Player层和Default层

    ~LayerMask.GetMask("Player", "Default"):检测除Player层和Default层之外的图层

    QueryTriggerInteraction.Collider:检测开启触发器的碰撞体

    QueryTriggerInteraction.Ignore:不检测开启触发器的碰撞体

    QueryTriggerInteraction.UseGlobal:isTrigger钩选时检测,isTrigger不钩选时不检测


    协程的创建和使用

    void Start(){
        //
        StartCoroutine("Fun");
        //
    }
    
    
    IEnumerator Fun(){
        //
        yield return new WaitForSeconds(2.0f);
        //
    }
    • startCoroutine("fun"):开启协程,并转到Fun函数
    • yield return:返回到Start()函数并往下执行
    • new WaitForSeconds(2.0f):等待两秒后从其他函数再跳转到Fun函数继续执行(其他函数等待,不往下执行)
    • 协程属于单线程,来模拟多线程

    WaitForFixedUpdate()

    • 在FixedUpdate()执行完后返回到协程

    WaitForEndOfFrame()

    • 在一帧结束后返回到协程

    WaitForSecondsRealtime(float time)

    • 等待现实时间time秒后返回到协程,不受时间缩放的影响

    WaitUntil(bool fun())

    • 直到fun()函数返回值为true时,才返回到协程

    WaitWhile(bool fun())

    • 与WaitUntil相反,直到fun()函数返回值为false时,才返回到协程

    协程的停止

    void Start(){
        //第一种写法
        StartCoroutine("Fun");
        StopCoroutine("Fun");
    
        //第二种写法
        IEnumerator ie = Fun();
        StartCoroutine(ie);
        StopCoroutine(ie);
    
        //第三种写法
        Coroutine coroutine=StartCoroutine(Fun());
        StopCoroutine(coroutine);
        
        //关闭所有协程
        StopAllCoroutines();
    }
    
    IEnumerator Fun(){
        //
        yield return new WaitForSeconds(2.0f);
        //
    }
    • 调用stopCoroutine时,不能直接传入Fun(),要按以上三种写法来停止协程。

    委托的创建和使用

    public class Player : MonoBehaviour{
        public delegate void PlayMotify(); //创建委托的固定写法
        public event PlayMotify OnPlay;    //定义委托的一个事件
        void Play(){
            if(this.OnPlay!=null){    //判断是否有其他类接收该事件
                this.OnPlay();        //发送该事件
            }
        }
    }
    
    

    委托事件的接收

    public class Game : MonoBehaviour{
        public Player player;    //创建Player对象
        void Start(){
            this.player.OnPlay+=Player_OnPlay; //监听player下委托的事件,并调用Player_OnPlay函数
        }
    
        void Player_OnPlay(){
            //触发事件后,做自己的处理
        }
    }
    
    

    Unity自带的委托调用

    using UnityEngine.Events;
    public class Player : MonoBehaviour{
        public UnityAction<int> OnScore;  //泛型为OnScore函数参数
        void Play(){
            if(this.OnScore!=null){    //判断是否有其他类接收该事件
                this.OnScore(1);        //发送该事件
            }
        }
    }
    
    
    public class Game : MonoBehaviour{
        public Player player;    //创建Player对象
        void Start(){
            this.player.OnScore=GetScore; //监听player下委托的事件,并调用GetScore函数
        }
    
        void GetScore(int score){
            //触发事件后,做自己的处理
        }
    }
    
    

    Invoke(string methodName , float time)

    • 用于延迟执行指定函数
    • 参数1:要执行的函数名字;参数2:延迟time秒后执行

    InvokeRepeating(string methodName , float time , float repeatRate)

    • 用于重复执行指定函数(Repeating是重复的意思)
    • 参数1:要执行的函数名字;参数2:延迟time秒后执行;参数3:每repeatRate秒执行一次指定函数
    • 执行顺序:先准备要执行的函数methodName,等待time秒执行methodName,之后每repeatRate秒执行一次该函数

    Instantiate(T original , Vector3 position , Quaternion rotation)

    • 用于克隆游戏物体,返回值为该克隆体
    • 参数1:需要被克隆的对象;参数2:克隆后的位置坐标:;参数3:克隆后的旋转坐标

    3D游戏物体的运动控制脚本

    void Update(){
        //竖直轴 -1,0,1
        float vertical = Input.GetAxis("Vertical");
        //水平轴 -1,0,1
        float horizontal = Input.GetAxis("Horizontal");
        //方向
        Vector3 dir = new Vector3(horizontal,0,vertical);
        if(dir != Vector3.zero){
            //先转向
            transform.rotation=Quaternion.LookRotation(dir);
            //后行走
            transform.Translate(Vector3.forward * 2 * Time.deltatime);
        }
    }

    2D游戏物体的运动控制脚本

    void Update(){
        //水平轴 -1,0,1
        float horizontal = Input.GetAxis("Horizontal");
        //往左(-1)或往右(1)
        if(horizontal!=0){
            //将x轴的缩放取反,来实现人物转向
            transform.localScale=new Vector3(horizontal>0?1:-1, 1, 1);
            //移动
            transform.Translate(Vector2.right * horizontal * Time.deltaTime);
        }
    }

    导航寻路脚本

    //导航
    private NavMeshAgent agent;
    //玩家
    private Transform player;
    
    void Start(){
        agent=GetComponent<NavMeshAgent>();
        player=GameObject.FindWithTag("player").transform;
    }
    void Update(){
        float dis = Vector3.Distance(transform.position,player.position);
        if(dis>1.5f){    //与玩家距离大于1.5时,自动寻路到玩家
            agent.isStopped=false;
            agent.SetDestination(player.position);
        }else{
            agent.isStopped=true;
        }
    }

    相机跟随目标脚本

    //跟随目标
    private Transform player;
    //向量:摄像机的位置减去目标位置
    private Vector3 dir;
    void Start(){
        player = GameObject.FindWithTag("player").transform;
        dir = transform.position-player.position;    //保证该差值不变,实现目标的跟踪
    }
    
    void Update(){
       transform.position = player.position + dir;   //更新摄像机的位置
    }

    AudioSource控制脚本

    public class AudioManager:MonoBehaviour{
        //单例
        public static AudioManager instance;   
        //播放源控件 
        private AudioSource audioPlayer;
        void Start(){
            instance=this;
            audioPlayer=GetComponent<AudioSource>();
        }
    
        //播放音乐
        //name:播放的音乐的名字
        public void PlaySound(String name){
            //播放音乐片段,从资源文件中通过名字来加载音乐文件
            AudioClip clip=Resources.Load<AudioClip>(name);
            //播放一次
            audioPlayer.PlayOneShot(clip);
        }
    }

    Canvas

    • Render Mode:渲染模式
    1. Screen Space - Overlay:UI显示在最前方,遮挡其它3D物体
    2. Screen Space -Camera:摄像机包含整个UI界面,和3D物体有层次关系
    3. World Space:Canvas完全变为一个3D物体,可自由调节Canvas

    Canvas Scaler

    • UI Scale Mode:UI缩放模式
    1. Constant Pixel Size:UI以恒定的像素大小显示
    2. Scale With Screen Size:UI按屏幕的大小自动缩放
    3. Constant Physical Size:UI以恒定的物理尺寸显示
    • Scale With Screen Size:
    1. Reference Resolution:参考分辨率,参照UI依据的分辨率,随着分辨率的变化而自动缩放

    Anchor Presets

    • 图片相对于锚点的位置是固定的。假设图片在右上角,需要将锚点选到右上方,从而达到屏幕适配的效果

    Image

    • Image Type:图片样式
    1. Simple:简单模式,图片正常拉伸
    2. Slice:切分样式,可以将图片切分成多块
    3. Tiled:平铺样式,图片拉伸时,会有相同的图片显示在多余的区域
    4. Filled:填充样式,可以按特定的填充方式来显示图片

    组件中的拖拽条

    public class Game:MonoBehaviour{
        [Range(0,1)]
        public float value;
    }
    • 在组件面板界面中显示名字为value,范围为[0,1]的拖拽条

    持续学习更新......

    展开全文
  • UNITY3D学习笔记11

    2015-08-03 14:35:55
    using UnityEngine; using System.Collections; public class Test1 : MonoBehaviour { int Port = 10000; // Use this for initialization void Start () { } ... // Update is called once per frame ...



    using UnityEngine;
    using System.Collections;
    
    public class Test1 : MonoBehaviour {
    	
    	int Port = 10000;
    	
    	// Use this for initialization
    	void Start () { }
    	
    	// Update is called once per frame
    	void Update () { }
    	
    	void OnGUI(){
    		
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			OnServer();
    			break;
    		case NetworkPeerType.Client:
    			
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    	
    	void StartServer(){
    		if(GUILayout.Button("create local server")){
    			NetworkConnectionError error = Network.InitializeServer(10,Port,false);
    			
    			Debug.Log("state:"+error);
    		}
    	}
    	
    	void OnServer(){
    		GUILayout.Label("create finish wait ro connection:");
    		
    		int length = Network.connections.Length;
    		
    		for(int i = 0;i<length;i++){
    			GUILayout.Label("ID:"+i);
    			GUILayout.Label("IP:"+Network.connections[i].ipAddress);
    			GUILayout.Label("port number"+Network.connections[i].port);
    		}
    		
    		if(GUILayout.Button("disconnection"))
    		{
    			Network.Disconnect();
    		}
    	}
    }
    



    using UnityEngine;
    using System.Collections;
    
    public class Test2 : MonoBehaviour {
    
    	string IP = "127.0.0.1";
    
    	int Port = 10000;
    
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    
    	void OnGUI(){
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			//OnServer();
    			break;
    		case NetworkPeerType.Client:
    			
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    
    	void StartServer(){
    		if(GUILayout.Button("connection")){
    			NetworkConnectionError error = Network.Connect(IP,Port);
    			Debug.Log("state:"+error);
    		}
    	}
    }
    



    using UnityEngine;
    using System.Collections;
    
    public class Test3 : MonoBehaviour {
    
    	int Port = 10000;
    	string Message = "";
    	Vector2 scrollPosition;
    
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    
    	void OnGUI(){
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			OnServer();
    			break;
    		case NetworkPeerType.Client:
    			
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    
    	void StartServer(){
    		if(GUILayout.Button("connection")){
    			NetworkConnectionError error = Network.InitializeServer(10,Port,false);
    			Debug.Log("state:"+error);
    		}
    	}
    
    	void OnServer(){
    		GUILayout.Label("create finish wait ro connection:");
    		
    		int length = Network.connections.Length;
    		
    		for(int i = 0;i<length;i++){
    			GUILayout.Label("ID:"+i);
    			GUILayout.Label("IP:"+Network.connections[i].ipAddress);
    			GUILayout.Label("port number"+Network.connections[i].port);
    		}
    		
    		if(GUILayout.Button("disconnection"))
    		{
    			Network.Disconnect();
    
    			Message = "";
    		}
    
    		scrollPosition = GUILayout.BeginScrollView(scrollPosition,GUILayout.Width(200),GUILayout.Height(500));
    
    		GUILayout.Box(Message);
    		GUILayout.EndScrollView();
    	}
    
    	[RPC]
    	void RequestMessage(string message,NetworkMessageInfo info){
    		Message += "\n" + info.sender+":"+message;
    	}
    }
    



    using UnityEngine;
    using System.Collections;
    
    public class Test4 : MonoBehaviour {
    
    	string IP = "127.0.0.1";
    
    	int Port = 10000;
    
    	string inputMessage = "input Message";
    
    	string Message = "";
    
    	Vector2 scrollPosition;
    
    	void OnGUI(){
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			//OnServer();
    			break;
    		case NetworkPeerType.Client:
    			OnClient();
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    
    	void StartServer(){
    		if(GUILayout.Button("connection")){
    			NetworkConnectionError error = Network.Connect(IP,Port);
    			Debug.Log("state:"+error);
    		}
    	}
    
    	void OnClient(){
    		scrollPosition  = GUILayout.BeginScrollView(scrollPosition,
    		                                            GUILayout.Width(200),
    		                                            GUILayout.Height(500));
    
    
    		GUILayout.Box(Message);
    		GUILayout.BeginHorizontal();
    		inputMessage = GUILayout.TextArea(inputMessage);
    
    		if(GUILayout.Button("send Message")){
    			networkView.RPC("RequestMessage",RPCMode.All,inputMessage);
    		}
    
    		GUILayout.EndHorizontal();
    
    		if(GUILayout.Button("disconnection")){
    			Network.Disconnect();
    			Message= "";
    		}
    
    		GUILayout.EndScrollView();
    	}
    
    	[RPC]
    	void RequestMessage(string message,NetworkMessageInfo info){
    		Message +="\n"+"Sendor"+info.sender+":"+message;
    	}
    
    	// Use this for initialization
    	void Start () {
    	
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    }
    



    using UnityEngine;
    using System.Collections;
    
    public class Test5 : MonoBehaviour {
    	int Port = 10000;
    
    	string Message = "";
    	string MoveInfo = ""; 
    
    	Vector2 scrollPosition;
    
    	void OnGUI(){
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			OnServer();
    			break;
    		case NetworkPeerType.Client:
    			
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    
    	void StartServer(){
    		if(GUILayout.Button("create local server")){
    			NetworkConnectionError error = Network.InitializeServer(10,Port,false);
    			Debug.Log("state:"+error);
    		}
    	}
    
    	void OnServer(){
    		GUILayout.Label("create finish wait to connection:");
    		
    		int length = Network.connections.Length;
    		
    		for(int i = 0;i<length;i++){
    			GUILayout.Label("ID:"+i);
    			GUILayout.Label("IP:"+Network.connections[i].ipAddress);
    			GUILayout.Label("port number:"+Network.connections[i].port);
    		}
    		
    		if(GUILayout.Button("disconnection"))
    		{
    			Network.Disconnect();
    			MoveInfo = "";	
    			Message = "";
    		}
    
    		scrollPosition = GUILayout.BeginScrollView(scrollPosition,
    		                                          GUILayout.Width(200),
    		                                          GUILayout.Height(Screen.height));
    
    		GUILayout.Box(Message);
    		GUILayout.Box(MoveInfo);
    		GUILayout.EndScrollView();
    	}
    
    	[RPC]
    	void RequestMessage(string message,NetworkMessageInfo info){
    		Message +="\n" +"sendor"+info.sender+":"+message;
    	}
    
    	[RPC]
    	void RequestMove(string message,NetworkMessageInfo info){
    		MoveInfo += "\n"+"Mover"+info.sender+":action"+message+"move event";
    	}
    
    	// Use this for initialization
    	void Start () { }
    	
    	// Update is called once per frame
    	void Update () { }
    }
    



    using UnityEngine;
    using System.Collections;
    
    public class Test6 : MonoBehaviour {
    
    	string IP = "127.0.0.1";
    
    	int Port = 10000;
    
    	string inputMessage = "input message";
    
    	string Message = "";
    
    	Vector2 scrollPosition;
    
    	float speed = 10.0f;
    	float rotationSpeed = 100.0f;
    
    	GameObject cube0 = null;
    	GameObject cube1 = null;
    
    	void OnGUI(){
    		switch(Network.peerType){
    		case NetworkPeerType.Disconnected:
    			StartServer();
    			break;
    		case NetworkPeerType.Server:
    			//OnServer();
    			break;
    		case NetworkPeerType.Client:
    			OnClient();
    			break;
    		case NetworkPeerType.Connecting:
    			
    			break;
    		}
    	}
    
    	void FixedUpdate(){
    		if(Network.isClient){
    			float translation = Input.GetAxis("Vertical");
    			float rotation = Input.GetAxis("Horizontal");
    
    			if(translation==1){
    				networkView.RPC ("RequestMove",RPCMode.All,"up");
    			}
    
    			if(translation == -1){
    				networkView.RPC ("RequestMove",RPCMode.All,"down");
    			}
    
    			if(rotation == 1){
    				networkView.RPC ("RequestMove",RPCMode.All,"left");
    			}
    
    			if(rotation == -1){
    				networkView.RPC ("RequestMove",RPCMode.All,"right");
    			}
    		}
    	}
    
    	void StartServer(){
    		if(GUILayout.Button("connection")){
    			NetworkConnectionError error = Network.Connect(IP,Port);
    			Debug.Log("state:"+error);
    		}
    	}
    
    	void OnClient(){
    		scrollPosition = GUILayout.BeginScrollView(scrollPosition,
    		                                          GUILayout.Width(200),
    		                                          GUILayout.Height(500));
    
    		GUILayout.Box(Message);
    		GUILayout.BeginHorizontal();
    
    		inputMessage = GUILayout.TextArea(inputMessage);
    
    		if(GUILayout.Button("send")){
    			networkView.RPC("RequestMessage",RPCMode.All,inputMessage);
    		}
    
    		GUILayout.EndHorizontal();
    
    		if(GUILayout.Button("disconnection")){
    			Network.Disconnect();
    			Message = "";
    		}
    
    		GUILayout.EndScrollView();
    	}
    
    	[RPC]
    	void RequestMessage(string message,NetworkMessageInfo info){
    		Message += "\n"+"sender"+info.sender+":"+message;
    	}
    
    	[RPC]
    	void RequestMove(string message,NetworkMessageInfo info){
    		string sender = info.sender.ToString();
    
    		GameObject moveObject = null;
    
    		if(sender =="-1")
    		{
    			moveObject = cube0;
    		}else{
    			moveObject = cube1;
    		}
    
    		int vertical = 0;
    		int horizontal = 0;
    
    		if(message == "up"){
    			vertical = 1;
    		}
    		if(message == "down"){
    			vertical = -1;
    		}
    		if(message == "left"){
    			horizontal = 1;
    		}
    		if(message == "right"){
    			horizontal = -1;
    		}
    
    		float translation = vertical * speed * Time.deltaTime;
    		float rotation = horizontal * rotationSpeed * Time.deltaTime;
    		moveObject.gameObject.transform.Translate(0,0,translation);
    		moveObject.gameObject.transform.Rotate(0,rotation,0);
    	}
    
    
    
    	// Use this for initialization
    	void Start () {
    		cube0 = GameObject.Find("Cube0");
    		cube1 = GameObject.Find("Cube1");
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    }
    


    展开全文
  • 一.官方文档 官方文档就相当于引擎的百科全书,有什么疑难点都可以翻阅查看。 链接:Unity3D官网 二.

    一.官方文档

    官方文档就相当于引擎的百科全书,有什么疑难点都可以翻阅查看。
    传送门:Unity官方文档
    在这里插入图片描述

    二.哔哩哔哩

    小破站真的是良心,很多好心的UP主常常会搬运视频到上面,对于无法科学上网的同学,是个不错的选择。
    传送门:哔哩哔哩( ゜- ゜)つロ 干杯~bilibili
    在这里插入图片描述

    三.官方公众号

    技术分享、活动预告、新闻资讯等等可以第一时间了解。
    传送门:微信搜索“Unity官方平台”
    在这里插入图片描述

    四.CSDN文章

    不说了,大家应该都懂的。
    传送门:CSDN Unity笔记
    在这里插入图片描述

    五.官方论坛

    我们在学习过程中遇到的大部分问题,都可以在上面寻找到答案(页面为英文,请自行翻译)
    传送门:官方论坛
    在这里插入图片描述

    六.Reddit论坛网

    有名的论坛网,很受欢迎的。(关键字需为英文、需要科学上网)
    传送门:Reddit论坛网
    在这里插入图片描述

    七.百度、Google、维基百科

    善用搜索引擎,是学习的必经之路(Google需要科学上网)
    传送门:
    百度
    谷歌
    维基百科

    在这里插入图片描述
    在这里插入图片描述

    八.油管(YouTube)

    最直接的学习途径(关键字需为英文、需要科学上网)
    传送门:YouTube
    在这里插入图片描述

    参考资料:谌嘉城—— UE4初学者系列教程合集(上)-全中文新手入门教程——第二集

    展开全文
  • Unity3d学习笔记1——基础概念了解目录Unity3d学习笔记1基础概念了解
  • 1.Draw Call本身的含义就是CPU调用图像编程接口,像OpenGL或者 DirectX。简单来说,Draw Call就是由CPU发起的一个命令,添加到一个命令缓冲区,当GPU完成了上一次的渲染任务之后,会从命令缓冲区的命令队列中再取出...
  • Unity3D课程学习笔记(一) 1.解释游戏对象(GameObjects)和资源(Assets)的区别与联系 官方文档对Assets的解释:An asset is representation of any item that can be used in your game or project. An asset ...
  • Unity3D学习笔记(一)

    2018-03-27 22:04:28
    1、解释 游戏对象(GameObjects)和 资源(Assets)的区别与联系。游戏对象:出现在游戏场景中的实体,是一些资源的集合体,是资源整合的具体表现。资源:资源可以被多个对象利用,成为组件中的属性或者行为;...
  • Unity3d学习笔记(一)

    2019-01-24 15:32:06
    今天下午乖乖的跟着教学视频学习使用Unity3d完成期末的游戏课程实验,第一遍跟着做的时候没有什么印象,几天尝试一边做一遍整理,一遍查自己不明白的地方,发现有很多知识点课本上并没有学习到。先把下午的知识点...
  • Unity3D学习笔记总结

    2013-12-21 21:34:06
    编辑器: Hierarchy窗口中是场景中的Game Object列表 Project窗口中是磁盘上Assets文件夹中的内容,可用来创建Game Object 调试: ...因Unity采用的是Mono运行时引擎而不是CLR,参考Debugging us
  • unity3d学习笔记

    2014-07-28 21:56:33
    一。Unity集成开发环境的搭建,
  • Unity3D学习笔记(2)Unity3D与3DMax结合开发注意事项 单位:比例统一 在建模型前先设置好单位,在同一场景中会用到的模型的单位设置必须一样,模型与模型之间的比例要正确,和程序的导入单位一致,即便到程序...
  • Unity3D学习笔记

    2020-06-05 11:26:04
    Unity3D学习笔记:AssetBundle有依赖关系时需要共同使用的材质设置为public using System.Collections; using System.Collections.Generic; using UnityEngine; public class LoadDependency : MonoBehaviour { //...
  • Unity3D学习笔记(五)湖泊与瀑布   转载自 http://huangxuyang.cn/unity3d/learning-unity3d-note-5 标签 Unity3D, 学习笔记, C# 七月 14 2012 11:35 下午 炎炎夏日,杭州的温度一直居高不下,还好今天...
  • Unity3D学习笔记(1)

    2016-03-01 13:59:34
    1. 解释对象与资源的区别与联系,根据AngryBots,以及其他官方案例,分别总结资源和对象组织的规则。 对象直接出现在游戏的场景中,是资源整合的具体表现,而资源可以被多个对象使用。有些资源作为模板,可实例化成...
  • 用Unet改造Tanks! Tutorial。 设计 第一步是在项目中创建 NetworkManager 对象,Game Object -&... Create Empty,添加NetworkManager组件来管理游戏的网络状态,添加NetworkManagerHUD组件得到了控制网络...
  • 学习内容:b站傅老师的U3D黑魂复刻课程 在角色下创建CameraHandle,将摄像机拖入 PlayerHandle控制水平旋转,CameraHandle控制竖直旋转 定义 public PlayerController pi; private GameObject playerHandle; ...
  • Unity3D 学习笔记

    2019-08-15 11:51:10
    Unity3D 学习笔记: Unity版本 2019.1.0f2 C#编辑器 Visual Studio 官方学习手册 博客干货: 新版Unity不再安装MonoDevelopment,可以自己设定脚本编辑器,参考:Unity3D使用VS作为脚本编辑(Unity3d与...
  • 保护资源管理文件的相关内容 Unity允许用户使用AssetBundle.CreateFromMemory从一个 byte[]数组中建立一个AssetBundle的对象。在运行传输解密时,可以用这种加密方法来提高安全性和保护用户建立的资源管理中的内容。...
1 2 3 4 5 ... 20
收藏数 4,102
精华内容 1,640