173

王者荣耀是怎样炼成的(三)unity组件与脚本 - my笔触

 6 years ago
source link: http://www.cnblogs.com/yuxiuyan/p/7565345.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

王者荣耀是怎样炼成的(三)unity组件与脚本 - 于果alpha - 博客园

转载请注明出处:http://www.cnblogs.com/yuxiuyan/p/7565345.html

上回书说到了unity的基本操作。这回我们来侃侃unity中的组件与脚本。

  一.组件与脚本简介

  二.鼠标与键盘输入

  三.使用变换组件移动游戏物体

  四.物理组件之刚体

  五.物理组件之碰撞体

  六.刚体常用方法介绍

  七.刚体碰撞事件监测与处理

  八.刚体触发事件监测与处理

  九.游戏打包与发布

  十.入门总结

一.组件与脚本简介

组件(Component),顾名思义,就是游戏物体的组成部件。

这和我们对现实生活的认识是一致的。就比如说一台主机,是有CPU,显卡,主板,内存条等等组成的。这些部件就是主机的“组件”。这些组件一旦有不满意的,随时可以增删改查。

Unity3D就是一个“组件式”的游戏引擎,它使用各种各样的的组件“拼装”了游戏物体,最终再把游戏物体拼装成游戏。

上图是一个Plane的自带组件。

Unity3D为我们提供了许多种类的组件。后期其实就是各种组件的使用和特性,以及它们能实现的功能和效果。

按照我们老祖宗的理论,五行是组成世界的最基本元素。那么在Unity3D中,组件就是组成游戏世界的最基本元素。

我总结出了上面一幅图,这幅图相当重要,大家需要认真看看。因为这涉及到了游戏物体与脚本中类和对象的联系。

2.Transform组件

在这里提一个最最基本的组件之一——Transform组件。

Transform,中文为“变换”,这个组件有三大基本属性,Position(世界位置坐标),Rotation(相对自身坐标系的旋转角度),Scale(相对于初始的缩放比例)。

这个组件是每一个游戏物体都有的属性,并且不能删除。其实想想也是,在现实生活中,只要是一个物体必定有方位、旋转、缩放的属性。

通过修改这三大属性的X\Y\Z值,我们就可以控制物体的“变换”信息了。这里有一个小技巧,当把鼠标放到X\Y\Z上时,鼠标变成了可以左右拖动的标志,可以直接左右拖动改变值,当然直接修改值也是ok的。

脚本(Script),也就是给游戏物体写的代码,用来控制游戏的逻辑。在Unity3D 5.x版本后,只支持C#脚本和JavaScript脚本。在国内开发的主流的C#。

4.创建与管理脚本

我们说过,Assets文件夹是总管,所以我们在Assets中新建一个Scripts文件夹,用来管理脚本资源。

在Scripts文件夹中右键-->Create-->C# Script。C#脚本文件的后缀是“.cs”。双击脚本文件,可以调用代码编辑器进行编辑。

5.原始脚本代码组成

在上一步我们新建了一个脚本,这次打开它看看究竟是什么东东。

ok,我们看到这次unity帮我们新建立了一个类,类名就是我们的脚本文件名。然后它继承自MonoBehaviour类,这个类呢,在unity的地位和作用,类似于在java中的Object类,所以重要性不言而喻。有兴趣的童鞋可以去看看这个类的实现。可以看一下这篇文章:http://blog.csdn.net/yuyueliuliu/article/details/43795333。还能看到,这个脚本using了UnityEngine的引擎。然后unity还帮我们写了两个方法Start()和Update()。

Start():当游戏运行起来,这个方法就会马上执行且只执行一次。由此看来,这个方法非常适合做初始化的工作。事实上也是这样的,我们常常在这个方法中做一些GetComponent()的操作。

Update():循环调用,每一帧就调用一次。我大致测了一下,一般的场景大概是每秒60次的样子。

这里还要介绍一个方法:Debug.Log()。这个用来输出调试。如果你的目标是“helloworld”,ok,这个方法正好就是这样。

顺便提一句,Start()和Update()都是unity内部的“事件方法”,不需要我们人工调用,系统会自动调用和管理这些方法的。

6.使用脚本

  • 直接将脚本拖拽到Hiearchy面板的物体上
  • 直接将脚本拖拽到物体的Inspector面板上

 运行游戏,脚本自动执行。

这是一个first.cs脚本:

using UnityEngine;
using System.Collections;

