当前位置: 首页 > article >正文

Unity 从零开始的框架搭建1-3 关于命令模式的一些思考

Unity 从零开始的框架搭建1-2 事件的发布-订阅-取消的小优化及调用对象方法总结[半干货]-CSDN博客

         本人水平有限 如有不足还请斧正,该文章专栏是向QFrameWork作者凉鞋老师学习总结得来,吃水不忘打井人,不胜感激  

         关于此模式我曾实现过,但是我看了凉鞋老师的课后有了一些思考C# x Unity 从玩家控制类去分析命令模式该如何使用_unity c# 命令模式-CSDN博客

0.场景引入 

        就比如场景中有一些敌人

        有一些敌人被点击到了就消失有些就随机移动

        引入ICommand

public interface ICommand 
{
   public void Execute();
}

         实现Icommand

using UnityEngine;

public class Enemy : MonoBehaviour {
    private ICommand _moveCommand;
    private ICommand _destroyCommand;

    void Start() {
        _moveCommand = new MoveCommand(this);
        _destroyCommand = new DestroyCommand(this);
    }

    // 被点到就消失
    public void OnMouseDown() {
        if(this.CompareTag("EnemyR"))
            _moveCommand.Execute();
        else
        _destroyCommand.Execute();
    }
}
public struct MoveCommand : ICommand {
    private Enemy _enemy;

    public MoveCommand(Enemy enemy) {
        _enemy = enemy;
    }

    public void Execute() {
        float x = Random.Range(-5, 5);
        float z = Random.Range(-5, 5);
        _enemy.transform.position = new Vector3(x, 0, z);
    }
}

public struct DestroyCommand : ICommand {
    private Enemy _enemy;

    public DestroyCommand(Enemy enemy) {
        _enemy = enemy;
    }

    public void Execute() {
        Object.Destroy(_enemy.gameObject);
    }
}

1.ICommand类做到了什么?

        这可能就要扯到MVC了,你一定要搞清楚M和C的区别

        M:做任务的

        C:控制的,下命令的

所以---------------------------------------------------------------------------------------------------------------------------

        没有使用命令模式时:
•    模型(Model):Enemy类(包含了移动和销毁的逻辑)
•    视图(View):Unity中的3D物体(敌人)
•    控制器(Controller):Enemy类中的OnMouseDown方法(包含了与用户交互的代码)

        
        使用命令模式后:
•    模型(Model):具体的命令类(例如MoveCommand和DestroyCommand)
•    视图(View):Unity中的3D物体(敌人)
•    控制器(Controller):Enemy类中的OnMouseDown方法(负责调用命令)

 ---------------------------------------------------------------------------------------------------------------------------

 2.每次执行都去new会不会造成性能浪费?

        我是说在这个场景之中,不得不去“new”对象

   void Update() {
       if (Input.GetMouseButtonDown(0)) {
           if (this.CompareTag("EnemyR")) {
               ICommand moveCommand = new MoveCommand(this);
               moveCommand.Execute();
           } else {
               ICommand destroyCommand = new DestroyCommand(this);
               destroyCommand.Execute();
           }
       }
   }

        对比这篇文章:C# x Unity 从玩家控制类去分析命令模式该如何使用_unity c# 命令模式-CSDN博客
        我在这里进行了小小的变动

