【学习笔记】unity脚本学习(五)【常用的方法函数Destroy、Instantiate 、SendMessage、invoke 、Coroutine】

这篇具有很好参考价值的文章主要介绍了【学习笔记】unity脚本学习(五)【常用的方法函数Destroy、Instantiate 、SendMessage、invoke 、Coroutine】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

转载请注明出处:🔗https://blog.csdn.net/weixin_44013533/article/details/130233098
视频参考 极客学院Unity3D视频精讲课程

常用的方法函数

Object体系结构

unitydestroy,unity,unity,笔记
unitydestroy,unity,unity,笔记
可以看到MonoBehaviour继承自Component,Component继承自Object

MonoBehaviour复习

MonoBehaviour官网API
之前学的start awake等都是Message事件响应函数,它们都是我们在脚本中直接使用的回调函数
unitydestroy,unity,unity,笔记

继承的变量

unitydestroy,unity,unity,笔记

继承自Object的方法

unitydestroy,unity,unity,笔记

Destroy 物体的销毁

比较好懂

// 删除gameObject
Destroy(gameObject);
// Removes this script instance from the game object
Destroy(this);
// Removes the rigidbody from the game object
Destroy(GetComponent<Rigidbody>());
// Kills the game object in 5 seconds after loading the object 延迟删除)
Destroy(gameObject, 5);

注意:

  • 删除gameobject也会删除其下所有子物体
DestroyImmediate 立即销毁对象(强烈建议您改用 Destroy)

public static void DestroyImmediate (Object obj, bool allowDestroyingAssets= false);

  • obj 要销毁的对象。
  • allowDestroyingAssets 设置为 true 将允许销毁资源。
    该函数应只在编写 Editor 代码时使用,因为在编辑模式下, 永远不会调用延迟销毁。 在游戏代码中,您应该改用 Object.Destroy。Destroy 始终延迟进行 (但在同一帧内执行)。 使用该函数时要务必小心,因为它可以永久销毁资源! 另请注意,切勿循环访问数组并销毁正在迭代的元素。这会导致严重的问题(这是一条通用的编程实践,而不仅仅是在 Unity 中)。
Object.DontDestroyOnLoad

public static void DontDestroyOnLoad (Object target);
在加载新的 Scene 时,请勿销毁 Object。(scene切换时会释放老场景内存,如果想不释放某个对象,就可以用这个方法)

    void Start()
    {
        DontDestroyOnLoad(gameObject);
    }
    // Update is called once per frame
    [System.Obsolete]
    void Update()
    {
        if(Input.GetKey(KeyCode.Space)){
            //Application.LoadLevel("emp");
            Application.LoadLevel(1);
        }
    }

可以用场景名称,也可以用scenes in build中scene的index
unitydestroy,unity,unity,笔记
如图,实现点击空格切换场景,但脚本所绑定的cube未被释放内存(这个方法可以用在比如切换场景但背景音乐丝滑过渡的场合)
unitydestroy,unity,unity,笔记
注意:

  • 物体一个组件不释放,那么这个物体和子物体都将得到保留
    void Start()
    {
        DontDestroyOnLoad(GetComponent<Rigidbody>());
    }

unitydestroy,unity,unity,笔记
脚本绑定到cube
unitydestroy,unity,unity,笔记
但如果但将脚本挂cube(1)或者cube(2)上,则DontDestroyOnLoad对这三个cube都不产生效果,所以要求不释放内存的对象没有父对象

Object.Instantiate 物体的生成

public static Object Instantiate (Object original);
public static Object Instantiate (Object original, Transform parent);
public static Object Instantiate (Object original, Transform parent, bool instantiateInWorldSpace);
public static Object Instantiate (Object original, Vector3 position, Quaternion rotation);
public static Object Instantiate (Object original, Vector3 position, Quaternion rotation, Transform parent);
参数

  • original 要复制的现有对象。
  • position 新对象的位置。
  • rotation 新对象的方向。
  • parent 将指定给新对象的父对象。
  • instantiateInWorldSpace When you assign a parent Object, pass true to position the new object directly in world space. Pass false to set the Object’s position relative to its new parent.

