Unity装箱与拆箱性能优化秘籍断篇

问:什么是装箱?
剑之初: 装箱转换是指将一个值类型隐式地转换成一个object 类型,或者把这个值类型转换成一个被该值类型应用的接口类型interface-type。把一个值类型的值装箱,也就是创建一个object 实例并将这个值复制给这个object。比如

 	int i = 10;

	object obj = i;

用下图所示,可以表示装箱的过程
在这里插入图片描述
我们也可以用显式的方法来进行装箱操作:

    int i = 10;

    object obj =(object)i;

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

问:什么是拆箱?
剑之初:和装箱转换正好相反,拆箱转换是指将一个对象类型显式地转换成一个值类型,或是将一个接口类型显式地转换成一个执行该接口的值类型。
拆箱的过程分为两步:首先,检查这个对象实例,看它是否为给定的值类型的装箱值。然后,把这个实例的值拷贝给值类型的变量。

利用如下例子:

    int i = 10;

    object obj = i;

    int j = (int)obj;

拆箱的过程用图来表示就是:
在这里插入图片描述
可以看出拆箱过程正好是装箱过程的逆过程。必须注意,装箱转换和拆箱转换必须遵循类型兼容原则。

那么接下来进入正题,我们将如何避免这样的装箱与拆箱操作呢?

剑之初采用的方式是创建自己的数据类型库,在内部根据泛型进行转换.具体骚操作如下:
创建数据类型库的基类: VartableBase.cs

话不多说上代码!!!:

#region 模块信息
//===================================================
// Copyright (C) 2020	
//
// 文件名(File Name):				VartableBase.cs
// 作者(Author):					稀饭 
// 邮箱(e-mail):					1144000915@qq.com
// 创建时间(CreateTime):			2021-01-11 15:20:13 
// 修改者列表(modifier):		
// 模块描述(Module description):	创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace YouYou
{
	/// <summary>
	/// 变量基类
	/// </summary>
	public abstract class VartableBase  {

		/// <summary>
		/// 获取变量类型
		/// </summary>
		public abstract Type Type
        {
			get;
        }

		/// <summary>
		/// 引用计数
		/// </summary>
		public byte ReferenceCount
        {
			get;
			private set;
        }

		/// <summary>
		/// 变量引用计数增加
		/// </summary>
		public void Retain()
        {
			ReferenceCount++;
		}

		/// <summary>
		/// 变量引用计数减少 变量回池
		/// </summary>
		public void Release()
        {
			ReferenceCount--;
            if (ReferenceCount<1)
            {
				//回池操作
				GameEntry.Pool.EnqueueVarObject(this);
			}
		}
	}
}

定义变量泛型基类:

#region 模块信息
//===================================================
// Copyright (C) 2020	
//
// 文件名(File Name):				Vartable.cs
// 作者(Author):					稀饭 
// 邮箱(e-mail):					1144000915@qq.com
// 创建时间(CreateTime):			2021-01-11 15:20:05 
// 修改者列表(modifier):		
// 模块描述(Module description):	创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace YouYou
{
    /// <summary>
    /// 变量泛型基类
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Vartable<T> : VartableBase
    {

        /// <summary>
        /// 当前存储的真实值
        /// </summary>
        public T Value;

        /// <summary>
        /// 变量类型
        /// </summary>
        public override Type Type
        {
            get
            {
                return typeof(T);
            }
        }


    }
}

例如我们现在需要一个byte类型,那么就创建一个脚本:VarByte.cs

#region 模块信息
//===================================================
// Copyright (C) 2020	
//
// 文件名(File Name):				VarByte.cs
// 作者(Author):					稀饭 
// 邮箱(e-mail):					1144000915@qq.com
// 创建时间(CreateTime):			2021-01-12 16:32:47 
// 修改者列表(modifier):		
// 模块描述(Module description):	创建脚本自动修改文件名、作者、创建时间
//===================================================
#endregion
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace YouYou
{
	public class VarByte : Vartable<byte> {
		/// <summary>
		/// 分配一个对象
		/// </summary>
		/// <returns></returns>
		public static VarByte Alloc()
		{
			VarByte var = GameEntry.Pool.DequeueVarObject<VarByte>();
			var.Value = 0;
			var.Retain();
			return var;
		}
		/// <summary>
		/// 分配一个对象
		/// </summary>
		/// <param name="value">初始值</param>
		/// <returns></returns>
		public static VarByte Alloc(byte value)
		{
			VarByte var = Alloc();
			var.Value = value;
			return var;
		}

		/// <summary>
		/// VarByte -> byte
		/// </summary>
		/// <param name="value"></param>
		public static implicit operator byte(VarByte value)
		{
			return value.Value;
		}
	}
}

准备工作全部准备好了我们开始使用他们!

备注提醒: 下面的测试脚本有调用我写的变量对象池脚本与状态机脚本,本篇论文只是为了传输思想,代码不可直接拿来使用!

添加数据到数据字典中:

 		/// <summary>
        /// 设置参数值
        /// </summary>
        /// <typeparam name="TData">泛型类型</typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void SetData<TData>(string key,TData value)
        {
            VartableBase itemBase = null;
            if (m_ParamDic.TryGetValue(key,out itemBase))
            {
                Vartable<TData> item = itemBase as Vartable<TData>;
                item.Value = value;
                m_ParamDic[key] = item;
            }else
            {
                //参数原来不存在
                Vartable<TData> item = new Vartable<TData>();
                item.Value = value;
                m_ParamDic[key] = item;
            }
        }

获取数据

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <typeparam name="TData">泛型类型</typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public TData GetData<TData>(string key)
        {
            VartableBase itemBase = null;
            if (m_ParamDic.TryGetValue(key, out itemBase))
            {
                Vartable<TData> item = itemBase as Vartable<TData>;
                return item.Value;
            }
            return default(TData);
        }

设置与获取写好了,来最后看下调用时的样子:

调用设置属性

			GameEntry.Prosedure.SetData("code", Random.Range(1, 100));
			GameEntry.Prosedure.SetData("name", "稀饭开发");

调用获取属性 注意!!!在获取并没有进行装箱与拆箱的操作!!!

			string name = GameEntry.Prosedure.GetData<string>("name");
            int code = GameEntry.Prosedure.GetData<int>("code");

            Debug.Log("name= " + name);
            Debug.Log("code= " + code);

这时候有人问了.虽然没有进行装箱与拆箱操作,你频繁的创转VarByte的对象就不消耗性能了么?
剑之初: 创建一个数据变量池就好了! GetType获取类型当key.存到池中!!! 即可!!!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值