原因: 内存上栈比堆快 AI说的

        栈在内存分配和释放操作上比堆快,主要基于以下原因:

         ### 1. 分配机制

        - **栈的分配**:栈的内存分配非常简单直接,类似于往栈中压入数据。栈有一个栈顶指针,当有新的数据(如局部变量、函数调用信息等)需要存储时,栈顶指针移动相应的字节数,为新数据腾出空间。这个过程几乎不涉及复杂的查找或计算,是一个高效的线性操作。例如,在一个函数中定义一个 `int` 类型的局部变量,栈顶指针只需移动4字节(假设为32位系统),即可完成该变量的内存分配。

         - **堆的分配**:堆的内存分配则相对复杂。堆内存是一块连续的、较大的内存区域,但被分配出去的内存块大小不一且分布离散。当程序请求在堆上分配内存时,堆管理器需要遍历已分配和未分配的内存块列表,寻找一块大小合适的空闲内存块。如果没有恰好合适的内存块,可能还需要进行内存分割等操作。这种查找和处理过程会消耗更多的时间和资源。例如,在堆上分配一个动态数组,堆管理器需要找到足够大的连续内存空间,如果没有合适的,可能需要将一个较大的空闲块分割成满足数组大小的部分和剩余的空闲块。

        ### 2. 释放机制

        - **栈的释放**:栈的内存释放遵循后进先出(LIFO)原则,如同从栈中弹出数据。当一个函数执行结束,其对应的栈帧会被销毁,栈顶指针会恢复到函数调用前的位置,栈上为该函数局部变量等分配的内存空间自动被释放。这个过程不需要额外的复杂操作,直接移动栈顶指针即可,非常高效。例如,函数执行完毕后,函数内定义的局部变量(存储在栈上)所占用的内存会随着栈帧的弹出而立即释放。

         - **堆的释放**:堆上对象的内存释放较为复杂,尤其是在使用垃圾回收机制(如在C#、Java等语言中)的环境下。当一个对象不再被引用时,它不会立即被释放。垃圾回收器需要定期运行,通过标记 - 清除、复制、标记 - 整理等算法来识别和回收不再使用的对象。这个过程涉及到对整个堆内存的扫描、标记存活对象、移动和整理内存等操作,不仅会暂停应用程序的正常执行(产生“stop - the - world”现象),而且算法本身也比较复杂,消耗较多的CPU时间和资源。即使在手动管理内存的语言(如C++)中,释放堆内存也需要程序员手动调用 `delete` 或 `free` 等函数,并且要确保释放的时机和顺序正确,否则容易引发内存泄漏等问题。

        ### 3. 内存结构特点 

         **栈的结构**:栈的内存结构相对简单和紧凑,数据按照顺序依次存储在栈上,内存布局相对固定。这种简单的结构使得栈的内存管理效率高,访问速度快。例如,在栈上访问一个局部变量,由于其内存位置是在栈顶附近,根据栈顶指针和变量在栈帧中的偏移量,可以快速定位到变量的内存地址。

         - **堆的结构**:堆的内存结构较为复杂,由于频繁的分配和释放操作,容易产生内存碎片化问题。即堆中会出现许多不连续的空闲内存块,虽然总的空闲内存空间可能足够,但由于不连续,无法满足某些较大内存块的分配请求。为了应对碎片化问题,堆管理器需要额外的机制来管理和整理内存,这进一步增加了堆内存管理的复杂性和开销。

•    struct是值类型,分配在栈上,通常会有更好的性能,特别是在频繁创建和销毁对象的情况下,因为它们不需要垃圾回收
•    class是引用类型,分配在堆上,可能会导致更多的垃圾回收开销,特别是在频繁创建和销毁对象的情况下。

        不信也没办法,我不知道怎么去追踪每一次点击之后:"上一个失去引用的对象 在 内存中被释放" 这个过程

        


http://www.kler.cn/a/468030.html

相关文章:

  • shell脚本总结2
  • 如何利用PHP爬虫按关键字搜索淘宝商品
  • Kafka 消费者专题
  • 【踩坑指南2.0 2025最新】Scala中如何在命令行传入参数以运行主函数
  • JavaScript系列(8)-- Array高级操作
  • weblogic安装 12.2.1.4.0 单机
  • 四、VSCODE 使用GIT插件
  • 综合能源建模:理论、方法与实践
  • 行为模式3.迭代器模式
  • rsync命令常用同步方案
  • (leetcode算法题)528. 按权重随机选择
  • 记录一下core-js安装报错(core-js/modules/es.array.push.js core-js/modules/es.error.cause.js)
  • 简历_专业技能_熟悉Redis常用数据结构及其操作命令
  • 现代光学基础4
  • 如何下载 Chrome 历史版本 - 完整指南
  • SwiftUI 撸码常见错误 2 例漫谈
  • EPS32基础篇开发
  • vue 如何实现复制和粘贴操作
  • 获取钉钉微应用免登授权码(h5微应用)
  • 创建.net core 8.0项目时,有个启用原生AOT发布是什么意思
  • Oracle 创建本地用户,授予权限,创建表并插入数据
  • SQL中,# 和 $ 用于不同的占位符语法
  • 在 Python 中合并多个 Word 文档
  • spring防止重复点击,两种注解实现(AOP)
  • [开源]C++代码分享
  • 基于Spring Boot微信小程序的房产交易租赁服务平台