描述
克隆 original 对象并返回克隆对象。
此函数会通过与编辑器中的复制命令类似的方式创建对象的副本。如果要克隆 GameObject,则可以指定其位置和旋转(否则,这些默认为原始 GameObject 的位置和旋转)。如果要克隆 Component,则也会克隆它附加到的 GameObject(同样可指定可选的位置和旋转)。

克隆 GameObject 或 Component 时,也将克隆所有子对象和组件,它们的属性设置与原始对象相同。
注意

  • 使用instantiate方法生成对象,比较消耗资源,尽管可以配合使用destroy销毁对象释放。后续优化可以使用对象池概念(估计类似java连接池这种)
  • 一般不生成场景中存在的物体,因为它需要加载,在其他场景就没法复用——>使用prefab预设体(hierarchy中将对象拉到assets中形成pref ab)
类子弹生成案例
    public Object obj;
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space)){
            //Quaternion.identity:旋转角默认0
            Object.Instantiate(obj,new Vector3(0,5,0),Quaternion.identity);
        }
    }

unitydestroy,unity,unity,笔记
添加物体自销毁、施加一个脉冲力

    public float survivalTime = 3;
    void Start()
    {
        Destroy(gameObject,survivalTime);
    }
    public Rigidbody rig;
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space)){
            //Quaternion.identity:旋转角默认0
            // 声明为Rigidbody,注意这里输入的是Rigibody,返回的也是Rigibody,如果输入GameObject输出Rigibody,会报NullReferenceException异常
            Rigidbody copyRig = Object.Instantiate(rig,new Vector3(0,5,0),Quaternion.identity) as Rigidbody;
            copyRig.AddForce(Vector3.forward*5,ForceMode.Impulse);
        }
    }

unitydestroy,unity,unity,笔记

继承自Component的方法

Component.tag和GameObject.tag都表示此游戏对象的标签。

Component.CompareTag 比较tag

public bool CompareTag (string tag);
Checks the GameObject’s tag against the defined tag.

注意比较tag有两种方法

  • CompareTag(“a”)比xxx.tag == "a"高效,原因是省去tag赋值的操作
消息推送
  • SendMessage
  • SendMessageUpwards
  • BroadcastMessage

使用场景:只要我们得到了一个类的引用,便可以向它的子类/类本身/父类传递某些消息,最终达到直接执行某个函数的目的,这样非常方便实现一个引用,简化开发复杂程度。

Component.SendMessage 消息推送

public void SendMessage (string methodName);
public void SendMessage (string methodName, object value);
public void SendMessage (string methodName, object value, SendMessageOptions options);
public void SendMessage (string methodName, SendMessageOptions options);

参数

  • methodName 要调用的方法的名称。
  • value 该方法的可选参数。
  • options 如果目标对象没有为消息实现该方法,是否应报错?

描述
调用此游戏对象中的每个 MonoBehaviour 上名为 methodName 的方法。
通过具有零参数,该接收方法可选择忽略此参数。 如果选项设置为 SendMessageOptions.RequireReceiver,则在任何组件均未拾取此消息时输出错误。
注意,不会将消息发送到非活动对象(即,在 Editor 中或使用 GameObject.SetActive 函数已停用的对象)。

Component.SendMessageUpwards

public void SendMessageUpwards (string methodName, SendMessageOptions options);
public void SendMessageUpwards (string methodName, object value= null, SendMessageOptions options= SendMessageOptions.RequireReceiver);

调用此游戏对象中的每个 MonoBehaviour 上或此行为的每个父级上名为 methodName 的方法。

Component.BroadcastMessage

public void BroadcastMessage (string methodName, object parameter= null, SendMessageOptions options= SendMessageOptions.RequireReceiver);
public void BroadcastMessage (string methodName, SendMessageOptions options);

