Unity高效编程经验50条分享
1.避免频繁创建临时对象
- 错误写法:obj.transform.position = pos;这种写法会在Lua中频繁返回transform对象导致gc
- 正确写法:创建一个静态方法来设置位置,例如
class LuaUtil {
static void SetPos(GameObject obj, float x, float y, float z) {
obj.transform.position = new Vector3(x, y, z);
}
}
Lua中调用LuaUtil.SetPos(obj, float x, float y, float z);
2.使用泛型必须生成对应类型的wrap文件
- 错误写法:泛型容器直接使用
- 正确写法:_GT(typeof(Dictionary<int, long>)然后生成对应的wrap文件,Lua调用避免产生GC
3.使用C#容器如果知道大概的容量尽量指定初始化大小避免自动扩容产生的GC,例如List、Dictionary、Array
- 错误写法:
Dictionary<ulong, int> buffTableIndexMap = new Dictionary<ulong, int>();
List list = new List();
for (int i = 0; i < 1000; i++)
{
list.Add(i);
} - 正确写法:Dictionary<ulong, int> buffTableIndexMap = new Dictionary<ulong, int>(1000);
List list = new List(1001);
for (int i = 0; i < 1000; i++)
{
list.Add(i);
}
4.注意非托管类型的手动释放
- 错误写法:
- Marshal.AllocHGlobal没有调用Marshal.FreeHGlobal
- 继承自IDisable接口的对象没有手动调用dispose方法
- 正确写法:
- 调用手动释放内存的接口方法
5.注意循环内部
- Unity携程
- 错误写法:大量的使用Coroutine
- 正确写法:使用Update自己管理状态
- 携程等待
- 错误写法:大量使用yield return new WaitForEndOfFrame();或者new WaitForSeconds(3f)或者new WaitForFixedUpdate()等
- 正确写法:保存一个new等待对象,重复使用
- New 对象
- 错误写法:循环内部不断new 对象
- 正确写法:使用对象池循环使用
- 频繁显/隐 SetActive
- 错误写法:频繁调用
- 正确写法:可以移到相机视野外或者设置透明度
- 频繁操作组件方法/属性
- GetComponent
- AddComponent
- Find/FindWithTag
- GetTag
- Camera.main 内部使用的FindGameObjectsWithTag()
- Object.name
- 错误写法:频繁调用
function Update()
local cube = CS.UnityEngine.GameObject.Find(“Cube”)
cube.transform:Rotate(CS.UnityEngine.Vector3(0, 90, 0) * CS.UnityEngine.Time.deltaTime)
end
void Update()
{
Camera.main.orthographicSize //Some operation with camera
} - 正确写法:第一次获取之后缓存之后复用
– 正确写法:在Start中获取组件并缓存
function Start()
self.cube = UnityEngine.GameObject.Find(“Cube”).transform
end
– 在Update中使用缓存的组件
function Update()
self.cube:Rotate(UnityEngine.Vector3(0, 90, 0) * UnityEngine.Time.deltaTime)
end
private Camera cam;
void Start()
{
cam = Camera.main;
}
void Update()
{
cam.orthographicSize;
}
- SendMessage
- 错误写法:直接使用SendMessage方法,内部调用了反射
- 正确写法:使用事件系统
6.字符串处理
- 大量字符串处理
- 错误写法:大量字符串拼接、切割
void Update()
{
text.text = "Player " + name + " has score " + score.toString();
} - 正确写法:尽量减少这种使用场景,用stringbuilder或者用ZString替代(原理:基于Span动态数组实现的0gc字符串方案)
void Start()
{
text = GetComponent();
builder = new StringBuilder(50);
}
void Update()
{
builder.Length = 0;
builder.Append("Player “);
builder.Append(name);
builder.Append(” has score ");
builder.Append(score);
text.text = builder.ToString();
}
- 错误写法:大量字符串拼接、切割
- 大量使用正则表达式
- 使用linq查询
- 错误写法:
var query = from item in myList
where item.SomeProperty == someValue
select item
linq会分配临时空间 - 正确写法:使用for循环遍历
- 错误写法:
7.C#、Lua数据传递交互
- 错误写法:把字符串当key传入,例如:
luaState.Push(MBuffMgr.UID_str);
luaState.Push(buff.UID);
或者
theSubTable[MBuffMgr.UID_str] = buff.UID; - 正确写法:使用数组而不是哈希表,例如
theSubTable[1] = buff.UID
或者使用枚举
theSubTable[(int)EBuffAttr.UID] = buff.UID
8.物理接口的使用
使用物理接口例如:Physics.Raycast、Physics.SphereCast、Physics.BoxCast和Physics.CapsuleCast等方法
- 错误写法:不注意检测长度和检测layer
- 正确写法:正确评估检测长度和设置必要的检测layer,减少不必要的物理计算量
9.同步异步接口使用
例如资源加载接口
- 不推荐写法:使用同步接口
- 推荐写法: 使用异步接口
10.分帧加载
- 错误写法:
length比较大
for (int i = 0; i < prefabs.Length; i++)
{
Instantiate(prefabs[i], parent);
} - 正确写法:
IEnumerator LoadPrefabs()
{
var waitForOneSecond = new WaitForSeconds(1);
for (int i = 0; i < prefabs.Length; i++)
{
yield return waitForOneSecond; // 每帧延迟1秒,可以根据需要调整
Instantiate(prefabs[i], parent);
}
}
11.注意Lua与C#交互传递Unity特有的值类型
Lua调用C#函数时,涉及到参数的传递和返回值的处理,这些操作都会产生性能开销。特别是当涉及到Unity特有的值类型(如Vector3、Quaternion等)时,性能消耗更大,因为需要进行类型转换
-
错误写法:
function Update()
local cube = CS.UnityEngine.GameObject.Find(“Cube”)
cube.transform.rotation = CS.UnityEngine.Quaternion.Euler(0, 45 * CS.UnityEngine.Time.deltaTime, 0)
end -
正确写法
function Start()
self.cubeTransform = CS.UnityEngine.GameObject.Find(“Cube”).transform
end
– 在Update中使用缓存的组件
function Update()
LuaUtil.SetRotation(self.cubeTransform, 0, 45 * UnityEngine.Time.deltaTime, 0)
end
C#的封装方法
public static SetRotation(transform, float x, float y, float z)
12.lua判空的写法
判空防止==误写成=
- 不推荐写法:if theMap == nil then
- 建议写法:if nil == theMap then
13.代码规范
建议按照约定熟成的方式,最大的收益方便搜索
- 驼峰命名
- 左右空格
- 枚举类型使用E开头
空格不要多也不要少
错误写法:table[i +1] =1
正确写法:table[i + 1] = 1
14.不要写立即数
影响代码阅读和统一修改
- 错误写法:
table[1] = 1 – 前面的1代表索引1,后面的1表示刷新标记 - 正确写法:
FlagIndex = 1
RefreshFlag = 1
table[FlagIndex] = RefresFlag
15.注意频繁调用函数参数量的控制
- 推荐写法
最好不要超过4个参数
16.优先使用static函数导出,减少使用成员方法导出
道理大家都懂
17.控制成员方法导出数量
不必要导出的函数用[NoToLuaAttribute]标记,减少lua虚拟机注册的函数数量
- 正确写法
[NoToLuaAttribute]
public void InsertBuffObj(MBuff buff, bool isTarget)
{
}
18.使用哈希值而不是字符串
针对Animator、Material或Shader属性进行内部寻址,推荐采用哈希的写法,例如Animator.StringToHash、Shader.PropertyToID,项目中写字符串都要谨慎,能不写就不写
- 错误写法
void Start()
{
anim = GetComponent();
anim.SetFloat(“Speed”, 1.0f);
} - 正确写法
void Start()
{
anim = GetComponent();
// 将字符串参数名转换为哈希值
int speedHash = Animator.StringToHash(“Speed”);
// 然后可以使用这个哈希值来设置参数值
anim.SetFloat(speedHash, 1.0f);
}
19.命名规范
- 不推荐使用2、4命名,可以用To、For
- 不要使用拼音,用最容易想到的单词
20.同时设置坐标和旋转
- 推荐写法
Transform.SetPositionAndRotation
GameObject.Instantiate(prefab, parent, position, rotation) - 不推荐写法
分开设置好几次属性
21.物理检测使用NoAlloc接口
- 错误写法
var layerMask = ~0;
if (Physics.Raycast(transform.position, transform.forward, m_Results, Mathf.Infinity, layerMask) > 0)
{
}
Physics2D. CircleCast();
- 正确写法
var layerMask = ~0;
if (Physics.RaycastNonAlloc(transform.position, transform.forward, m_Results, Mathf.Infinity, layerMask) > 0)
{
}
Physics2D. CircleCastNonAlloc();
22.数据配置
- 表格数据配置不要使用拼接的方式在运行时分割
- 数据存储不要采用json、xml等配置,推荐使用二进制或者scriptable object
23.不要出现空的Unity事件
- 错误写法:
void Update()
{
}
24.尽可能减少每帧运行的代码
考虑代码是否必要每帧执行,如果不需要的话可以控制调用频率
- 推荐写法
private int interval = 3;
void Update()
{
if (Time.frameCount % interval == 0)
{
Function();
}
}
25.避免初始化函数处理太复杂的逻辑
例如Awake、Start、OnEnable中处理复杂的逻辑,增加启动加载时间
26.调用统一的日志接口
调用统一接口方便宏定义开关管理
- 错误写法
print(“这是一条日志”)
Debug.log(“这是一条日志”) - 正确写法
LogManager.Print(“这是一条日志”)
27.避免运行时添加组件
在运行时AddComponent需要一些开销,因为要检查是否重复组件或者需要其他依赖组件
- 推荐做法
采用预制件
28.vector距离判断
如果只是距离判断推荐使用
- 不推荐写法
Vector3.Magnitude(vec) - 推荐写法
Vector3.SqrMagnitude(vec)
29.向量乘
向量乘需要耗时多一点,尽可能少的做向量运算
- 不推荐写法
Vector3 c = 3 * Vector3.one * 2; - 推荐写法
Vector3 c = 3 * 2 * Vector3.one;
30.shader数据精度
能用小的就不用大的
Float(32bit) (位置与纹理坐标信息)
Half(16bit)(纹理坐标与颜色信息)
Fixed(11bit)(颜色信息)(SRP下不支持)
31.除法转换成乘倒数
频繁的做除法运算,可以改成乘以倒数,属于指令集优化,硬件上乘以倒数比除执行效率高
- 不推荐写法
var res = a / b;
Var res = a / 5f; - 推荐写法
var res = a * (1 / b);
var res = a * 0.2f;
除法运算性能开销时间是乘法的100倍(官方说法)
32.双重循环
不得已要双重循环,大循环在内部
- 不推荐写法
for (int i = 0; i < numTests; i++)
{
for (int j = 0; j < 2; j++)
{
int k = i * j;
}
} - 推荐写法
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < numTests; j++)
{
int k = i * j;
}
}
[图片]
33.string操作
多次字符串操作,推荐使用stringbuilder,避免new string产生gc,如果stringbuilder能确定长度,最好先指定长度,也可以用ZString库
34.struct替代class
能用struct的就用struct,实在用不了再考虑class
35.系统自带默认值
例如Quaternion,Vector3等默认值全局静态只读变量,全局只有一个,减少一次new的操作
- 不推荐写法
Vector3 v3 = new Vector3(0, 0, 0); - 推荐写法
Vector3 v3 = Vector3.zero;
37.避免装拆箱
装箱:值类型->引用类型
int value = 11;
object obj = value;
拆箱:引用类型->值类型
object obj = 42;
int value = (int)obj;
- 不推荐写法
循环内部产生拆箱、装箱的写法
38.正确使用对应的数据结构
大量的数据查询操作
- 错误写法
for(int i=0; i<1000; i++)
{
if(list.Contains(i))
{
//todo
}
}
还有不要用for循环遍历查找luatable的数组表(数据量比较大) - 正确写法
用HashSet结构或者lua哈希表
39.循环修改值
- 错误写法
foreach(var item in array)
{
if(item.id == xxx)
{
item.xxx = xxx
}
} - 正确写法
for(int i = 0;i < array.count; i++)
{
if(array[i].id == xxx)
{
array[i].xxx = xxx
}
}
40.循环删除
倒序删除
- 推荐写法
// 假设有一个List
List myList = new List { 1, 2, 3, 4, 5 };
// 倒序删除所有偶数元素
for (int i = myList.Count - 1; i >= 0; i–) {
if (myList[i] % 2 == 0) {
myList.RemoveAt(i);
}
}
- 不推荐写法
正序删除
41.获取组件
在Unity中,GetComponent方法有三种重载方式:GetComponent()、GetComponent(Type type)和GetComponent(string type)。根据搜索结果,推荐使用泛型方式GetComponent()
- 推荐写法
GetComponent()
效率最高,耗时最少
42.跳过当前帧
- 不推荐写法
yield return new WaitForFrame(); - 推荐写法
yield return null;
yield return 0;
43.代码编写原则
- 推荐原则
- 尽早返回:如果函数在执行过程中遇到可以立即确定结果的条件,应立即返回,而不是继续执行更多代码才返回
- 避免深层嵌套:减少代码嵌套层数,可以提取函数,使用循环控制语句等方式来实现,警惕递归调用
- 单一出口点:尽量让函数只有一个返回点,减少代码复杂性,使得函数执行流程更加清晰
- 函数职责单一:确保一个函数只做一件事情,减少函数内部复杂度和耦合度,使得函数更容易理解和维护,功能通过若干单一函数组装
- 使用断言:检测函数参数的合法有效性,如果不合法则立即抛出异常或返回
44.避免单帧大循环逻辑处理
CPU瞬时压力过大,造成Big Jank
- 不推荐写法
for(int i = 0;i < 100;i ++)
{
}
- 推荐策略
- 分帧处理
- 算法处理,例如二叉树、四叉树、AOI等算法策略
45.碰撞检测
- 不推荐写法
collider碰撞检测 - 推荐写法
vector距离检测
46.异步编程
- 不推荐写法
void Start()
{
StartCoroutine(DelayedAction());
}
// 协程方法,延迟2秒后执行
IEnumerator DelayedAction()
{
yield return new WaitForSeconds(2.0f); // 等待2秒
Debug.Log(“Delayed action executed after 2 seconds”);
}
- 推荐写法
async void Start()
{
await Task.Delay(2000);
}
47.lua代码变量
- 错误写法
都写成全局变量
48.扩展原方法/类
扩展模板代码方法,或者引擎内部方法
- 错误写法
生成模板代码直接生成class - 正确写法
- 生成partial class的模板代码方法,以便提供扩展能力
- 使用扩展方法
49.谨慎频繁调用强制垃圾回收
- 不推荐写法
定期执行Resources.UnUsedAssets() 或者lua的collectgarbage(“collect”) - 推荐写法
- 资源采用引用计数管理和释放,不需要频繁粗暴调用Resources.UnUsedAssets(),会造成很大的帧率jank
- 手动在合适的时机调用gc方法
50.向量浮点数运算
- 不推荐写法
Vector3 pos1 = new Vector3(1,2,3);
Vector3 pos2 = new Vector3(4,5,6);
var pos3 = pos1 + pos2;
var pos4 = pos1 * 2f; - 推荐写法
var pos3 = new Vector3(pos1.x + pos2.x, pos1.y + pos2.y, …);
var pos2 = new Vector3(pos1.x * 2f, pos1.y * 2f, …);
51.lua UI变量查找
- 不推荐写法
find的方式 - 推荐写法
Editor中Prefab绑定,lua使用
52.tag比较
- 不推荐写法
gameObject.Tag == “MyTag”
属性访问,返回一个字符串跟另外一个字符串比较 - 推荐写法
gameObject.CompareTag(“MyTag”)
实用CompareTag方法,内部直接比较,避免一次字符串创建
53.能用localposition就不要用position
原因:获取position背后会做一系列计算,因为涉及到全局坐标,需求中能用localposition就用这个
持续更新,欢迎补充…
相关文章:
Unity高效编程经验50条分享
1.避免频繁创建临时对象 错误写法:obj.transform.position pos;这种写法会在Lua中频繁返回transform对象导致gc正确写法:创建一个静态方法来设置位置,例如 class LuaUtil { static void SetPos(GameObject obj, float x, float y, float z)…...
TypeScript 泛型
在 TypeScript 中,泛型是一种强大的工具,它允许你在定义函数、类、接口或类型别名时不指定具体的类型。这意味着你可以为这些实体创建可重用的组件,这些组件可以在不同的类型上以一致的方式工作。今天,我们将深入探讨 TypeScript …...
【Java从入门到放弃 之 条件判断与循环】
条件判断与循环 条件判断if 语句if-else 语句if-else 嵌套语句switch 语句 循环for 循环while 循环do-while 循环break 和 continuebreak 关键字continue 关键字总结 条件判断 条件判断用于根据不同的条件执行不同的代码块。Java 中常用的条件判断语句有 if、if-else 和 switc…...

Ubuntu20.04安装kalibr
文章目录 环境配置安装wxPython下载编译测试报错1问题描述问题分析问题解决 参考 环境配置 Ubuntu20.04,python3.8.10,boost自带的1.71 sudo apt update sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost…...
Flink 任务启动脚本-V2(包括ck启动)
#!/bin/bash#crontab时设置,如果依赖其他环境变量配置,可以在脚本执行一下环境变量脚本 source /etc/profile# 进入脚本目录 curdirdirname "$0" curdircd "$curdir"; pwd echo "进入启动脚本目录 $curdir"# 定义应用程序…...

扫雷-完整源码(C语言实现)
云边有个稻草人-CSDN博客 在学完C语言函数之后,我们就有能力去实现简易版扫雷游戏了(成就感满满),下面是扫雷游戏的源码,快试一试效果如何吧! 在test.c里面进行扫雷游戏的测试,game.h和game.c…...
python -从文件夹批量提取pdf文章的第n页,并存储起来
python -从文件夹批量提取pdf文章的第n页,并存储起来 废话不多说,看下面代码 讲解一下下面代码 reader PyPDF2.PdfReader (file) 将文件转化为PdfReader 对象,方便使用内置方法。 first_page reader.pages[0] 提取第一页 writer PyPDF…...
R Excel 文件操作指南
R Excel 文件操作指南 概述 R 语言是一种强大的统计分析工具,广泛用于数据分析和可视化。在实际应用中,经常需要将 R 语言与 Excel 文件结合使用,以便处理和分析数据。本指南将介绍如何在 R 中读取、写入和操作 Excel 文件。 准备工作 在…...

RabbitMQ 安装延迟队列插件 rabbitmq_delayed_message_exchange
前言: RabbitMQ 延迟队列插件(rabbitmq_delayed_message_exchange)是一个社区开发的插件,它为 RabbitMQ 添加了支持延迟消息的功能。通过这个插件,用户可以创建一种特殊的交换机类型 x-delayed-message,该…...

fatal error in include chain (rtthread.h):rtconfig.h file not found
项目搜索这个文件 rtconfig 找到后将其复制粘贴到 你的目录\Keil\ARM\ARMCC\include 应该还有cJSON,rtthread.h和 等也复制粘贴下...

Java 反射(Reflection)
Java 反射(Reflection) Java 反射(Reflection)是一个强大的特性,它允许程序在运行时查询、访问和修改类、接口、字段和方法的信息。反射提供了一种动态地操作类的能力,这在很多框架和库中被广泛使用&#…...

Python爬取机车网车型数据并存入Mysql数据库
结果展示(文末附完整代码): 一、引言 在当今数字化时代,数据对于各个领域的重要性不言而喻。对于机车行业而言,获取丰富的机车品牌、车型及详细信息数据,能够为市场分析、消费者研究等提供有力支持。本文将…...

fpga 时序分析基础
目录 触发器的动态参数 同步时序电路分析 1. 时钟脉冲的特性 2. 同步时序电路分析 Timing Analyzer的应用 异步时序与亚稳态问题 时序分析就是对时序电路进行时序检查,通过分析电路中所有寄存器之间的路径延迟以检查电路的传输延迟是否会导致触发器的建立时间…...
python学习——二维列表的列表生成式
二维列表的列表生成式允许你生成一个列表,其中每个元素本身也是一个列表。这在处理矩阵或表格数据时非常有用。 以下是如何使用列表生成式来创建二维列表的示例: 文章目录 基本语法示例1. 创建一个 3x3 的单位矩阵2. 创建一个 4x4 的乘法表3. 创建一个 …...

【错误❌】——槽函数定义好但未初始化
public slots:void onClose(); 初始化即可成功:...
OpenCV相机标定与3D重建(6)将3D物体点投影到2D图像平面上函数projectPoints()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::fisheye::projectPoints 是 OpenCV 库中用于鱼眼镜头模型的函数,它将3D物体点投影到2D图像平面上。这个函数对于模拟或者理解鱼眼…...

【Linux】剧幕中的灵魂更迭:探索Shell下的程序替换
🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 一念既出,万山无阻 目录 📖一、进程程序替换 1.替换的演示 ❓替换与执行流 ❓程序替换≠进程替换 2.替换的原理 …...

38 基于单片机的宠物喂食(ESP8266、红外、电机)
目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机,采用L298N驱动连接P2.3和P2.4口进行电机驱动, 然后串口连接P3.0和P3.1模拟ESP8266, 红外传感器连接ADC0832数模转换器连接单片机的P1.0~P1.…...

Unity中的数学应用 之 角色移动中单位化向量的妙用 (小学难度)
最近准备从简单到困难跟几个教程用以加强自己的业务能力,相信很多小伙伴都做过胡闹厨房这一个案例,其实这个案例比较初级,但是也包含了很多平常可能注意不到小细节,所以我就以它为举例,拓展其中的数学知识 CodeMonkey教…...

设置ip和代理DNS的WindowsBat脚本怎么写?
今天分享一个我们在工作时,常见的在Windows中通过批处理脚本(.bat 文件)来设置IP地址、代理以及DNS 相关配置的示例,大家可以根据实际需求进行修改调整。 一、设置静态IP地址脚本示例 以下脚本用于设置本地连接(你可…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...