开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

开发者专栏

关注:2212

当前位置:游戏蛮牛 技术专区 开发者专栏

__________________________________________________________________________________
开发者干货区版块规则:

  1、文章必须是图文形式。(至少2幅图)
      2、文章字数必须保持在1500字节以上。(编辑器右下角有字数检查)
      3、本版块只支持在游戏蛮牛原创首发,不支持转载。
      4、本版块回复不得无意义,如:顶、呵呵、不错......【真的会扣分的哦】
      5、......
__________________________________________________________________________________
查看: 2411|回复: 51

[凉鞋同学] Unity 游戏框架搭建 (二十二) 简易引用计数器

[复制链接]  [移动端链接]
排名
2300
昨日变化

32

主题

373

帖子

1913

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
57
蛮牛币
2076
威望
0
注册时间
2016-5-17
在线时间
632 小时
最后登录
2018-5-21

专栏作家

QQ
发表于 2018-1-27 19:53:42 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
本帖最后由 liangxiegame 于 2018-1-29 22:13 编辑

引用计数是一个很好用的技术概念,不要被这个名字吓到了。首先来讲讲引用计数是干嘛的。


引用计数使用场景
有一间黑色的屋子,里边有一盏灯。当第一个人进屋的时候灯会打开,之后的人进来则不用再次打开了,因为已经开过了。当屋子里的所有人离开的时候,灯则会关闭。
我们先定义灯的对象模型:
[C#] 纯文本查看 复制代码
    class Light
    {
        public void Open()
        {
            Log.I("灯打开了");
        }

        public void Close()
        {
            Log.I("灯关闭了");
        }
    }

很简单就是两个方法而已。
再定义屋子的类,屋子应该持有一个Light的对象,并且要记录人们的进出。当有人进入,进入后当前房间只有一个人的时候,要把灯打开。当最后一个人离开的时候灯要关闭。
代码如下:
[C#] 纯文本查看 复制代码
    class Room
    {
        private Light mLight = new Light();

        private int mPeopleCount = 0;

        public void EnterPeople()
        {
            if (mPeopleCount == 0)
            {
                mLight.Open();
            }

            ++mPeopleCount;

            Log.I("一个人走进房间,房间里当前有{0}个人",mPeopleCount);
        }

        public void LeavePeople()
        {
            --mPeopleCount;

            if (mPeopleCount == 0)
            {
                mLight.Close();
            }

            Log.I("一个人走出房间,房间里当前有{0}个人", mPeopleCount);
        }
    }

很简单,我们来看下测试代码。
[C#] 纯文本查看 复制代码
            var room = new Room();
            room.EnterPeople();
            room.EnterPeople();
            room.EnterPeople();

            room.LeavePeople();
            room.LeavePeople();
            room.LeavePeople();

            room.EnterPeople();

看下输出的结果:
[C#] 纯文本查看 复制代码
灯打开了
一个人走进房间,房间里当前有1个人
一个人走进房间,房间里当前有2个人
一个人走进房间,房间里当前有3个人
一个人走出房间,房间里当前有2个人
一个人走出房间,房间里当前有1个人
一个人走出房间,房间里当前有0个人
灯关闭了
灯打开了
一个人走进房间,房间里当前有1个人

OK.以上就是引用计数这项技术的使用场景的所有代码。 测试的代码比较整齐,很容易算出来当前有多少个人在屋子里,所以看不出来引用计数的作用。但是在日常开发中,我们可能会把EnterPeople和LeavePeople散落在工程的各个位置。这样就很难统计,这时候引用计数的作用就很明显了,它可以自动帮助你判断什么时候进行开灯关灯操作,而你不用写开关灯的一行代码。
这个例子比较接近生活,假如笔者再换个例子,我们把Light对象换成资源对象,其开灯对应加载资源,关灯对应卸载资源。而屋子则是对应资源管理器,EnterPeople对应申请资源对象,LeavePeople对应归还资源对象。这样你只管在各个界面中申请各个资源,只要在界面关闭的时候归还各个资源对象就可以不用关心资源的加载和卸载了,可以减轻大脑的负荷。
简易计数器实现:
计数器的接口很简单,代码如下:
[C#] 纯文本查看 复制代码
    public interface IRefCounter
    {
        int RefCount { get; }

        void Retain(object refOwner = null);
        void Release(object refOwner = null);
    }

Retain是增加引用计数(RefCount+1),Release减去一个引用计数(RefCount—)。 在接下来的具体实现中,当RefCount降为0时我们需要捕获一个事件,这个事件叫OnZeroRef。 代码如下:
[C#] 纯文本查看 复制代码
    public class SimpleRC : IRefCounter
    {
        public SimpleRC()
        {
            RefCount = 0;
        }

        public int RefCount { get; private set; }

        public void Retain(object refOwner = null)
        {
            ++RefCount;
        }

        public void Release(object refOwner = null)
        {
            --RefCount;
            if (RefCount == 0)
            {
                OnZeroRef();
            }
        }

        protected virtual void OnZeroRef()
        {
        }
    }

以上就是简易引用计数器的所有实现了。
接下来我们用这个引用计数器,重构灯的使用场景的代码。
[C#] 纯文本查看 复制代码
    class Light
    {
        public void Open()
        {
            Log.I("灯打开了");
        }

        public void Close()
        {
            Log.I("灯关闭了");
        }
    }

    class Room : SimpleRC
    {
        private Light mLight = new Light();

        public void EnterPeople()
        {
            if (RefCount == 0)
            {
                mLight.Open();
            }

            Retain();

            Log.I("一个人走进房间,房间里当前有{0}个人",RefCount);
        }

        public void LeavePeople()
        {
            // 当前还没走出,所以输出的时候先减1
            Log.I("一个人走出房间,房间里当前有{0}个人", RefCount - 1);

            // 这里才真正的走出了
            Release();
        }

        protected override void OnZeroRef()
        {
            mLight.Close();
        }
    }

测试代码和之前的一样,我们看下测试结果:
[C#] 纯文本查看 复制代码
灯打开了
一个人走进房间,房间里当前有1个人
一个人走进房间,房间里当前有2个人
一个人走进房间,房间里当前有3个人
一个人走出房间,房间里当前有2个人
一个人走出房间,房间里当前有1个人
一个人走出房间,房间里当前有0个人
灯关闭了
灯打开了
一个人走进房间,房间里当前有1个人

好了,今天就到这里
相关链接:
附: 我的框架地址:https://github.com/liangxiegame/QFramework
教程源码:https://github.com/liangxiegame/QFramework/tree/master/Assets/HowToWriteUnityGameFramework/
转载请注明地址:凉鞋的笔记http://liangxiegame.com





回复

使用道具 举报

3偶尔光临
166/300
排名
12730
昨日变化
11

0

主题

61

帖子

166

积分

Rank: 3Rank: 3Rank: 3

UID
137409
好友
0
蛮牛币
3
威望
0
注册时间
2016-2-24
在线时间
45 小时
最后登录
2018-4-9
发表于 2018-1-28 19:16:18 | 显示全部楼层
看下。。。支持下。。。。

回复

使用道具 举报

3偶尔光临
299/300
排名
6571
昨日变化
41

1

主题

22

帖子

299

积分

Rank: 3Rank: 3Rank: 3

UID
257829
好友
0
蛮牛币
581
威望
0
注册时间
2017-12-4
在线时间
102 小时
最后登录
2018-5-25
发表于 2018-1-29 09:13:20 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
763/1000
排名
5744
昨日变化
1

0

主题

403

帖子

763

积分

Rank: 5Rank: 5

UID
146677
好友
9
蛮牛币
2571
威望
0
注册时间
2016-4-25
在线时间
152 小时
最后登录
2018-5-19
QQ
发表于 2018-1-29 09:17:41 | 显示全部楼层
支持楼主,加油

回复

使用道具 举报

5熟悉之中
554/1000
排名
3850
昨日变化
2

0

主题

72

帖子

554

积分

Rank: 5Rank: 5

UID
52730
好友
1
蛮牛币
916
威望
0
注册时间
2014-11-3
在线时间
148 小时
最后登录
2018-5-26
发表于 2018-1-29 09:27:23 | 显示全部楼层
好文章,谢谢分享。

回复

使用道具 举报

6蛮牛粉丝
1138/1500
排名
3334
昨日变化
2

0

主题

527

帖子

1138

积分

Rank: 6Rank: 6Rank: 6

UID
156480
好友
0
蛮牛币
1849
威望
0
注册时间
2016-7-12
在线时间
225 小时
最后登录
2018-3-16
发表于 2018-1-29 09:29:19 | 显示全部楼层
6666666666

回复

使用道具 举报

4四处流浪
370/500
排名
12289
昨日变化
6

3

主题

133

帖子

370

积分

Rank: 4

UID
216830
好友
2
蛮牛币
211
威望
0
注册时间
2017-4-9
在线时间
170 小时
最后登录
2018-5-17
发表于 2018-1-29 09:40:42 | 显示全部楼层
谢谢分享

回复

使用道具 举报

5熟悉之中
978/1000
排名
3371
昨日变化
16

1

主题

367

帖子

978

积分

Rank: 5Rank: 5

UID
122160
好友
1
蛮牛币
1602
威望
0
注册时间
2015-9-10
在线时间
228 小时
最后登录
2018-5-25
发表于 2018-1-29 10:07:39 | 显示全部楼层
感谢分享

回复

使用道具 举报

5熟悉之中
501/1000
排名
7723
昨日变化
3

0

主题

260

帖子

501

积分

Rank: 5Rank: 5

UID
250350
好友
1
蛮牛币
430
威望
0
注册时间
2017-10-23
在线时间
103 小时
最后登录
2018-4-19
发表于 2018-1-29 10:15:14 | 显示全部楼层

谢谢分享
[发帖际遇]: liuwenjiandm 在论坛发帖时没有注意,被小偷偷去了 1 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

5熟悉之中
728/1000
排名
3968
昨日变化
22

7

主题

137

帖子

728

积分

Rank: 5Rank: 5

UID
252607
好友
1
蛮牛币
2042
威望
0
注册时间
2017-11-5
在线时间
264 小时
最后登录
2018-5-25
发表于 2018-1-29 11:58:31 | 显示全部楼层
谢谢分享

回复

使用道具 举报

6蛮牛粉丝
1493/1500
排名
1429
昨日变化
1

1

主题

219

帖子

1493

积分

Rank: 6Rank: 6Rank: 6

UID
2272
好友
3
蛮牛币
1381
威望
0
注册时间
2013-8-20
在线时间
499 小时
最后登录
2018-5-25

VIP

发表于 2018-1-29 13:56:06 | 显示全部楼层

谢谢分享
[发帖际遇]: fengjian1230 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

7日久生情
4039/5000
排名
135
昨日变化

18

主题

308

帖子

4039

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
67323
好友
1
蛮牛币
3051
威望
0
注册时间
2015-1-10
在线时间
1607 小时
最后登录
2018-5-20
发表于 2018-1-29 15:23:30 | 显示全部楼层
好文章 谢谢分享。

回复

使用道具 举报

排名
2300
昨日变化

32

主题

373

帖子

1913

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
57
蛮牛币
2076
威望
0
注册时间
2016-5-17
在线时间
632 小时
最后登录
2018-5-21

专栏作家

QQ
 楼主| 发表于 2018-1-29 16:48:47 | 显示全部楼层
AlexGau 发表于 2018-1-28 19:16
看下。。。支持下。。。。

谢谢支持

回复 支持 反对

使用道具 举报

排名
2300
昨日变化

32

主题

373

帖子

1913

积分

Rank: 9Rank: 9Rank: 9

UID
148923
好友
57
蛮牛币
2076
威望
0
注册时间
2016-5-17
在线时间
632 小时
最后登录
2018-5-21

专栏作家

QQ
 楼主| 发表于 2018-1-29 16:49:04 | 显示全部楼层

谢谢支持

回复 支持 反对

使用道具 举报

3偶尔光临
226/300
排名
9379
昨日变化
4

1

主题

52

帖子

226

积分

Rank: 3Rank: 3Rank: 3

UID
194221
好友
0
蛮牛币
477
威望
0
注册时间
2016-12-19
在线时间
71 小时
最后登录
2018-5-24
发表于 2018-1-29 21:06:07 | 显示全部楼层

好文章 谢谢分享。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

关闭

站长推荐 上一条 /1 下一条

快速回复 返回顶部 返回列表