调用此游戏对象或其任何子项中的每个 MonoBehaviour 上名为 methodName 的方法。

案例

up说比如足球踢到某个物体,那么就可以用这个方法触发被状物体的某个函数。
这几个方法使用的是反射方式,类似监听者模式,是官方提供的方法,后续应该会有自己实现的更高效的使用监听者模式实现的方法(delegate +event方式)。

这个sendMessage看起来非常重要,后续花个时间做个专题,这里就简单过一下。

MonoBehaviour的invoke方法

Invoke 延迟执行函数

public void Invoke (string methodName, float time);
在 time 秒后调用 methodName 方法。
注意:

  • invoke 的time是根据游戏的时间轴变化的,改变timeScale延迟会相应改变
  • 被调用的方法不能有参数
   public GameObject obj;
    public GameObject obj2;
    public float timeDelay = 2;
    public float myTimeScale = 1;

    // Update is called once per frame
    void Update()
    {
        Time.timeScale = myTimeScale;
        if(Input.GetKeyDown(KeyCode.Space)){
            Object.Instantiate(obj2,new Vector3(0,5,0),Quaternion.identity);
            Invoke("spawnCube",timeDelay);
        }
    }
    void spawnCube(){
        GameObject copyObj = Object.Instantiate(obj,new Vector3(0,5,0),Quaternion.identity);
            Rigidbody rig = copyObj.GetComponent<Rigidbody>();
            rig.AddForce(Vector3.forward*5,ForceMode.Impulse);
    }
    private void OnGUI() {
        GUILayout.TextArea("gameTime:" + Time.time.ToString());
        GUILayout.TextArea("realTime:" + Time.realtimeSinceStartup.ToString());
    }

unitydestroy,unity,unity,笔记

InvokeRepeating

public void InvokeRepeating (string methodName, float time, float repeatRate);
time 秒后调用 methodName 方法,然后每repeatRate秒调用一次。

*注意:*如果将时间刻度设置为 0,该函数不起作用。

CancelInvoke

public void CancelInvoke ();
取消该 MonoBehaviour 上的所有 Invoke 调用。

IsInvoking

public bool IsInvoking (string methodName);
是否有任何待处理的 methodName 调用?

MonoBehaviour的Coroutine方法

Coroutine协同执行程序

  • 在主程序运行时同时开启另一段逻辑处理,来协同当前程序的执行
  • 开启协同程序就是类似于开启一个线程
  • 但是协程并不是线程

参数IEnumerator对象,通常有三种方式获得。

  • 第一种方式,也是最常用方式,是使用带有yield指令的协程函数。
    unitydestroy,unity,unity,笔记
    Unity-C# 协程 IEnumerator 用法梳理
  • 第二种方式,继承Unity提供的类CustomYieldInstruction,但其实CustomYieldInstruction是实现了IEnumerator。
  • 第三种方式,就是自己实现IEnumerator接口,手动new出一个IEnumerator接口实现类。(后面测试会用到这个类)
StartCoroutine 启动协程。

public Coroutine StartCoroutine (IEnumerator routine);
启动协程。

public float step = 0.01f;
    private void OnMouseDown() {
        StartCoroutine(Move(step));
    }
    IEnumerator Move(float step){
        for(int i=0;i<500;i++){
            this.transform.Translate(step,0,0);
            yield return null;
        }
        this.transform.position = new Vector3(0,1,0);
        Debug.Log(this.name +"移动结束");
    }

unitydestroy,unity,unity,笔记

StopAllCoroutines

public void StopAllCoroutines ();
停止在该行为上运行的所有协同程序。

StopCoroutine

public void StopCoroutine (string methodName);
public void StopCoroutine (IEnumerator routine);
public void StopCoroutine (Coroutine routine);
停止在该行为上运行的第一个名为 methodName 的协同程序或存储在 routine 中的协同程序。

小结

这里message传递,协程和方法延迟调用这三个还有待继续深入文章来源地址https://www.toymoban.com/news/detail-759497.html

