unity教程_unity3d教程 - CSDN
精华内容
参与话题
  • Unity3D游戏引擎最详尽基础教程

    万次阅读 2018-06-27 15:23:06
    我一直向所有想做游戏的朋友推荐Unity3D,为什么呢?首先是因为专业,Unity3D非常强大,用它创建一个类似MiniGore这样的3D平面射击游戏简直轻而易举,而就连使命召唤这样的大型3d游戏,如果素材得当也不在话下。二是...

    我一直向所有想做游戏的朋友推荐Unity3D,为什么呢?首先是因为专业,Unity3D非常强大,用它创建一个类似MiniGore这样的3D平面射击游戏简直轻而易举,而就连使命召唤这样的大型3d游戏,如果素材得当也不在话下。二是因为易用,他的操作非常容易,而使用的脚本语言又是JavaScript或者C#,不仅非常简单,也让各个种类的程序员都非常容易上手。再次,就是因为免费,如果你不使用Pro或者Mobile的内容的话,Unity3d就是完全免费的。还有就是对3D模型的兼容性,几乎任何3d模型都可以导入到unity中,可以说是一个很方便的特性。

     

    今天,我就来讲讲Unity3D的基础操作,这可以说是一个新手必读吧,读完之后,你一定会惊叹,原来做一个游戏这么简单。

     

    第一节 加入重力

     

    我们先打开Unity3d,新建一个场景(Scene),新建的时候应该会有对话框要求你加入哪些Asset Package,记得选择Physics Material,因为后面我们一定要用的哦亲。

     

    如果创建的时候没加,你可以再后来的Asset菜单里加:

     

     

    之后,我们建立一个Cude,调整一下x和z的大小,我这里调成了25,让它变成一个地板,你也可以放一个texture上去,看起来更加真实,我这里从简,再创建一个sphere,在component中选择Physics中的RigidBody,前提是选中你的sphere物体,之后会看到这个Sphere的inpector中加入一个component叫做RigidBody,调整好Camera运行一下,你就会发现Sphere受到重力的影响自动掉落到地板上。

     

     

    之后,通过我们之前引入的Physics Materials资源包,你还可以选择这个物体的物理性质,我这里选择Bouncy(跳跳),落下之后,这个物体就会蹦来蹦去的,呵呵

     

     

     

    第二节 检测碰撞

     

    下面我们通过简单的JavaScript语句来检测碰撞,这在制作游戏中是很有用的,比如说检测到子弹和敌人的碰撞之后,可以使用我们后来要讲到destory命令消灭敌人。

     

    这次我们新建一个Terrain项目,在用Grass贴图来覆盖住它,如果你找不到贴图的话,记得在Asset菜单里找找,看看哪些资源你还没有引入进去。

     

    然后再加入一个Cube项目,我这里叫做PlayerCube,为他加上重力,之后选择bouncy性质,然后我们再新建一个Cude,调整y和z的值让他变成一堵墙,放置好,命名为Wall,别忘了给Terrain改名为Terrain,

     

    之后我们在Asset菜单中建立一个JavaScript项目,改名为CollisionDetect,双击打开,如果你使用的是Unity 3.5的话,就会打开MonoDev,这是一个新工具还是很好用的,在其中新建一个函数,别管Start和Update函数,我们待会会讲。

     

    加入以下代码:

     

    function OnCollisionEnter(theCollision : Collision){
    
     
    
    if(theCollision.gameObject.name=="Terrain"){
    
     
    
    Debug.Log("Hit terrain");
    
     
    
    }else if(theCollision.gameObject.name=="Wall"){
    
     
    
    Debug.Log("Hit the wall");
    
     
    
    }
    
     
    
    }
    

     

    如果看不懂这些代码的话,也没关系,JavaScript是最好学的编程语言,Google一下吧,保存这个JS文件,然后拖到我们的PlayerCube上。

     

    这时候我们运行,就会看到PlayerCube到处蹦,碰到Terrain的时候,控制台就会显示Hit Terrain,碰到wall的时候就会显示Hit the wall。

     

    第三节  检测用户输入

     

    下面我们来讲一下如何检测用户的键盘和鼠标的操作。

     

    就用我们上次的那个场景,这次我们给PlayerCube加上我们可以控制的动作。就是通过“wasd”或者上下左右键来控制移动。

     

    请注意,如果要使用这里使用的方法来控制移动,那么所控制的物体不能够是一个物理世界的物体,也就是说你要把RigidBody这个component删掉,如果你想要在物理世界里移动物体的话,你就需要我们在下面会讲到的力(force)。

     

    首先我们新建一个JavaScript文件,这里命名为InputDetect吧,输入下面的代码:

     

    #pragma strict
    
     
    
    var Player : GameObject;
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    Player = GameObject.Find("PlayerCube");
    
     
    
    if(Input.GetKey(KeyCode.W)){
    
     
    
    Debug.Log("Hit w");
    
     
    
    Player.transform.Translate(Vector3.forward * 2);
    
     
    
    }else if(Input.GetKey(KeyCode.S)){
    
     
    
    Debug.Log("Hit s");
    
     
    
    Player.transform.Translate(Vector3.back * 2);
    
     
    
    }else if(Input.GetKey(KeyCode.A)){
    
     
    
    Debug.Log("Hit a");
    
     
    
    Player.transform.Translate(Vector3.left * 2);
    
     
    
    }else if(Input.GetKey(KeyCode.D)){
    
     
    
    Debug.Log("Hit d");
    
     
    
    Player.transform.Translate(Vector3.right * 2);
    
     
    
    }
    
     
    
     
    
    }
    

     

    这时,我们运行这个游戏,就可以通过“WASD”来控制PlayerCube的移动了。

     

     

    第四节 使用Prefab复制和控制物体

     

    我们可以直接把Prefab看做是个妈,她能生好多小孩,如果妈妈的DNA变了,小孩的跟着变,就是说你可以用Prefab创建物体,然后通过这个Prefab修改所有这类物体的性质,这对于批量生成的敌人或者NPC来说很有用。

     

    首先,先创建一个Prefab,我这里命名为“Mother”,之后新建一个Sphere物体,当然你也可以建一些其他的物体,之后给这个Sphere加上你想要的性质,我加入了RigidBody和Bouncy,之后将Sphere拖到Mother上,你会发现mother变蓝了,之后你就可以随意拖一些mother物体到屏幕上去,你会发现所有的Prefab创建出的物体在清单上都是蓝色的,说明他们都有共同的性质。

     

     

    当然,作用于一个Prefab上的脚本也会作用到它的子物体上去。

     

    第五节 使用Destroy命令消灭物体

     

    我们游戏中怎么能够没有敌人呢?有敌人就得能够消灭他们,这时候,我们就会使用Destroy命令了。

     

    在这里,我们使用上次Mother生出来的小球球作为敌银,一旦我们的PlayerCube碰撞到了小球的话,就是用Destroy让小球消失。

     

    新建一个JavaScript脚本,输入以下代码:

     

    #pragma strict
    
     
    
    var mother : GameObject;
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    }
    
     
    
    function OnCollisionEnter(theCollision : Collision){
    
     
    
    mother = GameObject.Find("Mother");
    
     
    
    if(theCollision.gameObject.name=="Mother"){
    
     
    
    Debug.Log("Hit mother");
    
     
    
    Destroy(mother);
    
     
    
    }
    
     
    
    }
    

     

    这段代码很好懂吧,就是检验碰撞,然后销毁碰撞到的Mother物体,别忘了把Destroy的JavaScript文件拖到PlayerCube上去。运行一下,就可以看到碰撞到的物体都被消灭了。

     

     

    第六节 使用Instantiate命令创造物体

     

    我们直接在界面创造的物体都只是会在界面被初始化的时候加载,那么,如果为了节约内存或者其他什么事情,我想要在游戏过程中添加物体,那该怎么办呢?你猜对了,就是用instantiate命令。

     

    这个命令就是英文实例化的意思,下面我们给碰撞之后消失的mother物体继续初始化一些,也就是说消灭了一些,又来了一大波···

     

    为什么非要用mother呢?因为只有拥有Prefab的物体才能够使用这个命令哦亲。

     

    function Update () {
    
     
    
    var instance : GameObject = Instantiate (PreFab,transform.position,transform.rotation);
    
     
    
    }
    

     

    注意:这样的话,每次刷新一帧都会出现一个新的mother物体,你的内存也许会受不了哦,更合理的方法是按下空格键,然后出现一个新的物体,你可以自己做吗?试试看

     

    你可能已经注意到了,每一个初始化的脚本都会默认有两个函数,就是:

    Update()函数 —— 每刷新一帧都会检查并执行

    Start()函数 —— 只在场景初始化的时候执行

     

    第七节 使用Timer计时器

     

    这次,我们要让一个计时器倒数,倒数到0的时候创建一个mother物体,来看Javascript代码吧:

     

    #pragma strict
    
     
    
    var myTimer : float = 5.0;
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    if (myTimer >= 0){
    
    myTimer -= Time.deltaTime;
    
    guiText.text=(""+myTimer);
    
    }
    
     
    
    if (myTimer <= 0){
    
    guiText.text = ("Done");
    
    }
    
     
    
    }
    

     

    把这个脚本拖到GUItext控件上,你会发现我们所期待的效果。

     

     

    第八节 让物体动起来

     

    其实让物体行动的技巧,我们已经会了,不是吗?

     

    如果你觉得不是的话,没有认真的看上面的文章哦,我就再给你讲一次吧。

     

    请特别注意,这种方法不适合物理世界的物体,如果向移动物理世界的物体,请看下一节:

     

    创建一个Cylinder物体,之后将下面的脚本附着在上面。

     

    #pragma strict
    
     
    
    var myObject : GameObject;
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    myObject.gameObject.Find("Cylinder");
    
    myObject.transform.Translate(Vector3(0,0,1));
    
     
    
    }
    

     

    第九节 使用物理世界的力

     

    这里是我们讲移动物体的重点,因为大部分的物体移动都是在物理世界完成的,而如果想要在物理世界移动东西,除了position和rotation的移动之外,就是使用“力”了,在高中学过经典物理学的人都知道,要使物体用移动,木有力是不行的,那么我们就开始吧,再新建一个什么物体,我新建了一个Capsule。

     

    之后,我会在这个物体的上方加一个力,让它用力的向下飞,触碰到地之后,通过bouncy这个性质再弹回来。新建一个JavaScript文件,就叫做Force吧,加入如下代码:

     

    #pragma strict
    
     
    
    var Power : float = 500.0;
    
     
    
    function Start () {
    
     
    
    rigidbody.AddForce(Vector3(0,Power,0));
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    }
    

     

    运行之后,会发现capsule其实是个很有幽默感的物体。

     

     

    第十节 使用贴图和材质

     

    贴图和材质能够使你的虚拟3D世界看起来更加真实,不幸的是,需要大量在PS和AI中的设计工作,最近我一想到要打开PS就有点烦···呜呜。

     

    闲话少说,我已经做好了一个贴图,怎么使用在材质上呢?之后我们怎么才能通过材质使用到其他物体之上呢?

     

     

    就像你看到的一样,我是直接拖进去的···

     

    之后我们从新建菜单中选择Material这一项,之后选中material,将贴图拖进material的贴图选框里,之后,就可以拖动这个Material赋给任何物体了。

     

     

    第十一节 使用声效和音乐

     

    音效和音乐对于一个游戏来说是非常重要的,一个寂静无声的世界是无聊的,而且不真实,什么?你说声效和音乐是一个东西?那你就错了,声效是,比如说发射子弹的声音,什么东西爆炸的声音等等,而音乐则是背景音乐什么的,不一样的亲。

     

    对于音乐来说,往往使用立体声音乐,而对于生效来说,我们随便使用一个简单的音乐文件就可以了。

     

    想要在Unity3D中播放音乐,你需要两样东西,一个是监听器,一个是音乐源,监听器是Camera的一个组件,所以你不用担心,你唯一需要增加的就是音乐源。

     

    直接将项目中的音乐拖放到Audio Source项就可以播放,但是如果我们想要在某个特定的点上 播放音乐该怎么办呢?答案就是,写一个脚本,新建一个脚本,输入如下代码:

     

    #pragma strict
    
     
    
    var myClip : AudioClip;
    
     
    
    function Start () {
    
     
    
    AudioSource.PlayClipAtPoint(myClip,transform.position);
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    }
    

     

    之后将这个脚本拖放到我们的物体上,最后,将音频文件拖放到AudioSource选项框中。

     

    第十二节 使用关节

     

    关节在3D游戏之中的应用非常广,主要在于物理世界的重力影响,下面我们就通过关节来制作一个钟摆。

     

    这次我们新建一个场景,松了一口气?刚才的场景是不是太乱了?你做的时候可以整理一下嘛,呵呵

     

    新建一个cube作为地面,之后一个cube放在上空作为摆垂,之后用几个capsule分别用component中的fixed joint连接起来,之后最上面的那个capsule与世界相连,使用Hinge Joint,这样的话,他会默认与世界相连,不用担心,看图

     

     

     

    第十三节 使用Axes

     

    在Edit – Project Setting – input 中可以查看各种形式的input,这些input方法在unity中被叫做Axes。

     

    我们创建一个JavaScript,叫做GetAxes,输入以下内容:

     

    #pragma strict
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    var Honriz : float = Input.GetAxis("Honrizontal");
    
     
    
    Debug.Log(Honriz);
    
     
    
    }
    

     

    在拖放脚本之后,运行这个场景,看看控制台输出了什么,你就明白了。

     

     

    第十四节 使用触发器

     

    触发器一般用于检测一个物体是否处于一个空间内,他是怎么做到的呢?

     

    首先,他创造一个大的物体,之后将他的randerer属性去掉,他就隐形了,这样,我们再把他的isCollide属性去掉,他就不会发生碰撞了,之后,我们只需要用脚本检测物体是否与这个物体碰撞就可以了。

     

    我们新建一个场景,做一个地板,再做一个底座,叠加起来,再在他们的上空做一个方块,设置rigidbody属性,将底座设置成为我们刚才说的那种隐形的状态,之后新建一个JavaScript脚本,输入代码

     

    #pragma strict
    
     
    
    function Start () {
    
     
    
    }
    
     
    
    function Update () {
    
     
    
    }
    
     
    
    function OnTriggerEnter (myTrigger : Collider) {
    
     
    
    if(myTrigger.gameObject.name == "box"){
    
    Debug.Log("Hit");
    
    }
    
     
    
    }
    

     

    按下运行,会发现可以检测出Hit。

     

     

    第十五节 使用GUI

     

    其实我们已经学过了如何使用GUI text,不信,我们就用屏幕上的字代替我们在上面的程序中的Debug.Log现实的内容。

     

    你自己能做吗?

     

    试试看吧,一个下午写了这么多,有点累。

     

    一定要在Unity中加入一个GUI Text,运行一下,就会发现屏幕上的GUI Text会随着你设定的的内容而变化了。

    失败是什么?没有什么,只是更走近成功一步;成功是什么?就是走过了所有通向失败的路,只剩下一条路,那就是成功的路。
    展开全文
  • 深入浅出Unity3D——第一篇

    万人学习 2015-02-05 09:58:48
    Unity3D基础知识、游戏算法一网打尽。
  • Unity教程学习

    千次阅读 2018-10-15 16:39:17
    学习Unity有一段时间了,最近有空闲,重头学习一遍教程,做下记录,仅以此篇纪念。 教程的学习主要以操作步骤和说明为主。

    教程1.Roll-a-ball

    需求说明:通过键盘输入控制,上下左右等按钮,控制小球移动。移动小球收集物体,统计分数。

    1).创建游戏

    1.1 新建项目

    打开unity页面,选择NEW,然后输入项目名,选择保存的位置,选择3D模式。
    创建新项目图

    1.2 新建场景

    左上方菜单栏File–New Scene,点击后,会再Hierarchy窗口看到一个场景,如下。
    新场景
    在上图蓝色选中条的右边的设置按钮,点击选择‘Save Scene As’,然后选择保存的位置并输入场景名称。保存完成后可在Project窗口中看到。
    保存的场景

    1.3 新建地面与配置Material

    菜单GameObject–3D Object–Plane,将会在场景里创建一个只有一个面的平面游戏对象,并修改名称(window平台F2)为Ground。选中该plane对象,在Inspector窗口中,Transform组件的右上方,齿轮按钮,选择Reset,这将会让Ground对象的位置等参数初始化。然后将Transform的Scale参数设置 X=2 Y=1 Z=2。注:plane对象的Y参数只分正负,正数是指向向Y轴正方向的一面可见,背面不可见,负数则相反。
    下面是设置Ground的显示效果,材质Material设置。
    新建文件夹(此不是必须的),Project窗口Create–Folder创建文件夹,重命名为Materials。
    Create–Material创建材质球,重命名为MatGround。选择该材质球,在Inspector窗口,点击MainMaps下的Albedo右边的颜色按钮,配置颜色为RGBA 0 32 64 255.
    配置颜色
    接下来为Ground设置材质球。
    方法一:选中Project下的MatGround材质球,按住拖动到Hierarchy下的Ground游戏对象上,之后Ground会变成我们设置的材质。
    方法二:选中Hierarchy下的Ground,在Inspector窗口的MeshRenderer组件上,有一个参数Materials,选中,设置其的Size为1,Element0参数设置,点击右边的小圆点,在列表中选择MatGround材质球。

    1.4 新建小球与重设位置

    Hierarchy窗口Create–3D Objec–Sphere创建一个球的游戏对象,重命名为Player,并Reset初始化。小球理应让其在地面之上,所以我们要设置小球的位置,不改变球的大小(Scale)。因为scale为(1,1,1),而地面位置为(0,0,0),让小球的最小面在地面之上,所以小球应该上移scale的Y的值的一半0.5。故设置position为(0,0.5,0)。

    2).小球的移动控制

    玩家控制小球在游戏区域内移动,碰到墙壁后不会跑出去,不会飞出去,碰到收集的物体,能收集物体。可以运用unity的物理系统,将用户的输入信息转换到小球控制上。

    2.1添加rigidbody

    Hierarchy窗口选中Player游戏对象,在Inspector窗口,最下方AddComponent–Physics–Rigidbody,添加刚体组件,因为对象已经有Collider组件(SphereCollider),可以触发物理碰撞等。

    2.2添加控制脚本

    同样的操作AddCmponent–New Script在弹出的小窗口输入自定义的脚本名称PlayerCtr,选择下方的Create and Add,等新脚本创建后,新建一个文件夹Scritps,然后将PlayerCtr脚本移动到文件夹下,方便控制。
    添加新脚本

    2.3小球移动控制

    双击PlayerCtr脚本打开编辑,建议使用visualStudio打开,设置请自行上网查找。

    2.3.1输入控制

    获取用户输入信息,因为我们只需要在平面上移动,所以我们只控制前后左右,上下不做控制。

    float moveHorizontal = Input.GetAxis("Horizontal");
    float moveVertical = Input.GetAxis("Vertical");
    

    Input是Unity的输入系统,关于调用的方法,可以通过visualStudio的联想和unity说明文档查找。GetAxis(string axisName)方法,参数是名称,名称可以在Unity的InputManager中查看,可从以下路径进入,菜单Edit–Project Settings–Input,会在Inspector窗口里显示InputManager设置面板。
    moveHorizontal 是水平左右输入值,正表示右,负表示左。
    moveVertical是水平前后输入值,正表示前,负表示后。

    2.3.2刚体控制

    小球移动运用unity物理系统,所以我们通过控制rigidbody,来实现控制小球移动。需要在我们的脚本PlayerCtr中获取刚体组件,对刚体组件操作,可通过查找文档来确定rigidbody调用的方法。

    2.3.2.1 获取刚体组件

    生成的脚本PlayerCtr继承至MonoBehaviour,存在Start(),Update()方法,这些方法可通过查找MonoBehaviour生命周期了解其调用,触发机制和前后顺序。
    在这里插入图片描述
    Start()为脚本调用的第一帧,只会执行一次,我们可以在Start里获取刚体组件。由于后面每一帧都要对刚体进行操作,把刚体变量声明成成员变量是最好的选择。

    private Rigidbody RigPlayer;
    

    在Start()中获取组件并赋值

    void Start ()
    {
      RigPlayer = GetComponent<Rigidbody>();
    }
    
    2.3.2.2 刚体运动控制

    每一帧都要对刚体进行控制,控制代码放在Update(),或FixedUpdate()中,其中FixedUpdate()适用于物理体系的调用,所以把刚体控制代码放在FixedUpdate()中。
    刚体的运动,是给刚体施加推力,查阅可得方法AddForce(Vector3 force, ForceMode mode = ForceMode.Force),或者public void AddForce(float x, float y, float z, ForceMode mode = ForceMode.Force)。
    采用前一个,Vector3是3维向量,因为我们用户只有输入左右前后,所以,我们改变x和z,y始终为0,即竖直方向上不给施加额外的推力(rigidbody本身可以设置是否有重力)。同样Vector3我们也可以把它独立成成员变量。

    private Vector3 VecDirec = Vector3.zero;
    
    private void FixedUpdate()
        {
            float moveHorizontal = Input.GetAxis("Horizontal");
            float moveVertical = Input.GetAxis("Vertical");
            VecDirec.x = moveHorizontal;
            VecDirec.z = moveVertical;
            RigPlayer.AddForce(VecDirec);
        }
    

    Play模式测试,会发现运行速度不行,不满足,那我们就需要调整vector3的x和z的值,通过给其一个倍数来控制,为了方便修改,这个倍数用public的成员变量来设置,这样可以在Inspector可视化修改其值。修改后如下。

    public float Speed;
    
    private void FixedUpdate()
    {
       float moveHorizontal = Input.GetAxis("Horizontal");
       float moveVertical = Input.GetAxis("Vertical");
       VecDirec.x = moveHorizontal*Speed;
       VecDirec.z = moveVertical*Speed;
       RigPlayer.AddForce(VecDirec);
    }
    

    可视化修改值
    到此,小球的移动控制已经完成。

    3).相机跟随

    场景里有个MainCamera游戏对象,其上挂着Camera组件,这是用户看到的画面效果,也就是Game中的效果,我们需要让镜头跟随小球移动。
    先调整MainCamera的位置角度,position设置为(0,10,0),旋转设置Rotation为(45,0,0)。
    处理方法一,不是合理的方法,但可以提供一个思路,把MainCamera对象拖动到Player小球对象下面,让其依附于小球。但是从Play模式下会发现问题,小球旋转,镜头跟着旋转,这样完成找不到方向。毫无体验感可言。我们的需求只是镜头跟随小球移动,但是镜头不做旋转。所以MainCamrera还是独立,给其添加一个控制脚本来实现该跟随功能。
    选中MainCamera游戏对象,AddComponent–New Script输入新脚本名称CameraCtr,将新脚本移至Scripts文件夹,打开编辑。
    初始化时先获取方向

    	/// <summary>
        /// 小球Player的Transform
        /// </summary>
        public Transform TraPlayer;
        private Vector3 offset;
    	// Use this for initialization
    	void Start () {
            offset = transform.position - TraPlayer.position;
    	}
    

    然后每一帧更新MainCamera的位置,对相机的操作,代码应该放在LateUpdate中。

    private void LateUpdate()
        {
            transform.position = TraPlayer.position + offset;
        }
    

    记得将Player小球挂载到MainCamera对象的脚本的的TraPlayer参数上(在MainCamera对象的Inspector窗口)。

    4).创建游戏区域

    需要4面墙壁来挡住小球,防止小球跑出地面区域,为了方便管理,先创建一个空游戏对象并初始化位置,重命名为Wall。
    Create–Create Empty,在Inspector中Transform进行Reset,F2重命名。
    墙壁总控制
    创建第一个墙壁,Create–3D Object–Cube,初始化位置后,设置scale为(0.5,2,20.5),这是左右墙的设置,重命名为EastwardWall。接下来再Scene视图中,选中该墙壁,选择菜单栏下的第二个按钮,将墙壁移动到合适位置,最后在微调Position为(10,0,0)。把该墙壁移到Wall对象下面。
    方向按钮
    复制墙壁对象(菜单Edit–Duplicate或者选中墙壁,快捷键ctrl+D),修改名称,移动,修改数值,最终形成合围的4面墙,统一放在Wall对象下管理。注意,前后墙壁可以通过改变Rotation的Y为90实现旋转。
    墙壁效果图
    由于该游戏中,地板和墙壁都是不会动态改变移动,旋转,拉伸的,所以可以设置为静态,以地面为例,选中Ground对象,在Inspector页面,右上方有个static勾选按钮,勾选。或者在其下拉中选择需要的静态选项。
    静态勾选

    5).收集对象

    5.1创建收集预制品

    收集对象要让用户感觉到,要与其他的做区别,怎么突出显示呢?在不考虑性能情况下,要突显出来。一是收集物设置成运动的,二是颜色区别。
    创建收集物体的游戏对象。Create–3D Object–Cube,初始化Reset,重命名为Collection。设置位置,使其悬空,高于地面。设置角度,使其倾斜(45,45,45)。
    设置成运动状态。添加一个新脚本RotationCtr,因为没有物理力的作用,所以在Update里更新旋转角度。

     private Vector3 VecRot = new Vector3(15, 30, 45);
     void Update () {
            transform.Rotate(VecRot*Time.deltaTime);
    	}
    

    为了让其平滑的运动,每一帧运动的角度要跟每一帧的时间做处理。Time.deltaTime是上一帧到这一帧的时间。
    颜色处理。收集物体要跟地面,墙壁,小球做区分,所以最好用不同颜色处理。直接复制原来的地面的材质球,新的材质球更改颜色,在给收集物添加该材质。
    收集物体
    做成预制品保存,进行复用。在Project窗口新建文件夹Prefabs,然后将Collection收集物体对象拖动到Prefabs文件夹下,这样就会形成一个收集物预制品。复制收集物,调整位置,形成一个圆。

    5.2收集物体

    小球碰到收集物后,收集物被收集,则要从镜头里消失。涉及几点,一碰撞检测,二收集物体的消失控制。

    5.2.1碰撞检测

    基于unity的物理系统,碰撞检测是通过rigidbody和collider碰撞器检测的。从之前情况看到,小球碰到收集物会被弹开,但是我们需要的是碰到收集物体后,不会影响小球原先的运动,所以在收集物的碰撞器我们需要做额外处理,让其有碰撞的基础,同时又不触发物理碰撞。
    其实这就是将碰撞器变成触发器,将BoxCollider上的IsTrigger勾选上,这样该对象就变成一个触发器,不会发生物理的碰撞反弹之类的效果。另外,地板,墙壁之类的一定时碰撞器不是触发器。
    触发器

    5.2.2收集物的消失控制

    IsTrigger勾选后,变成触发器,我们需要获取触发器被触发的情况,这个可以在小球的脚本上去控制,因为小球挂了rigidbody,小球碰到触发器,会在其下的脚本调用有关触发器的方法,下面这几个是3D 触发器触发的方法,分别是进入触发器时调用,离开触发器时调用,处在触发器中调用且只要在触发器中,会一直调用。

    	private void OnTriggerEnter(Collider other)
        {}
        private void OnTriggerExit(Collider other)
        {}
        private void OnTriggerStay(Collider other)
        {}
    

    因为我们在一接触就要让收集物体消失,所以需要Enter的方法。还需要考虑一个,如果又多种触发器,我们怎么区分时碰撞到哪一种,解决方法是,给触发器的游戏对象加上Tag标签,通过对比tag来区分。
    tag标签
    最后是消失控制,如上图,tag标签上面是游戏对象的名称还有一个勾选,勾选状态就是对象的显示控制。选中,该对象就是显示状态,不选中,就是消失,隐藏状态。
    整理一下,就是在小球脚本上对private void OnTriggerEnter(Collider other)方法里处理。其中参数other是小球接触到的触发器,通过other对比tag,方法是Component上的CompareTag(参数)参数是tag的字符串。对符合要求的other,执行消失操作。也就是调用GameObject的SetActive方法。代码如下。

    private void OnTriggerEnter(Collider other)
        {
            if(other.CompareTag("Collection"))
            {
                other.gameObject.SetActive(false);
            }
        }
    

    另外,页面上需要做一些处理,新增触发的tag,为收集物体的预制品添加tag。
    新增。任意选中一个游戏对象,点击Tag的名称,再下拉菜单中点击Add Tag。。。在tag页面中点击+,新增一个tag,输入新增的名称。
    新增Tag
    在收集物体预制品上,同样点击tag名称,下拉菜单选择刚才新增的tag,注意这个名称要跟脚本的的CompareTag的参数是一样的。

    5.2.3物理性能优化

    unity的物理系统,对动态和静态的性能消耗是又差别的。动态的物理对象是添加了Collider和rigidbody的游戏对象,静态的是添加了Collider,没有rigidbody且一直在改变(位置,选择,大小拉伸)的游戏对象。
    收集的物体对象一直在旋转,但它是静态的,性能上,静态的会将一些信息保存到缓存中,由于一直在运动,所以每一帧都要将信息重新缓存到缓存里,这会造成额外的性能开销。因为动态的,信息一直在动态更新,不会做缓存。为了减少这部分缓存性能开销,我们要把静态的设定,改成动态的。
    改成动态的,最简单的是为这些收集物体增加rigidbody,并修改rigidbody的一些设置,使其不会有物理属性,而是作为触发器存在。
    方法一:取消rigidbody的UseGravity,这样作为触发器的收集物体就不会因为重力而往下掉落,因为是触发器,会穿过地面。但是这个设置还是会收到物理力的影响。
    方法二:勾选IsKinematic,这样物体会变成动态的,不受物理力影响,但是其形状大小等改变之类的,受到脚本影响。通过脚本修改Transform或动画等控制。
    至此游戏控制基本完成,剩下分数统计之类的其余功能。

    6).分数统计胜利提示

    收集了物体后,需要对分数进行统计并显示,全部收集完成后,显示胜利。

    6.1分数统计与显示

    在Player上的PlayerCtr脚本里对收集的分数进行统计。
    声明并初始化。

    private int count = 0;
    

    收集到物体后,增加分数,最简单处理,一个收集物体增加1。

    private void OnTriggerEnter(Collider other)
        {
            if(other.CompareTag("Collection"))
            {
                other.gameObject.SetActive(false);
                ++count;
            }
        }
    

    分数显示,在Hierarchy窗口,Create–UI–Text。会创建三个对象,Canvas是存放UI的父对象,EventSystem是UI的事件系统。还有一个Text是文本UI。我们把分数放到左上角显示。
    首先颜色改为白色。
    字体颜色设置
    位置设置到左上方,并留一定边距。
    在这里插入图片描述
    将文字内容删除。然后再脚本里初始化和显示文字。在PlayerCtr显示设置共有变量。记的要将Text对象拖动到改变量上,挂载上去。

    public Text TxtCount;
    

    初始化。

    TxtCount.text = "count:" + Count.ToString();
    

    在收集到收集物体后,更新显示内容,因为代码一样,可以抽离出来,处理成独立的方法。在初始化和更新分数时调用该方法。

    public void SetCountText()
        {
            TxtCount.text = "count:" + Count.ToString();
        }
    

    6.2胜利显示

    在所有收集物体被收集完成后,显示胜利。这需要另外一个文本显示。操作类型,新建Text,设置位置,颜色大小等,脚本控制初始化和胜利显示。

    TxtWin.text = string.Empty;
    

    在收集触发方法里,更新胜利显示。

    if(Count>=12)
    {
       TxtWin.text = "You Win!";
    }
    

    功能脚本代码如下

    	private int Count = 0;
    	public Text TxtCount;
    	public Text TxtWin;
    	// Use this for initialization
    	void Start () {
            RigPlayer = GetComponent<Rigidbody>();
            SetCountText();
            TxtWin.text = string.Empty;
    
        }
        private void OnTriggerEnter(Collider other)
        {
            if(other.CompareTag("Collection"))
            {
                other.gameObject.SetActive(false);
                ++Count;
                SetCountText();
            }
        }
        public void SetCountText()
        {
            TxtCount.text = "count:" + Count.ToString();
            if(Count>=12)
            {
                TxtWin.text = "You Win!";
            }
        }
    

    注:代码编写完成,记得把对象挂载到对应变量上。

    7).打包

    菜单File–Build Setttings在页面里点击AddOpenScene或者把目标场景拖到上部的框里,下面根据需求选择平台。各个平台需要设置一些基础信息,请自行查找。

    展开全文
  • Unity3D入门教程中文版

    2018-08-02 17:28:01
    适合unit3d新手入门,pdf文件,中文版,图文并解,仅供参考
  • Unity3D官方教程爬坑

    万次阅读 2017-03-29 02:18:13
    同时会添加到处学来的的Unity技巧 ---------------------------------------------------------- 代码: 1.使游戏对象运动的N种方式 更全面的移动方式参考 1、rigidbody.addforce(Vector3 * speed) (见roll...

     

     

    全是在学官教时遇到的坑,然后数小时后爬出来.同时会添加到处学来的的Unity技巧

    ----------------------------------------------------------

    代码:

     

    1.使游戏对象运动的N种方式

     

    更全面的移动方式参考

    1、rigidbody.addforce(Vector3 * speed) (见roll-a-ball)

    2、rigidbody.velocity(vector3 * speed);(见space shooter,改变位置向量,非常的生硬)


    3、rigidbody.MovePositon(vector 3) & rigidbody.MoveRotation(quaternion)(包含移动和转向,细腻,常用。见survival shooter player的移动)(转向包括光标指向转向,和键盘输入转向(见Tanks!))

     

    4、transform.translate(方向 * 速度 * Time.deltatime)

    见survival shooter内敌人被消灭后下沉并回收

     

    MoveTowards vs. Lerp vs. Slerp vs. SmoothDamp

     

     

    2.镜头跟随移动游戏对象移动,脚本内用LateUpdate()而非FixedUpdate()(见roll-a-balll)

     

    3.Random.Range(min,max),如果两个数都是float则前后都算,如果两个数是int则包前不包后

     

    4.FindObjectOfType<Inventory>()  vs  GetComponent<Inventory>()

     

    FindObjectOfType①为外部调用,在所有场景和游戏对象里找,不是很快;通常放在Start()内。

    GetComponent②为内部调用,只在挂着该脚本的游戏对象上的其他组件找,他们都在一个inspector里,比如rigidbody,renderer,collider等。

    ②替代①的方式是给脚本所在的对象选择tag,再用【FindGameObjectWithTag("tag的名字“).GetComponent<脚本>()】放入Awake()内。

    也可以直接 在脚本开头public Inventory inventory; 然后在inspecotor界面把挂着Inventory脚本的游戏对象拖入框。[Adventure Game]

     

    5.Debug

     

    在space shooter中,行星在游戏界面内存在,运行尝试是否子弹能消除时发现行星不见了,这时候在行星的脚本里加了一段“Debug.Log(other.name)”把将行星摧毁的物体的名称发送到了unity的console内。

    6.coroutine

    在土豆视频内spaceshoot官方教程中行星波生成里解释的很清楚(因为有中文字幕)。coroutine就是等某一段或几段设定好的时间后循环方法内的代码。

    调用这种异步(即有时间间隔)的方法要用语句 startCoroutine (方法()); 。含异步的方法要用IEnumerator来代替void,yield return new WaitForSecond(设定好的时间);是指等这段时间后继续循环,写在for语句内表示等N秒后i++,写在循环前表示等N秒后开始while循环(把for循环放入while循环内,判断条件可以按需求写,在 space shooter里想要的是行星不停出直到飞船被毁为止,所以判断条件写的是true(意思是true就是true,一直循环),再在while循环的末尾加上for循环的间隔)。

     

    关于yield return,这篇文章就说的很清楚了:http://www.cnblogs.com/wangchengfeng/p/3724377.html

    7.游戏对象的回收(包括落下的行星,行星被射击时的爆炸效果)

    在space shooter内行星和飞行的子弹靠的是外置一个boundary(cube,box collider)并用脚本(onTriggerExit)来回收游戏对象。

    但行星的爆炸特效并不与boundary碰撞,所以会冗余。在所有爆炸特效下挂载脚本在void start内用Destroy(gameObject, 设定的时间);语句使每帧检测超过设定的时间后被挂载的游戏对象销毁,在survival shooter内对敌人的回收也是如此(先下沉,下沉N秒后摧毁)。

     

    8.unity内脚本的实例化关系

    见space shooter内计分板的讲解,即在脚本内写一个public的方法,要在其他脚本内调用要先指定是要调用脚本的哪个实例(即使在只有一个实例的情况下)。

     

     

    9.Input.GetAxisRaw(); vs Input.GetAxis ();

    Raw是指非平滑输入,即输入值只有-1,0,1(左,无输入,右)。这种输入的作用让角色单位输入变小,在操作感官上更有灵敏性,角色反应更快更流畅。(见survival shooter内Player的移动)


    10.Time.time vs Time.deltaTime

    Time.time是游戏从开始到此刻的持续时间

    Time.deltaTime是游戏上一帧的持续时间(增量时间),每一帧完成的秒数都不同,所以在需要固定增量时(比如每秒移动10,每0.5秒攻击一次),要在数值上乘以Time.deltaTime(即单位),否则将变成(每帧移动10,每帧攻击2次)

     

    11.在脚本实例(A)内引用其他脚本实例(B)内方法

    【】如果A和B脚本实例都挂在同一对象上(比如survival shooter的敌人上同时挂载Enemy Health和Enemy Attack),则在A内private EnemyAttack enemyAttack;
    然后在Awake()内  enemyAttack = GetComponent<EnemyAttack> ();就可以直接调用了。

    【】如果A和B在不同对象上(比如survival shooter的Enmey Attack和Player Health)则在A内private PlayerHealth playerHealth;

    然后在Awake()内先要player = GameObject.FindGameObjectWithTag<"Player">();找到挂B脚本的对象(该对象必须添加“Player”的Tag)。

    然后再playerHealth = player.GetComponent<PlayerHealth>();,才可调用。

     

    如果是在场景里的GameObject上挂的脚本则可直接Public GameObject xx; 然后在Inspector里拖入。但如果是存成Prefab的的游戏对象上挂的脚本,引用方式必须是上面通过Tag寻找,而且要注意脚本加载顺序找不到引用报错。

    还有一种见Adventure Game(仅用于Editor继承),下面的target是Editor特有的字段,表示该Editor的对象,第二个红框里的句子只是把target转换成了ConditionCollection类型,在这之前target仅仅是个Object类型不明

     

    【】如果B在A的子对象上(比如survival shooter的PlayerShooting挂在游戏对象Player的子对象GunBarrelEnd上),在A内引用B的则private PlayerShooting playerShooting;

    然后在Awake内playerShooting = GetComponentInChildren<PlayerShooting>();

    【】还有一种情况,玩家开枪射击敌人,使敌人生命值降低。player下的游戏对象枪上所挂的脚本PlayerShooting要引用某个敌人上的EnemyHealth来调用生命值降低方法。

    则以射线碰撞Raycast,撞到层为“shootable”后返回碰撞点信息,在信息点上再找其脚本实例。(见survival shoot的playershooting脚本)

    【】如果一个变量声明方式为public static xx(类型) xx(名称),则在其他脚本内调用不用先声明上面的那一套,直接使用就是。(一般用于分数等不可改元素)

    【】游戏内的GameController,SoundController,DataBase等都可以直接在场景里建同名空对象,挂上对应的脚本,设置他们用单例在Awake里加载比较不容易出错。特别是在不同对象在不同场景里无法拖拽引用的情况(见Quiz Game)

     

    【】上面说到trigger可以探测是否挂载特定脚本(EnemyHealth)来判断是否是指定对象(Enemy)。

    比如在GameGrind装备系统教程里装备叠加方法中,就用到指定格子下装备上的脚本

     

    那如果要更新该装备下的Text呢,则是该脚本.transform就指代该脚本所在的游戏对象。

     

     


    12.脚本头的“using ...”(见2D Roguelike 4内BoardManager蛮牛)

    using System; 这样就可以在脚本里使用Serializable属性。Serializable可以让变量在Inspector里展开或收起。

    using System.Collections.Generic;,这样可以使用List

    using Random = UnityEngine.Random; 因为系统和unity引擎都有 Random的命名空间。

    using UnityEngine.EventSystem; 为了使用Eventsystem的功能,比如在背包拖拽装备(见装备系统)

    using System.IO; 为了查找加载文件,比如LitJson(见装备系统)

     

    13.将脚本里的Public属性隐藏,或显示Private属性

    有时一些Public属性我们需要在其他脚本调用,但已经调整好了,不想再Inspector内显示

    可以在脚本内该属性的上一行加上【HideInInspector】该属性将不会再Inspector面板内显示

    显示private属性则在属性上方加上【SerializeField】。

    如果不想加语句直接想看到一个脚本内的所有变量并调试,Unity有Debug模式,会显示该游戏对象的所有隐藏组件,包括其脚本的所有属性。Inspector面板右上角选择Debug就好了。

     

    14.脚本内代码分块

    有时候代码很长,想分块代码并收起以方便查看,可在想收起的代码块上一行写  #region 代码块名称,结尾写#endregion。

     

     

    15.for,switch循环和while,if等自动补全代码格式

    比如for循环 for(int i =0; i <`````),可以打下for后按两下Tab键系统自动补齐格式

     

    16.脚本内引用工程项目内文件的路径变动问题

    在装备系统教程里,我们引用了记录了装备信息Json的文件,如果打包游戏的话会发现游戏无法正常读取该文件,是因为随着打包文件,Json文件的路径也会变化,这时候把该文件放在一个Unity规定的特定文件夹,并用其他语句引用。

    具体参见Unity Manual:Streaming Assets页面

     

     

    17.脚本内注释每个字段并在unity Inspector上悬停显示字段

    参数字段太多了不知道什么意思,在声明句上加上[Tooltip(“XX”)],在unity内鼠标停在该属性上出现注释

     

    18.让Unity 内的Button变灰不能摁

    用Button.Interactable = false;

     

    19.代码内引用其他GameObject的方法(Find & FindWithTag)

    Unity里有3种引用方式

    Find 和 FindWithTag都需要该GameObject必须时active的。

    1.比如点击Button弹出一个界面,这个界面在平时是隐藏的。

    操作方法是:在Unity里该界面Active,然后在Start()或Awake()里用Find或FindWithTag找到然后再SetActive(false),然后就可以使用了。

    Find是在所有Active的游戏对象里找,FindWithTag是在所有标签对象里找,所以FindWithTag效率更高,官方不建议在Update()里使用Find因为太耗性能。

    2.再比如经常要检测其他对象,比如trigger里的是Enemy还是其他的东西。

    这时候除了给Enemy标上Tag,检测other.tag == "Enemy"之外,还有一种方法是if(!other.GetComponent<EnemyHealth>())通过检测trigger物上有没有指定脚本来判断是否是制定物。

     

    20.脚本内比较字符串大小

    可直接使用if(str1 == str2)或 if(str1.Equals(str2)) 

    注意string是区分大小写的,我在比较后List元素Add,不停跳出索引有问题的Bug。花了2个半小时才找到原来是str1的首字母时大写的,str2的首字母小写,结果全是false导致没有任何元素添加进List。

     

    21.List清除元素/查找元素/查看是否包含元素

    List.Clear(); 清除List内的所有元素,保持List的基本属性(比如List<Enemy> enemy清空后没有元素,但属性仍然是<Enemy>)。

    List.Remove(xxx); 清除xxx表达式满足的所有元素,比如删除一个List<int>内为偶数的所有元素:

     

    参考:http://blog.csdn.net/yl2isoft/article/details/17059093

     

    参考:https://msdn.microsoft.com/en-us/library/wdka673a(v=vs.110).aspx

    List.Find(xx)

    如果找到该语句要求的元素则返回该元素,如果没找到则返回的是该元素类型的默认值,而不是null。参考

    List.Contains()

    如果找到返回true,其他情况返回false。参考

    List.FindIndex(xx)

    如果找到该语句要求的元素则返回该元素的的索引,否则返回-1。参考

    List的用法 参考

     

    22. console提示:NullReferenceException: Object reference not set to an instance of an object

    意思为没有引用.

    一种可能是该脚本A引用条目本体所在的脚本B,的执行速度要快,所以造成没有引用。这时候调整脚本执行顺序就好。

    另一种可能是该Object本体就在该脚本,那么在脚本初始声明该Object时没有初始化。

    (比如把PlayerData playerData = new PlayerData()里后面的初始化语句忘了就会出现上述BUG)

    还有一种可能是Prefab在面板上未Apply,比如Prefab GameManager要拖拽引用 DataManager,DataManager必须也存成Prefab,然后把作为Prefab的DataManager拖入才算是引用成功。如果在Hierarchy下的DataManager新增了脚本却忘记Apply,则Prefab DataManager没有挂载新脚本,GameManager在运行时就找不到该脚本而报错。

     

    23.Destory DontDestoryOnLoad GameObject

    GameManager通常是DontDestoryOnLoad的,比如Roguelike里就一直存在。那如果想从某一场景切换到另一场景时会发现原先场景的GameManager还是存在,这时候要删除该GameManager GameObject有两种方式:

    参考

    1.

     

    2.

     

    不过图中的处理不是太好,应该在GameManager 对象所挂的脚本上,写入上面的代理。而代理的启用&取消通常在OnEnable() & OnDisable()里,代理必须取消,否则将导致内存泄漏。

    关于delegates和C#内Events的说明见Adventure Game教程。教程

     

    24.Unity内的双击

    using UnityEngine;  
    using UnityEngine.UI;  
    using UnityEngine.EventSystems;  
      
    public class MJCard : MonoBehaviour,IPointerClickHandler {  
      
        float lastClickTime;  //不要申明在方法内
     
        public void OnPointerClick(PointerEventData eventData)  
        {    
            if (Time.time - lastClickTime < 0.2)  
            {  
                Debug.log("双击");  
            }  
           lastClickTime = Time.time;  
        }

     

     

     

    25.点击框外区域关闭对话框(Popup)

    要点击对话框Child外区域关闭Child的最简单办法:新建一个Panel命名为Parent,拉伸到全屏,设为透明,把child拉为子对象。然后在该Parent上挂脚本

     

    点击透明Panel就会关闭子对象。

     

    26.物体抛物线移动

     

    27.怎样修改Image的alpha

    不可以直接image.color.a进行修改,会提示无法转换,必须中转一下。

     

     

    28.怎样使对象在移动时转向(比如在2D里)

    一般向左向右都是改scale,比如原本向右的改为向左就把scale.x改为-1,移动的时候改transform.localscale。

    但这一项不可以直接修改,而是要像image.color.a一样中转一下。

     

     

    参考:https://www.youtube.com/watch?v=e7I315b74HY

     

    29.怎样平滑的在N秒内填充slider

     

     

     

    30.用MD5加密资料的方法

     

     

    参考来源

     

     

     

    31.Unity中渐隐/闪烁/淡出的实现

    参考(渐隐/闪烁)

    淡出

     

    32.Unity内加载(Load)资源

    比如加载image的对象Sprite,一般我们的资源都放在Resourses文件夹(注意,一定是复数形式),用Resources.Load<你要加载的形式,比如Sprite>(“该文件在Resources文件夹下的路径”)就好了。

    官方API 额外的参考 打包时的资源加载问题

     

    33.Unity修改transform.rotation的两种方法

    transform.localPosition和transform.localScale都是直接赋值三元数,给旋转赋值需要用 
      方法一: 
      xxx.transform.localEulerAngles = new Vector3 (0.0f,0.0f,0.0f); 
      方法二: 
       xxx.transform.rotation=Quaternion.Euler(0.0f,0.0f,0.0f);
    参考

     

    34.Json内中文为解析后为乱码的解决

    json文件一般都是用记事本打开的,打开后另存为选择编码方式为UTF-8保存并覆盖就可以显示了。参考

     

    35.Unity点击鼠标移动2d对象并播放移动动画

    移动

     

    动画播放

     

    两个方法在FixedUpdate内执行就好。

    注意先把对象的世界坐标转换,计算偏移量后再换回。

    还有就是应使用GetMouseButton() 而非GetMouseButtonDown(),因为如果鼠标长按而不是点击的话GetMouseButtonDown()在之后帧都返回false。

     

    36.Unity内的数据保存路径

    参考来源

     

    37.引用其他脚本内函数避开次次实例化的方法

    ① roguelike官教里的fightmanager方法

     

    ② 和第一种很像,使用T.GetInstance().xxxxxx来使用

     

    ③ 一次性读取数据(不需要写入的情况),然后直接调用

     

    38.Unity内拖拽UI和物体

    参考

    ① 拖拽overlay模式下的ui

     

    ② 拖拽世界坐标/camera模式下的UI元素

    还有在鼠标点显示信息框等也是先把Input.mouseposition用上面的方法转换后再定位。

    悬停框所在的像素显示之前在overlay模式下设置的是100,在camera模式下会很模糊,改为小数(比如1或者2)。

     

    ③ 拖拽3d物体

    见上面参考链接

     

    39.UI元素显示在最上

    overlay永远存在于最上(离屏幕最近),多个overlay的层级取决于sort layer。sort layer越大越上。参考

    camera取决于plane distance(canvas所在平面离摄像机的距离,可存在于其他gameobject后),sorting layer(多个camera模式的canvas用此排序),order in layer(多个canvas在同一sorting layer时的排序)。

     

    平常的overlay canvas想暂时在camera canvas后显示时,可直接gameobject.setActive(false),之后再设置为true。

    overlay模式下的joystick则不可以,等setactive true后因为要注册horizontal和vertical导致joystick不能用。暂时的方式是先把该joystick设置为camera并指定camera。之后恢复为overlay模式。

     

     

    40.移动端触屏修改

    使用官方joystick组件的(比如player移动)则在电脑端移动端都可使用。

    电脑端的点击,双击,拖拽等事件在移动端依旧可以使用(电脑端的左键相当于移动端的触摸点击)。

    长按则可利用IPointerDownHandler 和 IPointerUpHandler 参考

     

    41.ios获得设备标识码(UDID)

    自己机器的UDID可以通过连接iTunes获得,但代码SystemInfo.deviceUniqueIdentifier 在ios7之后获得的是UIDevice identifierForVendor(unity API)。参考链接

     

    所以单机使用该条就够了,联机则参考

     

    42.

     

     

     

     

     

    Unity:

    1.无法创建新项目,重启Unity,或者重新登录Unity账号。

     

    2.打包发布时,Build Settings 提示”Because you are not a member of this project this build will not access Unity services.”,重启Unity,或者重新登录Unity账号。

     

     

    3.2D游戏更改整体背景大小,不要设置背景的Scale,设置摄像机的Size。

    4.Console提示

    保存了脚本回到unity发现提示“There are inconsistent line endings in the 'Assets/Scripts/CameraController.cs' script. Some are Mac OS X (UNIX) and some are Windows.”?,点击VS下File→Advanced Save Options→Line Endings选择Windows(CR LF),确定后再保存一遍OK了。

    或者在VS内先关闭这个script,再在File下“最近使用过的文件”打开该script,VS会跳出对话框,YES后再保存一遍就好。

     

    5.碰撞器(Collider)判断

    是否有接触的条件是两方都有碰撞器,且至少一方有rigidbody组件。如果任何一方勾选了Is Trigger(勾选这个的是被碰撞对象,比如小方块被碰撞后消失,则勾选小方块,而不是小球),可触发检测是否进入碰撞范围,并按脚本对应表现。所以双方都没勾选触发,可碰撞,不可有其他交互。

     

    6.盒子内的碰撞

    要一个平面上的球不滚出平面,直接为平面加Box Collider是不可行的,球滚到边缘会直接粘到平面外缘不动了。自身多个碰撞器重叠如果有一个以上未勾选Istrigger会把重叠部分处理成一体。所以要在平面四条边放四个条状碰撞器粘成一个框状的。[2D  UFO]

     

    7.2d模式下所有动的游戏对象(即使只是旋转,不移动)也要添加rigidbody2D

    不然尽管挂上脚本不添加rigidbody也可以移动,但是unity每一帧都会重新定位加载计算该对象,会对性能产生极大损耗。[2D UFO]

     

    8.Rigidbody.isKinematic

    在脚本和rigidbody组件内选项使用。对象选择Kinematic后,碰撞、力、关节不再对对象产生影响。该对象的移动或运动将完全由Animation(动画)控制或者脚本编辑对象的位置改变来控制。(2D Roguelike,不想player满场乱飞,就是一步一移动,所以用这个。之前的SpaceShooter,RollABall等没有勾选此选项,即默认的Dynamic。Static是将对象设为像背景一样的物件,不可移动不可受力,但是可以和其他dynamic物体碰撞)

     

    9.unity中的sprite(精灵)

    unity2D游戏中的所有对象都叫精灵(比如2D Roguelike中的Player,Enemy,以及Floor这些不动的元素),精灵每个都用Sprite Renderer而不是Mesh Renderer。

     

    10.Layer vs Tag

    tag是为了对object分类,通常用于脚本(GameObject.FindWithTag())来快速搜索对象。Layer用于区分摄像机的渲染&射线投射对象,灯光的特定照射和物体的碰撞等。Layer虽然可以自己添加并命名,但layer在系统内是以编号区分的,所以layer的属性是int。(比如 int blockingLayer)。sorting layer在Sprite Renderer选项内,因为2D物体是可以覆盖的,所以Sorting Layer最底层的最先渲染,处于场景的最上方。

     

    11.UNITY里的文本

    unity的文本层和游戏层不同,游戏层以像素计数,文本层以比例计数,左下角为(0,0),右上角为(1,1),所以要把文本放在左上角只要更改position为(0,1,0)。

    要是想给文本留些空隙而不是死贴着边框,在pixel offset里调整(x,y)的像素相对移动(见space shooter内文本的设置)

     

    12.Animation组件内Parameters trigger vs bool

    动画状态转换的参数有四种类型:int,float,bool,trigger。前三种都很好理解,第四种是一次性的bool,比如人物死亡触发trigger,发呆和行走转换用bool。

    比如SurvivalShooter里人物行走用bool来转换

     

    像攻击比如Roguelike里的Chop和Hit就用trigger来转换。NPC释放一次性动画用Trigger。

     

    13.Unity里快速查找Component讲解

       不用在浏览器内打开官网再输入查询,直接点组件右上角的小书图标。

     

    14.场景搭建时用Snap Setting

    比如一排围墙,普通用Duplicate,然后手动一点一点挪(比如roll-a-ball),要对齐及其痛苦。我们可以在上方工具栏Edit→Snap Setting里设置好移动单位,移动下一个Duplicate Object时按住Ctrl键同时移动,就可以设置好的单位轻松移好。选定一堆小方块,然后摁Snap All Axes就会自动帮排列整齐(像Word里的对齐)。

     

    15.锁定Inspector面板方便拖拽对象或属性

     Unity经常需要确定组件内引用的是哪个对象,我们常在Hierarchy或Project下找到对象然后拖进栏内,但有时文件太多,点击到对象Inspector直接显示该对象的组件群,而不是我们需要拖拽的组件群。这时先把Inspector锁住,再开始查找,拖拽就很方便了。

     

     

    16.Unity Color取色

    在选择如背景Color时,点击小滴管可以取色,不仅可以取Unity Scene窗口里的颜色,也可以取其他颜色,比如一幅网上图取色,我们把浏览器和Unity并行放置,点击取色然后点击图片上需要的颜色就可以了。

     

    17.Unity工程2D和3D模式的区别

    unity其实不存在2D或3D的区别,只是摄像机是Orthographic或Perspective的区别。正交模式下镜头没有Z轴就成了2D模式。

    具体区别:

    2D:

    镜头为Orthographic;

    Scene面板为2Dmode;

    Windows→Lighting→Setting里Skybox为None,AmbientSource为color,Realtime Lighting和Mixed Lighting都取消GI勾选。

     

    3D:

    镜头为Perspective;

    Scene面板为3Dmode;

    Skybox为Default,AmibientSource为Skybox,两个选项都勾选。

     

    18.Unity内脚本加载顺序

    Edit→Project Settings→Script execution Order里可以设置各脚本的执行顺序和指定多少时间后该脚本开始加载。

    为了防止这种BUG:脚本引用json数据,添加json数据List脚本还没加载完,搜索数据并执行其他方法的脚本已经开始运行了。

    包括GameController,DataBase等需要提前加载的脚本可放到前面。

     

    19.Unity内image/button等上面叠加序列帧动画

    比如在场景切换时一般就显示一个黑图做幕布的效果(比如2DRougelike里的level升级时的Day N),如果想要在这块黑布上再播放动画,把动画拖入Canvas或给黑布Image下加Animator都是没有用的。

    比如UICanvas下有一个UIImage为黑色,UIImage下有一个UIText用来显示Day 1.现在要再UIImage上显示帧动画。则再UIImage下再新建一个子Image,比如命名为AnimationImage,然后再选中AnimationImage的情况下,打开Animation窗口,点击creat,选好名字和文件夹,新建好动画后,把序列帧动画包含的sprite全部拖入Animation窗口,调整下播放速度就可以了。

    参考:http://blog.csdn.net/mynameiszhuli/article/details/77951668

     

    20.在NPC头上显示对话框,或地图上显示指引箭头

    这时候UI作为整个地图的一部分,应该新建一个Canvas设置为WorldSpace。把Canvas拉到所需大小和位置。

    比如对话框,有Panel有Text,单纯设置WorldSpace是没法正确显示的。

    应该将Dynamic Pixels Per Unit设置的尽量大一些,这个选项表示如Text等的每一单位渲染的像素,值越大Text可以显示的越小。

    然后Reference Pixels Per Unit设置为1,表示图片等资源等比像素像素,这样就不会造成如Panel,Image等的虚化。

     

    比如NPC头顶的DialogueBox,NameText字号选择为1,调整canvas像素大小,然后把DialogueText设置为Best Fit,就会自适应Text大小。

     

    21.血条跟随

    血条小小的跟在玩家头上,需要Slider所在的Canvas跟随当前主相机。参考

     

    22.Unity设置横屏的方法等相关

    参考来源

     

    23.Unity屏幕分辨率自适应

    参考来源

    要点:

    1.UI所在的Canvas设置为screen space-overlay及scale with screen size & expand。

     

    2.UI内部件对应的设置锚点,比如某button保持在左下角则该button的锚点设为左下。

     

    3.勾选Pixel Perfect(防止由高分辨率转为低分辨率时字体模糊)

    4.Reference Resolution填为你在制作时的分辨率。比如我在1920*1080时制作的UI,现在要做自适应时填成该分辨率,则在测试时不同分辨率依然保持同样位置大小。

     

    24.

     

     





     

     

     

     

     

    展开全文
  • 2018年什么游戏最火? 不用问,肯定是人人都在撸的“王者荣耀”和吃鸡游戏了。...Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综...

    2018年什么游戏最火?

    不用问,肯定是人人都在撸的“王者荣耀”和吃鸡游戏了。

     

    只会打游戏,不去研究可不行。一直在想,像王者荣耀这样火的游戏是用什么引擎和语言开发的?

    这里就不得不说到现在最主流的游戏开发引擎——Unity3D了。

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

    相信做开发的人知道Unity3D,很多小伙伴也在找它的教程,今天我就分享一下Unity3D视频教程,希望能帮到大家。

    Unity3D基础视频

    http://yun.itheima.com/course/137.html?stt

    资料:http://pan.baidu.com/s/1eSDUbTo 密码:o97j

    课程介绍
    这是一套关于unity的基础课程,由传智大沙漠老师随堂录制。本套课程从C#语言开始,介绍了很多语言方面的特性,这些特性在unity开发及插件使用中都会出现。接下来是关于unity的操作,包括:模型、物理引擎、粒子系统、渲染、脚本生命周期、着色器、优化等知识点。通过学习这些内容,能够独立完成一些简单的游戏开发,并为接下来更高阶段的学习提供帮助。
    视频概况
    【第一天】
    讲解C#的基础知识,主要讲语法、面向对象两个知识点。如果你有C语言的开发基础,你会发现他们太像了,是的,语法非常相似。面向对象的三大特性:封装、继承、多态,会逐一讲解,并通过一些示例代码让你有更深入的理解。最后讲解了枚举与标志枚举的使用。
    【第二天】
    讲解常用的C#的类及函数。包括泛型、集合(List<T>与Dictionary<K,V>)、文件IO操作(主要是FileStream类)、Ado.Net(操作数据库),并以MySql数据库为例进行crud操作。
    【第三天】
    讲解C#的高级部分。包括:在函数的参数主要有3种方式传递,分别为:值传递,ref引用传递,out引用传递;关键字params实现参数的数组化;扩展方法的实现;委托与事件、lambda表达式的使用;线程的使用;最后讲解了单例、工厂、发布-订阅三种设计模式。
    【第四天】
    讲解C#的套接字Socket。以聊天室为示例,自定义传输协议,客户端能够收发信息,服务器端则负责将客户端发来的转发给其它客户端。主要讲解了Socket类的构造方法、Connet、Bind、Accept、Receive、Send等方法的使用。
    【第五天】
    讲解unity的知识点主要包括:坐标系;摄像机的投影方式;内置对象的使用;Scence面板的操作;用户接入;游戏对象的旋转、移动;预设与复制;导入模型;动态的两种方式Animation、Animator;在VS中调试。
    【第六天】
    讲解unity的知识点主要包括:光照及烘焙;第一人称与第三人称设置;地形系统;粒子系统;物理引擎中的刚体、碰撞检测、角色控制器。最终通过学习的知识点完成了打箱子、夏威夷漫游两个小示例。
    【第七天】
    讲解unity的知识点主要包括:音频的播放;预保存;资源加载;场景切换;协同调用;WWW类;寻路导航。在寻路中主要实现了自定义、水平跳、向下跳三种自定义移动方式,以及动态选择层。
    【第八天】
    讲解unity的知识点主要包括:GUI、uGUI、NGUI。重点介绍的是NGUI,通过NGUI可以制作图集、字体(结合BMFont)、交互脚本(以Button为例)、动画脚本(以宽高为例),最后完成了滚动栏、拖曳的效果。

     

    展开全文
  • 2019年Unity学习资源指南[精心整理]

    千次阅读 2019-07-14 14:02:23
    前言 进入一个领域,最直接有效的方法就是,寻找相关综述性文章,首先你需要对你入门的领域有个概括性的了解,这些包括: 1、主流的学习社区与网站。 2、该领域的知名大牛与...2019年Unity学习资源指南(本文相...
  • Unity学习 — 官方中文版本教程详解

    万次阅读 2018-10-18 10:36:02
    Unity官网中文版来了一:简单介绍二:简单的顺序循环数组内元素三:截图四:功能实现结束五:支持 一:简单介绍 1,Unity推出的中文,有利于英文不太好的人去学习和记忆 2,由于版本限制,并不是所有版本都...
  • 一些值得学习的Unity教程

    万次阅读 多人点赞 2016-01-29 10:03:20
    ***********************项目源码******************************** 1. 降临 2. 沉睡缤纷乐 3.... 4.... 5.... 6....天天萌泡泡 源码都分享在群里:375151422*****************************Git开
  • Unity 安装的时候,会提示安装的 组件,里面就有 教程 和 标准 工程。详见相关文章1 如果没有安装教程 ,可以 在 Unity 的 AssetStore 里面搜索 publisher:Unity Technologies, 相关文章: 1....
  • 最近在做项目的过程中遇到这样的一个需求:玩家可以在游戏过程中进行实时存档,在存档过程...首先是截取游戏画面,这个问题大家可以在《Unity教程之-Unity3d游戏开发之截屏保存精彩瞬间》这篇文章中找到答案。其次是从
  • Unity学习记录①: 关于教程无法正常运行的问题 可能有的同学在从UnityHub上开官方教程的时候会遇到这种情况: 直接弹出了这种界面而没有官方教程的亲切对话框 (我有问过学长,据说是版本问题,GetStarted这套教程...
  • http://www.unitymanual.com/thread-6498-1-1.html
  • 我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活自由的技能系统架构设计,传统的技能设计,做法都是填excel表,技能需要什么,都填表里,很死板,比如有的技能只需要1个特效,有的要10个,那么表格也得...
  • 原地址: 【教程贴】如何制作一辆简单的车 附件下载
  • *****************************Git开源项目*******************************1.https://git.oschina.net/dingxiaowei/TANKS.git2.SCUT https://github.com/ScutGame/Scut/wiki3.TTUIFramework ...
  • 教程将为刚接触unity的初学者讲解如何在Unity中实现3D立方体的堆叠,利用一个或多个预制件动态创建立方体进行拼接,为这些立方体赋予不同的颜色。  下载本文的示例工程,示例工程使用Unity 5.3.1f1。 ...
  • 每周更新unity3d视频教程,从入门到就业,官方unity3d培训,上千门实时更新课程,供学员在线观看学习,unity3d游戏开发,可以让学员随时随地学习! 免费网上学习unity3d自学教程,国内名师机构专业授课,O基础快速学习,1小时...
  • Unity3D安装教程

    千次阅读 2017-02-20 10:55:56
    Unity官网下载链接 https://store.unity.com/cn/?_ga=1.107281794.1832005354.1486108272 第一个为个人免费版,作为学习完全够用。建议通过注册账号进行免费使用,后续从资源商店下载资源时会用到账号。 Unity3D...
  • Photon Unity中文教程

    热门讨论 2014-10-21 17:47:49
    Photon Unity中文教程 PUN, short for Photon Unity Networking, is a Unity 3D plugin to easily setup a fast and reliable connection between remote clients through a Photon backend. PUN is API compatible ...
1 2 3 4 5 ... 20
收藏数 26,132
精华内容 10,452
关键字:

unity教程