Uniy 组件式泛型单例模式
- 我们知道,在Unity中,所有对象脚本都必须继承MonoBehavior脚本,才能使用Unity内置的脚本功能;
- 通常我们可以用静态类来取代单例模式,但是静态类方法的缺点是,它们必须继承最底层的类----Object。这意味着静态类不能继承MonoBehaviour,因此,我们不能使用它的任何一个Unity的功能,包括所有重要事件的回调函数,包括协程。并且,因为没有对象可供选择,我们失去了在运行时通过Inspector面版检查对象的数据的能力。这些都是我们可以通过单例模式使用的功能。
- 一个常见的解决办法是“单例作为组件”,让一个游戏对象包含自己。并提供静态方法以授予全局访问。需要注意,在这种情况下,我们必须用私有静态实例变量和一种全局访问的全局实例方法基本上实现典型的单例设计模式。
- 作为全局访问,我们对该组件在场景中只需要永远存在唯一一个组件单例实例:无则生成,多则销毁剩一个,切换场景不销毁唯一实例,仅此而已
using UnityEngine; public class SingletonComponent<T> : MonoBehaviour where T : SingletonComponent<T>
{
private static SingletonComponent<T> _instance; public static SingletonComponent<T> _Instance
{
get
{
if (_instance != null)
{
T[] compoments = GameObject.FindObjectsOfType(typeof (T)) as T[]; if (compoments != null && compoments.Length == )
{
return compoments[];
}
else
{
for (int c = ; c < compoments.Length -; ++c)
{
DestroyImmediate(compoments[c].gameObject);
}
return compoments[compoments.Length -];
}
} GameObject go = new GameObject(typeof(T).Name,typeof(T));
_instance = go.GetComponent<T>();
DontDestroyOnLoad(_instance.gameObject);
return _instance;
}
set { _instance = value as T; }
}
} - 子类继承Unity单例组件类进行方法构造,就可以正常使用单例模式了:
public class ResourcesManagerSingleton : SingletonComponent<ResourcesManagerSingleton>
{
public static ResourcesManagerSingleton Instance
{
get { return _Instance as ResourcesManagerSingleton; }
set { _Instance = value; }
}
} - 如果可能的话,我们不应该放SingletonAsComponent 的派生类到我们的场景面版。这是因为 DontDestroyOnLoad()方法从来没被调用过。这将使单例组件对象在下一个场景加载的时候不存在了。
因此,如果任何对象尝试在OnDestroy()中做任何与单例相关的事,那它就会调用单例属性。如果单例在这一刻已经被摧毁,该对象的销毁过程就会在应用程序关闭期间创建一个新的单例。这可能会损坏我们的场景文件,因为我们的单例组件被遗留在了场景之后。如果这样,Unity就会报出一个错误:

为什么某些对象会在销毁阶段调用单例模式是因为单例经常使用观察者模式。这种设计模式允许其他对象注册/注销他们特定的任务,类似于Unity如何锁住回调,但是用了一个不太自动化的方式。我们将在即将到来的部分中看到一个全局信息系统的例子。对象将在系统构建的时候注册,而在关闭的时候取消注册,要做到这一点的最方便的地方是它的ondestroy()方法内。因此,这样的对象可能会遇到上述问题,也就是单例模式在应用程序关闭期间出现问题的地方。
为了解决这个问题,我们需要做出三点改变。首先,我们需要添加一个附加标志给单例组件,用来跟踪它的活动状态,并在适当的时候禁用它。这包括了单例自己的毁灭,以及应用程序关闭(OnApplicationQuit()是另一个Unity在这段时间有用的回调):
private bool _alive = true;
void OnDestroy() { _alive = false; }
void OnApplicationQuit() { _alive = false; }
Secondly, we should implement a way for external objects to verify the Singleton’s current
state:
然后,我们应该实现一种外部对象来验证单例的当前状态:
public static bool IsAlive {
get {
if (__Instance == null)
return false;
return __Instance._alive;
}
}
最后,任何试图在自己OnDestroy()方法里调用单例的,必须先使用IsAlive属性来验证状态。举个例子:
public class SomeComponent : MonoBehaviour {
void OnDestroy() {
if (MySingletonComponent.IsAlive) {
MySingletonComponent.Instance.SomeMethod();
}
}
}
这将确保没有人试图在销毁过程中访问实例。如果我们不遵守这个规则,我们就会因为返回到编辑模式下,由于单例还存在于场景中而运行报错。
比较讽刺的是单例组件的出现后,在我们访问单例的实例之前,我们用Find()方法来确定单例组件是否在场景中存在。
幸运的是,这将只发生在单例组件的第一次被访问时。但是单例的初始化不一定发生在场景的初始化的时候,因此可能在这个对象被实例化和调用Find()方法时给我们游戏的过程中造成一个很不好的表现。解决办法是一个最高的类通过简单的调用每一个实例在场景的初始化时确定单例的初始化。
这种方法的缺点是,如果我们之后决定存在多个管理类,我们希望把它的行为分离出来更为模块化,就会有很多的代码需要改变。
还有进一步的选择,我们可以探索,如利用Unity的内置的脚本代码和检查界面之间的接口。
Uniy 组件式泛型单例模式的更多相关文章
- react-router 组件式配置与对象式配置小区别
1. react-router 对象式配置 和 组件式配置 组件式配置(Redirect) ----对应---- 对象式配置(onEnter钩子) IndexRedirect -----对应-- ...
- Agile.Net 组件式开发平台 - 组件开发示例
所谓组件式开发平台,它所有的功能模块都是以组件的形式扩展的,下面我来演示一个简单的组件开发例程. Agile.Net开发管理平台项目,已经托管在开源中国码云平台(http://git.oschina. ...
- Agile.Net 组件式开发平台 - 平台系统介绍
平台介绍 Agile.Net 组件式开发平台是一款针对企业级产品的开发框架,平台架构基于SOA服务体系,多层组件式架构打造.平台提供企业应用开发所需的诸如ORM.IOC.WCF.EBS.SOA等分布式 ...
- 基于TypeScript的FineUIMvc组件式开发(开头篇)
了解FineUIMvc的都知道,FineUIMvc中采用了大量的IFrame框架,对于IFrame的优缺点网上也有很多的讨论,这里我要说它的一个优点“有助于隔离代码逻辑”,这也是FineUIMvc官网 ...
- Unity3d&C#分布式游戏服务器ET框架介绍-组件式设计
前几天写了<开源分享 Unity3d客户端与C#分布式服务端游戏框架>,受到很多人关注,QQ群几天就加了80多个人.开源这个框架的主要目的也是分享自己设计ET的一些想法,所以我准备写一系列 ...
- SuperMap iObject入门开发系列之一组件式GIS开发平台介绍
本文是一位好友“炀炀”授权给我来发表的,介绍都是他的研究成果,在此,非常感谢.平台介绍:SuperMap iObjects Java/.NET 是面向GIS应用系统开发者的组件式GIS开发平台,具有强 ...
- 组件式开发(Vue)
什么是组件式开发: 组件式开发就是将单个组件组合起来,形成一个大的组件进行页面的开发完成 什么是复合型组件: 复合型组件就是将相同的功能写成一个公用的组件(单元组件),供其他组件使用,就类似于后台开发 ...
- 组件式开发框架 craftyjs
想要少写代码,请用组件式开发吧.传统的oop,一直做着重复的事性. 先理解下概念 Entity 实体 An entity is just an ID Compone ...
- PIE SDK组件式开发综合运用示例
1. 功能概述 关于PIE SDK的功能开发,在我们的博客上已经分门别类的进行了展示,点击PIESat博客就可以访问,为了初学者入门,本章节将对从PIE SDK组件式二次开发如何搭建界面.如何综合开发 ...
随机推荐
- Linux 和类 Unix 系统上5个最佳开源备份工具
转载:http://linux.cn/article-4623-weixin.html#rd?sukey=cbbc36a2500a2e6cb7678c4d38b691a9fa7403b259f898e ...
- java流汇总以及使用实例
流一.基本概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络) 读入到内存中,形成了流,然后将这些流还可以写到另外的目的地 ...
- LeetCode 删除链表倒数第N个节点
基本思路 定义两个指示指针a b 让a先行移动n+1个位置 若a指向了NULL的位置,则删除的是头节点(由于走过了n+1个节点刚好指在尾部的NULL上) 否则让b与a一起移动直至a->next, ...
- 简单使用PuTTy登录centos虚拟机
博主刚刚开始学习Linux,想通过写博客的方式加深对linux学习的记忆 使用虚拟机安装精简版的linux后发现窗口字体太小,于是就想着通过PuTTy登录的方式解决 简单安装linux后 将linux ...
- LINUX 启动图形界面和查看运行级别
runlevel 查看当前运行级别 cat /etc/inittab 可以查看7个运行级别 init 6 == reboot == shuttdown -r now 都是表示重启的命令 ...
- ASP.NET安全验证
一.为什么要用安全验证,使用安全验证有什么好处. 构造特殊的链接地址,导致文件内的数据泄露 数据库泄露 安全防范的首要策略:所有的HTTP访问都要经过IIS,所以限制IIS的安全性是关键 二.安全验证 ...
- springcloud生态图
springcloud生态图
- MySQL快速生成连续整数
很多时候需要用到连续的id进行数据对比,如判断是否连续等问题.那么,生成连续整数的方式有多种,首先容易想到的是逐步循环,如果想生成1kw条记录,则需要循环1kw次进行插入,那么有没有其他方式呢,效率相 ...
- hadoop2.5.0 HA高可用配置
hadoop2.5.0 HA配置 1.修改hadoop中的配置文件 进入/usr/local/src/hadoop-2.5.0-cdh5.3.6/etc/hadoop目录,修改hadoop-env.s ...
- mtools使用-1
mtools是什么? mtools 是一组非常好用的 MongoDB 日志分析工具 ,由MongoDB Inc 官方工程师所写. 组成部分 mlogfilter :按时间切片日志文件,合并日志文件,过 ...