当前位置:   article > 正文

【Unity学习笔记】Component、Transform、GameObject、Object四个重要类_unity gsmeobject component

unity gsmeobject component

调试

1、控制台调试 Debug.Log(变量);print(变量);//用完一定记得删掉!!!
2、定义共有变量,程序运行后在检测面板查看数据//可观察数据的变化规律啥的
VS调试:
单帧调试: 启动调试–>>运行场景–>>暂停游戏–>>加断点–>>单帧执行–>>结束调试
调试过程中,输入代码:1、右键–快速监视 2、也可以查看“即时窗口”

组件(Component)的认识

1、组件的定义

组件 是在游戏对象(Game Object)中的实现某些功能的集合。
无论是模型、 GUI、灯光还是摄像机,所有游戏对象本质上都是一个空对象挂载了不同类别的组件,从而让该游戏对象拥有不同的功能。
对于一个空游戏对象来说,如果为其添加一个摄像机组件,那么该对象就是一架摄像机;如果为其添加了网格过滤(Mesh Filter)组件,那么该对象就是一个模型;如果为其添加了灯光组件,该对象就是一盏灯光。
游戏对象(GameObject)上可以包含多个组件(Component)。每个游戏对象都有一个Transform Component(创建游戏对象时就默认有了)。我们也可以自行添加组件,添加不同的组件可以使游戏对象有各种功能。
脚本在Unity中也是一种组件。 (我们写脚本就是自己写一个类,这个类一旦挂到游戏对象上就实例化成了一个对象,也可以说是这个游戏对象的一个组件)

2、分清组件(游戏对象)和变量(脚本成员)的区别 [来源]

在Unity中组件其实就是一个类的实例,它属于游戏对象,一般可以直接添加在游戏对象上的功能都是组件,他们显示在Inspector属性查看器窗口上。
而很多组件在脚本中都有对应的脚本变量来代替,想通过脚本代码来时获得对应组件及其属性,就可以通过这些变量名来获得。(例如想修改位置可以用transform。。。)
所以在脚本中通过访问组件和访问变量来获取组件的方法是不一样的。
首先最大的区别,就是变量都是小写,而组件开头是大写。
例如:

组件名称变量名称
Transformtransform
Rigidbodyrigidbody
Animationanimation
Renderrender

等等。但是也有例外,比如Camera组件和Light组件,他们的变量名称和组件名称是一样的,因为他们的变量只对摄像机对象和光源对象有效。

组件和变量在脚本中的不同用法

如果通过访问变量就可以直接更改其属性,但是要通过组件进行修改,必须先调用GetComponent<组件名称>()的方法。
例如,同样是让物体进行位移,就有两种方式:
(因为Translate和GameObject俩组件经常用,所以unity把这俩属性实例化了,点 点儿~ 就能用)