public class first : MonoBehaviour {

    void Start () {
        Debug.Log("这是Start方法");
    }
    
    void Update () {
        Debug.Log("这是Update方法");
    }

}

把它添加到灯光上,运行游戏,控制台效果:

二.鼠标与键盘输入

上面我们已经知道了C#脚本的大致套路。说到写代码就是各位童鞋的长处了。这次我们实现一下让游戏读出我们的输入。

unity很友好地为我们都写好了方法,我们只需要调用这些接口就ok了。

1.获取键盘输入

案例如下:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class InputTest : MonoBehaviour {
 5 
 6     void Update () {
 7         if (Input.GetKey(KeyCode.A))
 8         {
 9             Debug.Log("按下了A键");
10         }
11         if (Input.GetKeyDown(KeyCode.A))
12         {
13             Debug.Log("GetKeyDown");
14         }
15         if (Input.GetKeyUp(KeyCode.A))
16         {
17             Debug.Log("GetKeyUp");
18         }
19     }
20 }

 2.获取鼠标输入

直接上方法。

用法和监听键盘输入类似,在这里就不再写代码举例了(笑~)。

三.使用变换组件移动游戏物体

上面提到了鼠标键盘监听控制,也提到了Transform组件,我们利用脚本,可以把两者组合起来,实现通过键盘让游戏物体动起来!

备注:脚本也可以看成组件,一般是要控制哪个游戏物体就把脚本挂载到哪个物体上。

下面就是一个例子:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class StudentMove : MonoBehaviour
 5 {
 6     private Transform trans;
 7 
 8     // Use this for initialization
 9     void Start()
10     {
11         trans = gameObject.GetComponent<Transform>();
12     }
13 
14     // Update is called once per frame
15     void Update()
16     {
17         if (Input.GetKey(KeyCode.W))
18         {
19             trans.Translate(Vector3.forward * 0.1f, Space.World);
20         }
21         if (Input.GetKey(KeyCode.A))
22         {
23             trans.Translate(Vector3.left * 0.1f, Space.World);
24         }
25         if (Input.GetKey(KeyCode.S))
26         {
27             trans.Translate(Vector3.back * 0.1f, Space.World);
28         }
29         if (Input.GetKey(KeyCode.D))
30         {
31             trans.Translate(Vector3.right * 0.1f, Space.World);
32         }
33     }
34 }

把这个脚本,拖到游戏物体的Inspector面板上,然后点击游戏的“运行”按钮,可以发现我们已经可以通过键盘的W\A\S\D键控制物体的前左后右的移动了!amazing!

四.物理组件之刚体

在上面我们通过Transform组件实现了物体位置的移动,但是仔细研究一下发现了以下几个特点:

  • 移动的物体会“穿透”场景中其他的物体模型
  • 移动的物体不会受到重力影响(即使到达场景之外,也不会下落)

 这样看起来物体动是动了,但是不太真实,和我们现实生活中有很大差别。

大家应该都听过或者玩过《愤怒的小鸟》,小鸟的抛物线运动,石头的坍塌,都是符合物理规律的。

我们说过,组件是构成游戏物体的基础。所以,我们需要其他组件来使物体符合物理规律。

 刚体(Rigidbody),属于物理类组件。添加了刚体组件的游戏物体,就有了重力,就会做自由落体运动,也就实现了现实物体的物理运动。

选择游戏物体-->菜单栏点击Componment-->Physics-->Rigidbody,给物体添加刚体组件成功!

2.常用属性

看着上图,我们了解一下它的几个常用属性。

Mass[质量],可以设置物体的质量,你可以认为单位是KG。

Drag[阻力],一般是指空气阻力,0表示没有空气阻力,空气阻力越大,物体自由落体越慢。当值很大时,物体甚至会停止运动,漂浮在空中。

Angular Drag[角阻力],收到扭曲力时候的空气阻力,0表示没有阻力,当值很大时,物体甚至会停止运动。

Use Gravity[使用重力]。当勾选之后,如果物体掉入场景之外,会落入“深渊”。

3.在脚本中使用刚体组件移动游戏物体

