unity中,获取物体的方法用的最多的是GameObject.Find()。但是GameObject.Find()有个致命缺点就是无法找到未激活的物体——假设我们想制作一个机关,游戏角色进入触发器区域,宝箱显形;离开触发器区域,宝箱消失。如果我们用GameObject.Find()方法会无法实现“游戏角色进入触发器区域,宝箱显形”这个功能。
这时候通常我们会选择transform.Find()方法,通过先寻找父对象,再搜索父对象的子物体找到需要触发的游戏物体(将需要触发的游戏物体提前绑定在一个父对象之下,且该父对象必须处于激活状态:可以将物体绑定在一个激活的空父物体下面)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class doorcontrol : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)//进入触发器区域时调用
{
GameObject doorparent = GameObject.Find("doorparent");
//寻找父对象并绑定在一个新建的GameObject类doorparent上
GameObject door = doorparent.transform.Find("door1").gameObject;
//通过transform.Find方法寻找父对象下doorparent的子物体中的名字为“door1”的游戏物体并绑定在一个新建的GameObject类door上
door.SetActive(false);
//取消door激活状态
}
private void OnTriggerExit(Collider other)//退出触发器区域时调用
{
GameObject doorparent = GameObject.Find("doorparent");
GameObject door = doorparent.transform.Find("door1").gameObject;
door.SetActive(true);
//激活door物体
}
}
当然,在上述代码例子中,我们在可以直接使用OnTriggerEnter方法取消door物体激活状态可以直接使用GameObject.Find(因为初始door物体处于激活状态,可以找到),而使代码简洁一点。这里是为了统一和省事,两个触发器方法都使用了transform.Find。
问题到这里其实解决了,但是楼主突然想起开放变量public的用法,是否可以利用public变量,在检查器界面手动将需要触发的door提前绑定好(也就是不用再Find了),这样即使door在未激活状态下,亦可直接由SetActive(false)转为SetActive(true)。
很简单的思路,但是效果异常的好
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class doorcontrol2 : MonoBehaviour
{
// Start is called before the first frame update
public GameObject door;
//设置public变量
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter(Collider other)
{
GameObject go = door.gameObject;
go.SetActive(false);
}
private void OnTriggerExit(Collider other)
{
GameObject go = door.gameObject;
go.SetActive(true);
}
}
相较于transform.Find方法,使用public方法至少有两个好处:
一,代码简洁,逻辑简单很多;
二,运行效率高不少,要知道无论是transform.Find还是GameObject.Find方法,系统采取的策略都是遍历,而遍历一般都很消耗资源。而public变量不需要遍历,因为已经提前手动绑定。