public class BNUComponent : MonoBehaviour {
    void Update(){
        transform.Translate(1, 0, 0);			//直接修改对象transform变量的属性
        GetComponent<Transform>().Translate(1, 0, 0);    /*先访问对象的Transform组件,
                                                           再通过Translate方法进行变化*/
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

常用API

Unity核心类图


PS:红框框出来的是我们的直系亲属,里面的方法属性不用见外,随便用

Component 组件类

【component类提供了查找(当前物体后代、先辈)组件的功能】

Component常用属性

•常用属性
tag、gameObject、transform、colliderrenderer……
(ps:这些属性都当自己的属性用就行,我们都是继承于C爸爸)

           //在脚本里面写一个this 就是这个 脚本类/脚本这个组件 的引用
            //this.transform 拿到了transform的引用,再点position属性,就能改变位置了
            //position是结构体 要用new
            this.transform.position = new Vector3(0, 0, 10);
  • 1
  • 2
  • 3
  • 4

//transform是component里的属性 相当于是自己的属性
//则上面的语句等价于下面

            transform.position = new Vector3(0, 0, 10);
  • 1
Component常用方法

找自身组件:
Getcomponent< type>() //返回游戏对象上type类型的组件
GetComponents < type>()//查找 [自身] 所有父类是Component的,type类型的组件 即 查找所有挂在物体上的组件
找后代组件(DFS):
GetComponentInChildren< type>() 获取后代物体中某一组件(某一组件在后代中,但不确定是哪一个后代,可用它查找)
GetComponentsInChildren< type>() //获取后代物体的指定组件(从自身开始查找)
找先辈:
GetComponentInParent 。。。同上
GetComponentsInParent 。。。同上

        if(GUILayout.Button("改变颜色"))
        {
            //返回游戏对象上type类型的组件,若没有,返回无
            this.GetComponent<MeshRenderer>().material.color = Color.red;
        }
        if(GUILayout.Button("GetComponents"))
        {
            //查找自身所有父类是Component的组件,即可查找出所有挂在物体上的组件
            var allComponent=this.GetComponents<Component>();
            foreach (var item in allComponent)
                Debug.Log(item.GetType());
        }
        if (GUILayout.Button("GetComponentsInChildren"))
        {
            //获取后代物体的指定组件(从自身开始查找)
            var allComponent = this.GetComponentsInChildren<MeshRenderer>();
            foreach (var item in allComponent)
                item.material.color = Color.blue;
        }
        if (GUILayout.Button("GetComponentInChildren"))
        {
            //深度优先搜索
            //获取后代物体中某一组件(某一组件在后代中,但不确定是哪一个后代,可用它查找)
            var item = this.GetComponentInChildren<AudioSource>();
            item.loop = true;
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

Transform 变换类

【Transform类提供了 查找(父、根、子(索引、名称))变换组件(即Transform组件);改变位置、角度、大小功能】

Transform常用属性

改变位置、角度、大小
这里的数值都是localPosition
这里编辑器里的三个的数值都是localPosition

position& localPosition 世界坐标 &本地坐标(以父节点为原点)

            //物体相对于世界坐标系的位置 即 世界坐标
             this.transform.position;
            //物体相对于父物体轴心点的位置 在编辑器里面的位置、旋转和缩放都是localPosition
            this.transform.localPosition
  • 1
  • 2
  • 3
  • 4

rotation 同上

localScale&lossyScale 世界坐标系大小&本地坐标系大小

            //相对于父物体缩放比例
            //若localScale是(2,2,1)父物体是(1/3,3,1),则自己是(2/3,6,1)
            this.transform.localScale
            //理解为:【只读】物体与模型缩放比例(自身缩放比例*父物体缩放比例)
            //若lossyScale是(3,2,1)父物体是(1/3,3,1),则自己是(1,6,1)
            this.transform.lossyScale
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取父、根、子物体变换组件

foreach(Transform child in transform) //查找子物体的变换组件
this.transform.root//获取根物体的变换组件
this.transform.parent//获取父物体的变换组件

       if (GUILayout.Button("foreach--transform"))
        {
            foreach(Transform child in transform)
            {
                //child为每个子物体的变换组件(只能查找子物体这一层)
                print(child.name);
            }
        }
        if (GUILayout.Button("root"))
        {
                //获取根物体变换组件
                Transform rootTF = this.transform.root;
                print(rootTF.name); 
        }
        if (GUILayout.Button("parent"))
        {
                //获取父物体变换组件
                // 目前只能获取 不能改变 想改变用 SetParent
                Transform parentTF = this.transform.parent;
                print(parentTF.name);  
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
Transform常用方法

改变位置、角度
Translate()//移动位置
Rotate()//旋转
RotateAround()//围绕旋转

  if (GUILayout.Button("pos/scale"))//摁一次执行一帧
        {
            //向自身坐标系z轴移动1米
            this.transform.Translate(0, 0, 1);
            //向世界坐标系z轴移动1米
             this.transform.Translate(0, 0, 1,Space.World);
            // ==>角度rotation等同

            //沿自身坐标系y轴 旋转10°
            this.transform.Rotate(0, 10, 0);
            //沿世界坐标系y轴 旋转10°
            this.transform.Rotate(0, 10, 0, Space.World);
        }
        if (GUILayout.RepeatButton("RotateAround"))//一直摁下就一直执行
        {
            //围绕旋转:(绕着哪一个点,绕哪一个轴,转几度)
            this.transform.RotateAround(Vector3.zero, Vector3.up, 1);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

查找/改变 父、根、子物体
SetParent()//认一个新爸爸
Find()//根据名称获取子物体 儿子孙子都能找到
GetChild()//根据参数获取子物体 只能获取亲儿子
DetachChildren()//与子对象解除父子关系

       if (GUILayout.Button("SetParent"))
        {
            //设置父物体(认一个新爸爸)
            //当前物体位置视为 世界坐标
            this.transform.SetParent(NewDad);
            //当前物体位置视为 LocalPosition,则跟了新爸爸后轴心点变了,位置也要随之改变
            this.transform.SetParent(NewDad, false);

        }
         if (GUILayout.Button("Child"))
        {
            //根据名称获取子物体(写上子物体名称)
            Transform childTF = this.transform.Find("Cube (3)");
            //根据名称获取孙子。。但不建议用 只要路径一变换就会报错
            Transform childTF2 = this.transform.Find("子物体名称/子物体名称");
            //  print(childTF.name);
        }
        if (GUILayout.Button("GetChild"))
        {
            int count = this.transform.childCount;
            for(int i = 0; i < count; i++)
            {
                Transform childTF = this.transform.GetChild(i);
            }
        }
         //【所有子对象】解除父子关系 即 我不要孩子们了
        transform.DetachChildren();
        //若 我不要我爸爸了 可以 
        this.transform.SetParent(null);
        Destroy(gameObject);//可以再把自己销毁


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
作业:在未知层级下查找子物体
 //DFS深搜
 private Transform GetChild(Transform t,string childName)
    {
        print(t.name);
        Transform childTF = t.Find(childName);//看看子物体里有没有
        if (childTF != null)
            return childTF;
        if (t.childCount == 0)
            return null;
        foreach(Transform i in transform)
        {
            Debug.Log(i.name);
            childTF = GetChild(i, childName);
            if (childTF != null)
                return childTF;
        }
        return null;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

注意: 递归函数在运行时会执行压栈操作,当压栈次数太多时,导致堆栈溢出。所以当层级太多时运用递归Unity会直接卡死。。。
补充:递归的过程就是调用本身的过程,函数当中的变量是存储在栈中,当我们执行函数的时候变量会一直压入栈中,当函数执行完毕销毁的时候依次出栈,由于系统栈很小,栈满之后继续压栈就会导致栈溢出。

GameObject 游戏对象

【对游戏对象进行:激活/禁用、添加组件;通过Tag查找物体】

有关激活/禁用游戏对象

GameObject.activeInHierarchy//【只读】场景中游戏对象实际被激活状态
GameObject.activeSelf//【只读】场景中游戏对象局部被激活状态(父辈禁用,即使自己的勾还有也是被禁用状态)
GameObject.SetActive(true/false)//激活、停用 此游戏对象

            //【只读】场景中游戏对象实际被激活状态
            Debug.Log("activeInHierarchy:"+ objectDemo.activeInHierarchy);
            //【只读】场景中游戏对象局部被激活状态(就是面板上的小勾勾的状态)
            //有的时候,他爸爸被禁用了,他也被禁用了
            Debug.Log("activeSelf:"+ objectDemo.activeSelf);
            //激活、停用 此游戏对象
            objectDemo.SetActive(false);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
有关给游戏对象添加组件

怎样用代码添加一个光?/怎么给物体添加组件?
首先,要清楚,不能直接new一个组件,

     light = new Light();//错错错错错错错错错错错错错错错添加组件不能直接自己 new 
  • 1

要用AddComponent方法加,此方法里面会自己对相关组件实例化
gameObject.AddComponent< Type >()//返回值即此组件的引用

            //1、创建物体
            GameObject lightGO = new GameObject();// 嗯,只有GameObject我们可以自己new
            //2、添加组件
            //这里的返回值就是对这个light 的 引用
            Light light=lightGO.gameObject.AddComponent<Light>();
            light.color = Color.red;
            light.type = LightType.Point;//点光源

            //或者直接给自身游戏对象添加组件
            this.gameObject.AddComponent<Light>();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
有关通过Tag查找游戏对象

[慎用]GameObject.Find(“游戏对象名称”);//在场景中根据名称查找物体,往上、下多少辈都能查找 相当于大海里捞针
—— ps:transform.Find(“游戏对象名称”);//这个可以用 只找孩子
GameObject.FindGameObjectsWithTag(“Enemy”); //获取所有使用该标签的物体(游戏场景里的所有),返回的是Gameobject数组
[首选]GameObject.FindWithTag(“Enemy”);//获取使用该标签的物体(单个 应该是从上往下数首个)

            //在场景中根据名称查找物体(慎用)
            //往下多少辈都能查找 相当于大海里捞针
            GameObject.Find("游戏对象名称");

            //这个可以用 只找孩子
            transform.Find("游戏对象名称");

            //获取所有使用该标签的物体(游戏场景里的所有)
            //返回的是Gameobject数组
            GameObject[] allEnemy = GameObject.FindGameObjectsWithTag("Enemy");
            print(allEnemy.Length);
          
            //获取使用该标签的物体(单个 应该是从上往下数首个)
            //多用这个,毕竟Tag比物体名字少多了
           GameObject obj=GameObject.FindWithTag("Enemy");
            print(obj.name);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

Object 基类

【根据组件类型查找对象;克隆物体;加载场景时保留目标对象;删除游戏对象、组件或资源,是所有类的基类】

Object常用属性

name //访问到游戏物体的名称

Object常用方法

//都是静态方法可以直接用
DontDestroyOnLoad();//加载新场景时使目标对象不会被自动销毁
FindObjectOfType< >();//根据类型查找【对象】
FindObjectsOfType< >();// (没有父子物体的限制)
Instantiate();//克隆原始物体并返回克隆物体
Destroy(); //【删除一个游戏对象、组件或资源】

            //加载新场景时使目标对象不会被自动销毁
            DontDestroyOnLoad(transform.gameObject);

            //根据类型查找【对象】 (没有父子物体的限制)
            Object.FindObjectOfType<MeshRenderer>();
            FindObjectsOfType<MeshRenderer>();

            //克隆原始物体并返回克隆物体
            GameObject ga=Instantiate(this.gameObject);

            //销毁对象
            //【删除一个游戏对象、组件或资源】
            Destroy(this.transform);
            //5s后删除对象
            Destroy(gameObject,5);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/104145?site
推荐阅读
相关标签
  

闽ICP备14008679号