直接上脚本:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class RigidbodyMove : MonoBehaviour
 5 {
 6     private Transform trans;
 7     private Rigidbody rigid;
 8 
 9     // Use this for initialization
10     void Start()
11     {
12         trans = gameObject.GetComponent<Transform>();
13         rigid = gameObject.GetComponent<Rigidbody>();
14     }
15 
16     // Update is called once per frame
17     void Update()
18     {
19         if (Input.GetKey(KeyCode.W))
20         {
21             rigid.MovePosition(trans.position + Vector3.forward * 0.1f);
22         }
23         if (Input.GetKey(KeyCode.A))
24         {
25             rigid.MovePosition(trans.position + Vector3.left * 0.1f);
26         }
27         if (Input.GetKey(KeyCode.S))
28         {
29             rigid.MovePosition(trans.position + Vector3.back * 0.1f);
30         }
31         if (Input.GetKey(KeyCode.D))
32         {
33             rigid.MovePosition(trans.position + Vector3.right * 0.1f);
34         }
35     }
36 }

 代码很简略,但是却实现了像现实物体一样的物理运动,很神奇。

五.物理组件之碰撞体

 1.碰撞体

上面使用刚体组件的物体,在场景中其他物体可以产生碰撞的效果。其实碰撞目标物体的,是专门有一个组件来负责的,就是碰撞体组件(Collider)。

换个说法,我们控制的物体A与物体B的碰撞,实质上是物体A与物体B的碰撞体组件发生了作用关系。 

碰撞体可以理解成我们模型的“外骨骼”。

这是一个什么也没有动的原来的Cube。

 把物体的渲染器(上面的Renderer的勾选去掉)屏蔽,可以发现物体的碰撞体长得什么样子:

显示的就是Cube外层的碰撞体组件。

只要我们创建了物体,unity就默认为我们加上了碰撞体组件,没有碰撞体的刚体是没有意义的,就失去了刚体本该有的物理特性。

换句话说,物理特性是刚体组件和碰撞体组件一起表现出来的。

其实这一对“好基友”有很多很多的故事,大致总结了一下。

碰撞体组件按照它们的形状,大致可以分为以下几类。

2.Box Collider

盒子碰撞体,形状是立方体,用来包裹盒子状的模型,比如箱子、门、房子,等等。有几个常用属性:

Is Trigger:设置是否为触发器。这个属性非常重要,在后面讲触发器会经常使用。

Material:物理材质。

Center:碰撞体也可以设置中心点。一般来说碰撞体中心点就是物体的几何中心点。

Size:设置物体的“外骨骼”的尺寸。

 3.Sphere Collider

球形碰撞体,和上面的盒子碰撞体基本类似,Radius是半径。

4.Capsule Collider

胶囊碰撞体,属性和球形碰撞体类似,Direction是指设置它的高度的方向。

5.Mesh Collider

网格碰撞体,用来包裹复杂结构的模型

Mesh:根据指定的网格,生成碰撞体。

六.刚体常用方法介绍

有了组件,必然有新带来的方法。

1.AddForce()

作用:给刚体一个力,使刚体按照“世界坐标系”进行运动。

其中的ForceMode是力的模式,是一个枚举类型,决定以什么样的方式添加力给刚体。

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class ForceTest : MonoBehaviour
 5 {
 6     private Rigidbody rigid;
 7     void Start()
 8     {   //获取物体的刚体组件
 9         rigid = gameObject.GetComponent<Rigidbody>();
10     }
11     void Update()
12     {   //给刚体施加一个相对世界坐标系向前的力
13         rigid.AddForce(Vector3.forward, ForceMode.Force);
14     }
15 }

2.AddRelativeForce()

作用:给刚体添加一个力,让刚体按照“自身坐标系”进行运动。

由此可以知道,AddForce()和AddRelativeForce()是非常像的,这俩其实就是双胞胎,只不过一个是相对世界坐标系,另一个是相对自身坐标系罢了。

3.FixedUpdate()

这个是固定的更新方法。这个方法值得说道说道。一查网上资料还真不少,那就不献丑了~

Update()方法是每一帧刷新一次,但是时间间隔是不确定的。而FixedUpdate()方法是固定时间间隔(默认0.02秒)刷新一次。

这个值是可以自己设定的。Edit-->Project Settings-->Time-->Fixed Timestep。

基本上和物理相关的操作,代码都是写在FixedUpdate()方法里面。如果你写在了Update()里,会出现卡顿的现象。

七.刚体碰撞事件监测与处理

1.碰撞事件简介

啥叫“碰撞事件”呢?当一个用刚体控制的物体与另外一个物体碰撞时,就会触发碰撞事件。

注:目标物体必须带有Collider组件。

碰撞 Collision

