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.mzph.cn/news/891835.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UVM :uvm_sequence_item property and methods

transaction是uvm_sequence_item的一个子类。 topic transaction介绍 uvm_sequence_item override Set_type_override:同类型替换 Set_inst_override:同例化替换

SpringBoot原理分析-1

SpringBoot原理分析 作为一个javaer,和boot打交道是很常见的吧。熟悉boot的人都会知道,启动一个springboot应用,就是用鼠标点一下启动main方法,然后等着就行了。我们来看看这个main里面。 SpringBootApplication public class E…

前端(API)学习笔记(CLASS 4):进阶

1、日期对象 日期对象:用来表示事件的对象 作用:可以得到当前系统时间 1、实例化 在代码中发现了new关键字,一般将这个操作称为实例化 创建一个时间对象并获取时间 获得当前时间 const datenew Date() 使用日志查看,得到的…

力扣刷题:二叉树OJ篇(上)

大家好,这里是小编的博客频道 小编的博客:就爱学编程 很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!! 目录 1.单值二叉树(1)题目描…

4.1.2 栈和队列(二)

文章目录 队列的定义队列的基本运算队列的存储结构 队列的定义 队列先进先出,仅允许一端插入、一端删除 队尾(Rear),插入 队头(Front),删除 队列的基本运算 队列的基本运算 初始化空队列:initQueue(Q)判队空:isEmpty…

【HeadFirst系列之HeadFirst设计模式】第1天之HeadFirst设计模式开胃菜

HeadFirst设计模式开胃菜 前言 从今日起,陆续分享《HeadFirst设计模式》的读书笔记,希望能够帮助大家更好的理解设计模式,提高自己的编程能力。 今天要分享的是【HeadFirst设计模式开胃菜】,主要介绍了设计模式的基本概念、设计模…

Oracle数据库如何找到 Top Hard Parsing SQL 语句?

有一个数据库应用程序存在过多的解析问题,因此需要找到产生大量硬解析的主要语句。 什么是硬解析 Oracle数据库中的硬解析(Hard Parse)是指在执行SQL语句时,数据库需要重新解析该SQL语句,并创建新的执行计划的过程。这…

【GBT32960协议学习系列】GBT 32960协议的背景、目的和适用范围

GBT 32960协议的背景、目的和适用范围 1. GBT 32960协议的背景 GBT 32960是中国国家标准,全称为《电动汽车远程服务与管理系统技术规范》。该标准由中国国家标准化管理委员会发布,旨在规范电动汽车远程服务与管理系统的技术要求,确保电动汽车…

蓝桥杯备赛:C++基础,顺序表和vector(STL)

目录 一.C基础 1.第一个C程序: 2.头文件: 3.cin和cout初识: 4.命名空间: 二.顺序表和vector(STL) 1.顺序表的基本操作: 2.封装静态顺序表: 3.动态顺序表--vector:…

创建并配置华为云虚拟私有云

目录 私有云 创建虚拟私有云 私有云 私有云是一种云计算模式,它将云服务部署在企业或组织内部的私有基础设施上,仅供该企业或组织内部使用,不对外提供服务.私有云的主要特点包括: 私密性:私有云的资源(如…

OWASP ZAP之API 请求基础知识

ZAP API 提供对 ZAP 大部分核心功能的访问,例如主动扫描器和蜘蛛。ZAP API 在守护进程模式和桌面模式下默认启用。如果您使用 ZAP 桌面,则可以通过访问以下屏幕来配置 API: Tools -> Options -> API。 ZAP 需要 API 密钥才能通过 REST API 执行特定操作。必须在所有 …

音视频入门基础:MPEG2-PS专题(3)——MPEG2-PS格式简介

一、引言 本文对MPEG2-PS格式进行简介。 进行简介之前,请各位先下载MPEG2-PS的官方文档。ITU-T和ISO/IEC都分别提供MPEG2-PS的官方文档。但是ITU提供的文档是免费的,ISO/IEC是付费的,所以我们主要阅读ITU提供的官方文档,比如较新…

CPT203 Software Engineering 软件工程 Pt.3 系统建模(中英双语)

文章目录 5. System Modeling(系统建模)5.1 Context models(上下文模型)5.2 Interaction models(交互模型)5.2.1 Use case modeling(用况建模)5.2.2 Sequence diagram(顺…

什么是Kafka的重平衡机制?

Kafka 的重平衛机制是指在消费者组中新增或删除消费者时,Kafka 集群会重新分配主题分区给各个消费者,以保证每个消费者消费的分区数量尽可能均衡。 重平衡机制的目的是实现消费者的负载均衡和高可用性,以确保每个消费者都能够按照预期的方式…

Nginx——反向代理(三/五)

目录 1.Nginx 反向代理1.1.Nginx 反向代理概述1.2.Nginx 反向代理的配置语法1.2.1.proxy_pass1.2.2.proxy_set_header1.2.3.proxy_redirect 1.3.Nginx 反向代理实战1.4.Nginx 的安全控制1.4.1.如何使用 SSL 对流量进行加密1.4.2.Nginx 添加 SSL 的支持1.4.3.Nginx 的 SSL 相关指…

VBA(Visual Basic for Applications)编程|excel|一系列网址或文件路径快速转换为可点击的超链接

很多时候,我们需要把导入的数据某一列转换成超链接,比如URL形式的列。 那么,大批量的情况下,无疑一个个手动点击是非常愚蠢的办法,这个时候我们就需要VBA编程来编写宏,通过编写宏来简化这些手动操作并不现…

【C++】图像模糊处理题目详解与实现

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述题目内容输入格式输出格式示例输入:输出: 💯题目分析问题拆解 💯我的做法代码实现代码分析 💯老师的做法…

在 Ubuntu 22.04 上部署 AppArmor 应用安全教程

在这篇教程中,我们将为你设置 AppArmor 以增强应用程序的安全性。 AppArmor 是一个 Linux 安全模块,允许你限制各个程序的功能。通过强制执行强制访问控制策略,AppArmor 增强了你的应用程序和系统的安全性。 AppArmor 是一个易于使用的 Lin…

Nginx:动静分离

什么是动静分离? 动静分离 是指将网站中的静态资源(如图片、样式表、脚本等)和动态内容(如 PHP、Python、Node.js 等后端生成的内容)分开部署和处理。这样做的好处是可以利用不同的服务器或缓存策略来优化不同类型的资源。 动静分离的好处 提高性能:静态资源可以直接从…

每天40分玩转Django:Django插件开发

Django插件开发 一、插件开发概述表 阶段主要任务技术要点难度准备工作项目结构设计、环境配置项目布局、setup.py★★★☆☆开发实现功能开发、测试编写Django AppConfig、Signals★★★★☆文档编写API文档、使用说明Markdown、reStructuredText★★★☆☆发布部署PyPI打包…