一、物体、组件和对象
一个游戏物体是一个对象;没有被挂到物体上的脚本,是一个未被实例化的类,暂时还不是具体的对象;当脚本被挂到物体上后,就成了一个实实在在的对象。
脚本在执行时,一般已经挂到了某个对象上。因此在脚本代码中,可以随时访问脚本目前挂到了那个对象上,直接用gameObject就行
下面两个都可以,this可以被省略
Debug.Log(gameObject.name);
Debug.Log(this.gameObject.name);
二、获取组件的方法
获得某个物体后,就可以通过物体获取到它的每一个组件。举个例子,新建一个Test脚本文件并挂到球体上,脚本内容保持默认,为了得到Sphere Collider组件,可以直接用GetComponent()方法,将Test脚本内容修改如下。
using UnityEngine; public class Test : MonoBehaviour { SphereCollider collider; void Start() { collider=gameObject.GetComponent<SphereCollider>(); } }
上述是很常见的获取组件的代码,即先从当前脚本获取到游戏物体,再到游戏物体中找到某个组件。
Transform组件也可以用GetComponent()方法获得,但是由于Transform组件非常常用,因此随时刻通过字段transform访问,不需要通过代码获取
Unity为了方便,设计了获取组件的简便写法。思路是,在同一个物体上,从任意一个组件出发都可以直接获取到其他组件,不需要先获取游戏物体。也就是说,获取组件的写法有很多等价的形式,举例如下
collider=gameObject.getComponent<SphereCollider>(); //下面每一句写法均与上面一句等价 collider=this.GetComponent<SphereCollider>(); collider=GetComponent<SphereCollider>(); collider=transform.GetComponent<SphereCollider>();
如果需要获取多个相同组件,就要用到 GetComponents()方法,一般用一个数组存着。
三、获取物体的方法
1、通过名称获取物体
使用GameObject.Find()方法即可。举例:新建一个立方体,并挂一个TestGetObject脚本,内容如下
Public class TestGetGameObject : MonoBehaviour { GameObject objMainCam; GameObject objMainLight; void Start() { objMainCam=GameObject.Find("Main Camera"); objMainLight=GameObject.Find("Directional Light"); Debug.Log(" 主摄像机:"+objMainCam.name); Debug.Log(" 主光源:"+objMainLight.name); //将主摄像机放在这个物体后方1m的位置 objMainCam.transform.position=transform.position-transform.forward; } }
GameObject.Find()方法比较常用,但它有两个弊端
- 无法找到未激活的物体
- 需要遍历场景中的所有物体,性能上来说非常低效
为了验证第一个弊端,我们可以在上面的例子中,禁用场景光源(在Inspector窗口中取消勾选Drectional Light选项),这时再次运行,就会出现报错,异常类型为NullReferenceException(空引用)。双击该错误,就会定位到相应的源代码,源代码如下
Debug.Log(" 主光源:"+objMainLight.name);
这是由于其当前为空引用null,因此访问其name字段会报错。说明了GameObject.Find()方法的确无法找到未激活的物体
对于第二个弊端,在简单场景里很难察觉。而在一个完整的游戏中,场景中经常会有成千上万个物体,那时的效率差异就会想当明显。但这也不代表不能用GameObject.Find()方法。如果仅在Start方法中调用一次,然后将物体保存在objMainCam中,以后都不用重新查找,这样就不会产生明显的效率差异。
2、通过标签查找物体
通过例子来说明
//查找第一个标签为Player的物体
GameObject players=GameObject.FindGameObjectWithTag("Palyer");
//查找所有标签为Monster的物体,返回只是一个数组,结果可以是0个或多个
GameObject[] monsters=GameObject.FindGameObjectsWithTag("Monser");
除了Inspector中修改物体的标签,在脚本中也可以,举例如下
GameObject m=GameObject.FindGameObjectWithTag("Player"); m.tag="Cube"; if(m.CompareTag("Cube")) //CompareTag用法等效于m.tag=="Cube",推荐使用CompareTag { ......//略 }