到了这里,关于【学习笔记】unity脚本学习(五)【常用的方法函数Destroy、Instantiate 、SendMessage、invoke 、Coroutine】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity学习笔记——ScrollView常用技巧

    在学习UI过程中反复接触ScrollView,遇到了很多使用问题,有许多技巧需要记录下来 如果不使用横向滑动,只需要将ScrollView中的Horizontal取消即可,虽然在Unity视图中还会存在,但运行游戏后就会消失;纵向滑动条同理 另外,如果你的Content的范围设置太小,也是不会显示滑动条

    2024年02月09日
    浏览(53)
  • unity2.5D动画学习笔记(一):添加人物四向移动动画及脚本

    突发奇想要做游戏,但是么得基础,捣鼓几天,算是摸到属于自己路子学习unity了,很多东西百度能找到,但是好复杂,完全不懂文章里过程的本质是哪里,遂自己写文章记录在此过程中的丁零笔记 注:此为空中阁楼,无基础可言,是自己从0到1的过程,内容粗糙,自己理解

    2023年04月08日
    浏览(74)
  • 网络安全学习笔记——SQL常用函数

    version(): 查询数据库的版本 user():查询数据库的使用者 database():数据库 system_user():系统用户名 session_user():连接数据库的用户名 current_user:当前用户名 @@datadir:读取数据库路径 @@basedir:mysql安装路径 @@version_compile_os——操作系统版本 group_concat(): 连接一个组的所有字符

    2024年02月14日
    浏览(42)
  • Unity Instantiate的用法

    之前总结Unity实例化物体的文章:Unity 实例化物体以及赋予到父物体之下-CSDN博客 现在回头看来,感觉总结得不够全面,尤其关于Instantiate的用法,过于简陋了。 关于Instantiate,它实际上有10个语法: Object Object.Instantiate(Object original); Object Object.Instantiate(Object original,Transform pa

    2024年02月05日
    浏览(31)
  • 如何使用Unity的Instantiate

    刚开始学习游戏开发的时候,对于实例化的方式一直模棱两可,看别人的例子有时用到new,有时又用到Instantiate。new大家熟悉的一种用法就是创建一个对象,一般用于类的实例化; Instantiate是Unity里的一种方法,一般用于对Prefab(预制体)的实例化 。下面主要介绍Instantiate的用

    2024年02月09日
    浏览(36)
  • 【AI】《动手学-深度学习-PyTorch版》笔记(三):PyTorch常用函数

    返回一维张量(一维数组),官网说明,常见的三种用法如下 tensor.shape:查看张量的形状 tensor.reshape:返回改变形状后的张量,原张量不变

    2024年02月15日
    浏览(50)
  • 强化学习价值函数方法笔记

    在强化学习中,价值函数(Value Function)是一个核心概念,它用于衡量在不同状态或状态-动作对下,一个智能体(agent)可以获得的预期累积奖励。价值函数对于智能体做出决策和学习行为策略非常重要。 价值函数可以分为两种类型: 状态价值函数(State Value Function):记作

    2024年02月15日
    浏览(37)
  • unity学习笔记-延迟执行方法

    我辣鸡,不会用

    2024年02月06日
    浏览(36)
  • Python学习笔记(三) 数据结构与常用方法

    数据结构是计算机内部对数据按一定的结构进行排列组织的存放,以达到快速查找,提取但目的 常见的数据结构有:列表、字典、元组、集合、双端队列、区间 通过键值对key=value的形式保存元素的一种数据结构 一种不可变的数据结构,一旦创建不能添加、删除与修改 出于数

    2024年02月04日
    浏览(51)
  • 【Unity函数执行顺序(Unity脚本生命周期函数)】

    温故而知新,下面我将介绍Unity入门需要了解的常用生命周期函数 生命周期函数就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中 会通过反射自动调用的一些特殊函数。 下面是对各个函数解锁 a.调用情况: 1.在加载场景时初始化包含脚本激活状态的GameObject时。

    2023年04月23日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包