Unity 之 代码访问组件简介

653 阅读4分钟

「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战

代码与游戏对象的互相访问:

//sqb1类挂载在Cube

// sqb2类挂载在Cube,GameObject,Main Camera

public class sqb1 : MonoBehaviour {

    //将挂载物体赋值给go ,此时go和this.gameObject 是一样的
    public GameObject go; 

    void Start () {

        // go.gameObject.SetActive(false); 使挂载的游戏对象不显示
        //this.gameObject.SetActive(false); 与上同理 (此例中指Cube)



        //获取自己身上其他的组件,并访问属性
        sqb2 s2=this.gameObject.GetComponent<sqb2>();
        s2.num = 4;



        //获取子对象上的组件
        sqb2 s3 = this.transform.Find("GameObject").GetComponent<sqb2>();
        s3.num = 5;


        //通过名称获取组件 (其他对象的属性)
        sqb2 s4 = GameObject.Find("Main Camera").GetComponent<sqb2>();
        s4.num = 6;



        //通过标签进行查找 (Tag查找)
        sqb2 s5=GameObject.FindWithTag("Player").GetComponent<sqb2>();
        s5.num = 7;



        //通过类型进行查找
        sqb2 s6 = GameObject.FindObjectOfType<sqb2>();
        Debug.Log(s6.gameObject.name); //输出 GameObject



        //获取到所有的sqb2类型的载体
        sqb2[] s7 = GameObject.FindObjectsOfType<sqb2>();
        foreach (sqb2 item in s7)
        {
            Debug.Log(item.gameObject.name);
        }

    }

}
public class sqb2 : MonoBehaviour 
{

    public int num = 3;

    void Start () {

    }


    void Update () {

    }

}

查找游戏对象:

GameObject.Find(); 返回值类型:GamObject

可以查找任何层级物体,不受脚本绑定层级影响,,若指定层级,在指定层级中找,若不指定,则会在所有层级找,(名字不能重复),,如果存在多个物体重名,则会查找Hierarchy面板中最后创建的那个,,如果路径名没写全,不支持查找隐藏物体

transform.Find(); 返回值类型:Transform

只能查找子集物体,,如需查找其他层级,则要使用“完整路径”进行查找,,支持查找隐藏物体,,,(隐藏物体是指没有激活的物体,并不是看不见的物体)

通过标签查找:

通过Inspector 中的 Tag 标签查找物体

GameObject obj = GameObject.FindWithTag("AI");//通过Tag标签查找一个物体

GameObject obj = GameObject.FindGameObjectWithTag("AI");//通过Tag标签查找一个物体

GameObject[] obj = GameObject.FindGameObjectsWithTag("AI");//通过Tag标签查找一批物体

获取组件的方法

GetComponent<>(); //<脚本或者组件名>

GetComponentInChildren<>(); //<脚本或者组件名> 获取子物体组件列表

GetComponentsInChildren<>();

GetComponentInParent<>() ; //<脚本或者组件名> 获取父类物体组件列表

GetComponentsInParent<>(); //包括物体本身以及下面所有的子物体

// 代码示例
void Start () {
    //print("start");

    //两点之间的距离
    //print(Vector3.Distance(Vector3.zero, new Vector3(3, 4, 0)));

    /*
    GameObject go;
    go = null;
    print(go.name);*/
    //使用GameObject.Find可以通过层级关系查找到到未激活的游戏物体,如果不写层级关系,则找不到。
    //print(GameObject.Find("/Cube (2)/Cube (3)/Cube").name);

    /*
    使用Transform.Find()方法查找。只能查找其子级物体,不能越级。能查找隐藏的子级物体。能通过层级关系查找(隐藏)孙级物体
    Transform t = this.gameObject.transform.Find("/Cube (2)/Cube (3)/Cube");
    print(t.name);
    */

    //泛型方法的好处。
    print(GameObject.Find("/Cube (2)/Cube (3)/Cube").GetComponent<Transform>().localPosition);
    }

void Update () 
{
    //print("update");

    // this.transform.Rotate(10, 10, 0);//物体旋转

    //平滑移动
    //this.gameObject.transform.position = Vector3.Lerp(this.transform.position, new Vector3(10, 0, 0), Time.deltaTime);
    
    //使用MoveTowards方法对物体进行移动
    //this.gameObject.transform.position = Vector3.MoveTowards(this.gameObject.transform.position, new Vector3(10, 0, 0), 0.05f);
}

添加组件的方法

gameObejct.AddComponent<>(); //动态添加组件 <脚本名称>

[RequirtComponenr(typeof())] //添加组件(扩展编辑器)

方法与属性的执行效率

比较组件:

Component.tag == "XXX";

Component.CompareTag("XXX");

注: 继承自GameObject 的游戏对象和Component类的组件都有一个tag 和 CompareTag属性和方法,,,执行效率ComparTag相对更高;

Tags 标签管理类

游戏中可以通过标签来分别主角,敌人和场景,,比如射击游戏,我们需要判断子弹打到了谁,而对方有什么样的动作,,,此时我们如果用标签管理类就会方便很多

例如:

public class Tags
{

    pubilc const string player = "Player";

    pubilc const string mainCamera= "MainCamera";

}

此类不需要挂载到物体上,所有没有必要继承MonoBehavior ,需要被外部访问所以用 public 修饰符,用count 代替static 是防止在代码中更改标签值,

使用时直接调用,

if(this.gameObject == Tags.player) { ... } 就可以了

游戏对象的生成和销毁

GameObject.CreatePrimitive 创建基本物体

C# => static GameObject CreatePrimitive(PrimitiveType type);

PrimitiveType 是枚举类型,使用时只需"."出想创建的基础物体即可,,,

Object.Instantiate 克隆、实例,创建一个游戏物体,

C# => static Object Instantiate(Object original, Vector3 position, Quaternion rotation);

C# => static Object Instantiate(Object original);

注:创建每个实例都比较消耗系统的内存,所以我们用完的时候,一定及时销毁

删除场景中的一个物体或组件

Object.Destroy 销毁

//Destroy()方法继承自Object ,凡是基础Object的组件物体资源都可被此方法动态删除 Object.DestroyImmediate 立即销毁

Object.DontDestroyOnLoad 加载时不销毁

//DontDestroyOnLoad ()方法用于当前场景到新场景中切换,保留被加载的物体,身上所有的组件及对应的属性信息都不会改变

MonoBehaviour.OnDestroy 当销毁 //此方法和以上三个不一样,该方法属于生命周期函数

注:销毁父级物体,自己物体自动销毁

面试易问问题:

GameObject.Find()和Transform.Find()的区别?

  • GameObject: 可以根据游戏物体的名称查找所有层级的游戏物体,不支持查找被禁用(未激活)物体

  • Transform: 只能查找脚本所依附的游戏对象的子物体中,并且只能查一级子物体,如查找多层需要完整路径,支持查找被禁用物体