比如,一个射击类游戏,我们发射了子弹,子弹是一个由刚体控制运动的物体。子弹射中了敌人,我们怎么监测这个碰撞呢?

2.碰撞事件监测方法

  • OnCollisionEnter(Collision)   //当碰撞开始时调用,只会调用该方法一次
  • OnCollisionExit(Collision)     //当碰撞结束时调用,只会调用该方法一次
  • OnCollisionStay(Collision)     //当碰撞进行中时,会持续调用该方法

这个Collision参数是什么呢?

这个是“碰撞”的一个类,用来传递碰撞信息。

Collision.gameObject属性,与当前物体碰撞的物体的引用。

gameObject.name属性,当前物体的名字。

上代码示例:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class CollisionCube : MonoBehaviour {
 5 
 6     void OnCollisionEnter(Collision coll)
 7     {
 8         if(coll.gameObject.name != "Ground")
 9             Debug.Log ("Enter " + coll.gameObject.name);
10     }
11 
12     void OnCollisionExit(Collision coll)
13     {
14         if(coll.gameObject.name != "Ground")
15             Debug.Log ("Exit " + coll.gameObject.name);        
16     }
17 
18     void OnCollisionStay(Collision coll)
19     {
20         if(coll.gameObject.name != "Ground")
21             Debug.Log ("Stay " + coll.gameObject.name);                
22     }
23         
24 }

八.刚体触发事件监测与处理

1.触发事件简介

将碰撞体组件上的Is Trigger选项选中,当前的游戏物体的碰撞体组件就变成了触发器。

我想大家应该都理解“触发器”的概念。

注:移动的刚体物体都会穿透碰撞体勾选了“Is Trigger”选项的物体。

当一个用刚体控制的物体进入到另一个物体的触发器范围内,就产生了触发事件。

这个不与目标物体发生直接的碰撞(接触),而是只要进入目标物体的“触发范围”就能执行某些操作。

那怎么设定“触发范围”呢?其实和我们上面设置碰撞体范围的方法是一致的。

2.触发事件监测方法

  • OnTriggerEnter(Collider)  //当进入触发范围开始时调用,只会调用该方法一次
  • OnTriggerExit(Collider)   //当退出触发范围开始时调用,只会调用该方法一次
  • OnTriggerStay(Collider)     //在触发范围内,会持续调用该方法

这个Collider参数是什么呢?

这个是“碰撞体”的一个类,用来传递触发信息。

Collision.gameObject属性,进入触发范围内的目标物体的引用。

gameObject.name属性,当前物体的名字。

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 public class TriggerCube : MonoBehaviour {
 5 
 6     void OnTriggerEnter(Collider coll)
 7     {
 8         Debug.Log (coll.gameObject.name+"on trigger enter");
 9     }
10     void OnTriggerStay(Collider coll)
11     {
12         Debug.Log (coll.gameObject.name+"on trigger stay");
13     }
14     void OnTriggerExit(Collider coll)
15     {
16         Debug.Log (coll.gameObject.name+"on trigger exit");
17     }
18 }

九.游戏打包与发布

好了,当我们制作好了一个游戏,怎么把它发布到各个平台呢?

其实很简单。untiy已经帮我们做好了绝大部分事情。

我们要做的事情:

1.Build Settings[生成设置]

2.Player Settings[详细设置]

3.成品介绍

一个exe文件,一个data数据文件夹,两者缺一不可。

十.入门总结

这个阶段我们从最简单的组件与脚本学起,介绍了鼠标键盘的交互,怎么移动物体,了解了刚体、碰撞体以及常用的几个方法,还学习了怎么打包发布。那么unity的基本操作差不多告一段落。虽然还有很多没有介绍到,那我们在做demo的过程中再学再用吧。我还把上面介绍到的所有的方法和属性写了一个思维导图文件,缩略图:

详细的地址:链接:http://pan.baidu.com/s/1dFMXvpf 密码:8xq0

ok,今天告一段落。

 ------------------------------------9.26更新---------------------------------------------------------------------------------------------------------------

最近规划了一下,发现看似简单的一个demo做起来需要用到许多unity的其他知识,什么动画系统,粒子系统,物理引擎,所以准备开一个新的案例,如《贪吃蛇大作战》等,补充自己的知识后,再来更好地做这个农药的demo。再加上本人还是某不知名双一流大学的学生,课程比较紧,期间会穿插其他知识,所以这个专栏更新会比较慢。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK