HOME
BLOG
unity 组件思想
9月 07 2022

组件介绍

| 组件概念

可替换性、可直接使用

| 游戏组件

系统 - 如UI系统,有按钮、图片、下拉框,这些功能都是不同的组件,在一起就组成了 UI系统


Unity内置简易模型和材质

| 模型介绍

层级面板 -> 右键 -> 3Dobject -> 各种模型

| 材质介绍

顶点组成的网格数据


Scene 界面游戏物体操作

| 工具栏

手型工具:Q & 鼠标中键,用于拖动场景

移动工具:W ,用于移动模型的位置

旋转工具:E ,用于旋转模型

缩放工具:R ,用于放大缩小模型

移动&缩放工具:Y ,可以同时移动、旋转模型

| 约束与吸附

变化拘束:移动、缩放、选择时按住 Ctrl (拘束程度在 Edit -》 Grid And Snap 中可以设置)

模型吸附:选择模型后按 V,选择吸附位置在拖拽到需要吸附的位置上

复制模型:Ctrl + C

粘贴模型:Ctrl + V

快速复制:Ctrl + D

快速定位:F


自定义组件

| 为什么要自定义组件

我们写的组件大多和游戏逻辑有关,比如玩家控制脚本。

| 如何自定义组件

项目面板右键 -> 创建 -> C#脚本 ->拖拽

| 注意事项

  • 继承 MonoBehaviour 的类都是组件

  • 只有组件可以挂载到游戏物体身上

  • Inspector面板 和 C# 一同使用

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_4Demo : MonoBehaviour
{
    public string Name;
    public int ID;

    void Start()
    {
        Debug.Log(666);
    }
}

Transform组件

| 组件介绍

三个主要数值:

  • Position:位置

  • Rotation:旋转

  • Scale:缩放

| 组件常用属性和方法

属性:

childCount :子物体的数量

parent :父物体的 Transform 组件

root :最高级别父物体

postioneulerAngleslocalScale

方法:

Find(string) :查找子物体

Translate(Vector3) :朝着一个坐标移动

Rotate(Vector3) :旋转一个角度

LookAt(Transform) :看向目标

| 组件的特殊性

可以直接访问 Transform 组件

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_5TransformDemo : MonoBehaviour
{

    private float num = 0;

    void Start()
    {
        #region 属性
        //print(transform.childCount);
        //print(transform.parent);
        //print(transform.root);
        //print(transform.eulerAngles); // 旋转

        //print("当前坐标:"+transform.position);
        //print("当前旋转:" + transform.rotation);
        //print("当前缩放:" + transform.localScale);

        //transform.position = new Vector3(num, 10, 10);
        //transform.rotation = new 
        //num += 0.01f;
        #endregion

        #region 方法
        //print(transform.Find("C"));
        //transform.Translate(new Vector3(-0.01f, 0, 0));
        //transform.Rotate(new Vector3(3, 0, 0));
        //transform.LookAt(transform.parent);
        #endregion
    }
}

GameObject

| GameObject 是什么

在 层级面板 中的都是游戏对象或者说游戏物体。

| 组件中的 gameobject

组件中可以使用来自基类继承 gameObject 属性 直接访问脚本所在的游戏物体,类似 transform。

  1. gameObject:组件所在游戏物体

  2. transform:组件所在游戏物体的transform组件

| GameObject 常用属性和方法

属性:

name :游戏物体名称,和层级面板中等同

tag :游戏物体的标签

activeInHierarchy :显示状态

transform :这个游戏物体的变换组件

方法:

static GameObject Find(string path) :一个静态方法,查找游戏物体

GetComponent<T>() :获取游戏物体身上的组件,T代表要查找的类型,类似方法有很多

SetActive(bool) :修改显示状态

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_6Demo : MonoBehaviour
{
    private GameObject gO;
    public Transform ts;

    void Start()
    {
        // 获取当前组件所在的游戏物体
        //print(gameObject);
        //print(gameObject.transform.position);
        //print(gO.transform.position);

        //print(ts);
        //print(ts.position);
        //print(ts.gameObject);


        //print(gameObject.name);
        //print(gameObject.tag);

        //print(gameObject.activeInHierarchy);
        //print(gO.activeInHierarchy);

        //gO = GameObject.Find("C/D");
        //print(gO.transform.localPosition);


        //GameObject go = gameObject.GetComponent<GameObject>(); //error
        //print(go.name);

        Transform temptransform = gameObject.GetComponent<Transform>();
        BoxCollider boxCollider = gameObject.GetComponent<BoxCollider>();
        print(temptransform.position);
        print(boxCollider.isTrigger);

        gameObject.SetActive(false);
    }
}

预制体

| 概念

预先制作好的游戏物体。

如:lol小兵,远程近战,什么时候放,固定ai逻辑。

| 创建

将游戏物体放在Assets面板。

| 使用

将预制体从项目面板拖拽到层级面板来达到复用效果。

  1. 接近“引用关系”

  2. 预制体被删除,不影响游戏物体(但会变成红色)。右键里可以选择取消引用关系

  3. 双击资源文件夹里的预制体或点击预制体小箭头,进入“异世界”进行编辑

| 修改

预制体可以套娃,也就是预制体套预制体。

变体:

如果游戏物体已经是预制体,Unity会弹窗提醒我们选择创建模式

原始预制体:一个完全独立的预制体

预制体变体:旧的预制体变化,变体也会发生变化,但是变体保留和旧预制体不同的部分


Unity生命周期函数

| 概念

指一个组件从激活到销毁的整个过程。

| 常用生命周期函数

Awake() :唤醒事件,一开始就执行,只执行一次。

OnEnable() :启用事件,每次启用都执行一次。当脚本组件被启用的时候执行一次

Start() :开始事件,执行一次

FixedUpdate() :固定更新事件,执行N次,每0.02s 执行一次。所有物理相关的更新都在这个事件中处理

Update() :更新事件,执行N次,每帧执行一次

LateUpdate() :稍后更新事件,执行 N 次,在 Update() 事件执行完毕后再执行

OnDisable() :禁用事件,每次禁用都执行一次。在 OnDestroy() 事件也会执行

OnDestroy() :销毁事件,执行一次。当组件被销毁时执行

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_8Demo : MonoBehaviour
{
    private void Awake()
    {
        // 初始化一次
        print("Awake");
    }

    private void OnEnable()
    {
        // 如 背包
        print("OnEnable");
    }

    void Start()
    {
        print("Start");
    }

    void Update()
    {
        // 每帧执行一次
        print("Update");
        // 我渲染上一帧的时间
        //print(Time.deltaTime);
    }

    private void LateUpdate()
    {
        print("LateUpdate");
    }

    private void FixedUpdate()
    {
        print("FixedUpdate");
    }

    private void OnDisable()
    {
        print("OnDisable");
    }

    private void OnDestroy()
    {
        print("OnDestroy");
    }
}

Invoke

| 函数使用

  • Invoke 是调用、执行的意思

  • Invoke(string methodName, float time) :输入一个方法名称,过个几秒 来执行一次

    • methodName:方法名称

    • time:几秒后执行

  • InvokeRepeating(string methodName, float time, float repeatRate) :重复调用

    • methodName:方法名称

    • time:几秒后执行

    • repeatRate:重复间隔时间

  • CancelInvoke(string methodName) :取消调用,使用无参重载就是取消全部

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_9Demo : MonoBehaviour
{
    void Start()
    {
        // 3s 后执行一个方法/行为
        //Invoke("Demo", 3);

        // 2s 后,每间隔1s执行一次
        InvokeRepeating("Demo", 2, 1);

        // 5s 后执行取消Demo
        Invoke("CancelDemo", 5);
    }

    private void CancelDemo()
    {
        CancelInvoke("Demo");
    }

    public void Demo()
    {
        print("Demo");
    }
}

协程

| 概念

协同程序,并不是多线程。

要有一个主程序,这个主程序就是生命周期函数。

为什么需要?主程序已经在执行某个任务,希望 “同时运行” 其他逻辑,这里的同时并不是多线程意义的,只是感官上同时。

| 函数的定义

协程特定返回值: IEnumerator

返回: yield return

协程不会因为前面返回则不执行后面的代码

小演示:

    // 常规函数
    public int GetNum()
    {
        return 0;
    }
    // 协程函数
    public IEnumerator Demo()
    {
        print("先执行的");

        // 等待 1s
        yield return new WaitForSeconds(1.0f);
        print("后执行的");

        // 下一帧继续执行
        yield return null;
        print("最后执行的");
    }

| 函数的使用

  • Coroutine StartCoroutine(Demo("这是参数")) :执行一个协程,参数直接调用协程方法即可。可以用一个变量接受返回值用于后续停止该协程。

  • 我们在生命周期函数中调用协程,但是协程的运行顺序和主程序无关,可以理解成开了一个分支专门运行这个协程,如果我们打开了多个协程,这些协程之间也无关。

| 函数的停止

  • StopAllCoroutines() :结束全部协程

  • StopCoroutine(demo()) :结束某个协程程序

  • StopCoroutine(IEnumerator routine) 和调用协程一样使用,但是如果协程有参数不要使用这个

  • StopCoroutine(Coroutine routine) :参数填写协程变量

  • StopCoroutine(string methodName) :参数填写协程方法的名

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_10Demo : MonoBehaviour
{
    void Start()
    {
        //StartCoroutine("Demo");

        //Coroutine cor = StartCoroutine(Demo(10));
        //StopCoroutine(cor);

        //StartCoroutine(Demo2());
        StartCoroutine(Demo3());
        StartCoroutine(Demo4());
    }

    // 常规函数
    public int GetNum()
    {
        return 0;
    }

    // 协程函数
    public IEnumerator Demo(int num)
    {
        print(num);
        print("先执行的");

        // 等待 1s
        yield return new WaitForSeconds(3f);
        print("后执行的");

        // 下一帧继续执行
        yield return null;
        print("最后执行的");
    }

    // 协程函数
    public IEnumerator Demo2()
    {
        while (true)
        {
            // 暂停 0.1s
            yield return new WaitForSeconds(0.01f);
            transform.Rotate(new Vector3(5, 0, 0));
        }
    }

    // 协程函数
    public IEnumerator Demo3()
    {
        transform.position = new Vector3(10, 10, 10);
        yield return Demo2();
    }

    // 协程函数
    public IEnumerator Demo4()
    {
        // 5s 之后取消协程
        yield return new WaitForSeconds(5);
        // 取消全部
        StopAllCoroutines();
    }
}

常用工具类

| 数学工具类

  • Mathf.Abs(int num) :返回绝对值

  • Mathf.Max(int a,int b) :返回更大的值

  • Mathf.Min(int a,int b) :返回最小的值

  • Mathf.Round(2.5f) :四舍六入,五取偶数

  • Mathf.Ceil(2.5f) :返回向上取整的值

  • Mathf.Floor(2.5f) :返回向下取整的值

  • Random.Range(0.5) :返回随机值

    • (1)如果是int 重载:返回0-4的随机值,包含0;不包含5

    • (2)如果是float重载:返回0-5的随机值,包含0并且包含5

| 时间工具类

只读:

  • Time.time :表示从游戏运行到现在的时间,会随着游戏的暂停而停止计算

  • Time.deltaTime :表示从上一帧到当前帧的时间,以 秒 为单位

  • Time.realtimeSinceStartup :表示自游戏开始后的总时间,即使暂停也会增加,也就是现实时间

读写:

  • Time.timeScale :时间缩放,默认值为 1,若设置 <1,表示时间减慢,若设置 >1,表示时间加快,0 意味着游戏暂停

演示:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class L2_11Demo : MonoBehaviour
{
    void Start()
    {
        #region math
        //int num1 = Mathf.Abs(-6);
        //int num2 = Mathf.Max(3,4,5,10,20);
        //int num3 = Mathf.Min(3,4,5,10,20);
        //float num4 = Mathf.Round(2.5f);
        //float num5 = Mathf.Ceil(2.4f);
        //float num6 = Mathf.Floor(2.4f);

        //print(num1);
        //print(num2);
        //print(num3);
        //print(num4);
        //print(num5);
        //print(num6);

        // 0~4 因为包含左边,不包含右边
        //int num1 = Random.Range(0, 5);
        //print(num1);

        //float num2 = Random.Range(0, 5.0f);
        //print(num2);
        #endregion

        #region time
        Time.timeScale = 3;
        #endregion
    }
    private void Update()
    {
        #region time
        //print(Time.time);

        // 每帧上升 1m
        //transform.Translate(new Vector3(0, 1f, 0));

        // 每 秒 上升 1m ; 方向 * 速度 * 一帧花费的时间
        //transform.Translate(new Vector3(0, 1f, 0) * 1 * Time.deltaTime);

        //print(Time.deltaTime); 

        print("游戏时间:"+Time.time);
        print("帧时间:"+Time.deltaTime);
        print("现实时间:"+Time.realtimeSinceStartup);
        #endregion
    }
}


👾森木清树👾

Unity Study