更新 HowToUseWeaklyScripts

2026-03-10 16:44:00 +08:00
parent fdace4a87c
commit 00ff081dd1
+32 -16
@@ -33,36 +33,52 @@
### 隐式提升为单例(隐式声名)
你可以直接在代码中通过超级单例访问实例,而不用在乎这个类是否实现过单例,通过超级单例获取的单例实例与这个类是无关的。
你可以直接在代码中通过超级单例访问实例,而不用在乎这个类是否实现过单例。
``` csharp
// 直接通过实例访问,如果这个类还没有在世界场景中生成,那么这一步会立刻创建一个实例在世界中
SingleMonoBase<MyClass>.Instance
// 超级单例只能作用在组件脚本上,比如随便声名一个脚本
public class TestScript: MonoBehaviour
{
// 一些其他与单例实现无关的逻辑
}
// 可以使用带有全局标识的实例进行访问,区别是,这会创建在dontdestroy世界中
SingleMonoBase<MyClass>.GlobalInstance
// 接下来直接通过超级单例访问:
TestScript inst = SingleMonoBase<TestScript>.Instance;
// 1. 如果这个类还没有在世界场景中生成,那么这一步会立刻创建一个实例在世界中。
// 2. 如果这个类已经存在,但是还没有通过超级单例访问,那么超级单例会首先尝试在场景中查找,然后根据你调用的作用域将他转移到对应的位置。
// 这里使用另一种全局作用域,这会将单例创建在dontdestroy世界中
TestScript globalInst = SingleMonoBase<TestScript>.GlobalInstance;
// 如果对象已经被超级单例注册过了,那这个对象就会保持当前的作用域,调用新的作用域也不会使其转移,所以请在一开始就确定单例的作用范围。
```
### 隔离绝对自身
超级单例允许你使用并非传统单例的模式进行声名,谁说单例的泛型必须声名自己了?
超级单例允许你使用并非传统单例的模式进行声名,谁说自己是单例的同时必须单例是自己了?
``` csharp
public class MyClassA: SingleMonoBase<MyClassB>
{
public class MyClassB: SingleMonoBase<MyClassA>
{
// 如果想访问自己可以这么做
public static MyClassB myInstb => InstanceSelf as MyClassB;
// 否则其他inst方法获取的是 MyClassA的单例
public static MyClassA myinsta => MyClassB.Instance;
}
// 使用带有self的属性来访问 MyClassA
myAclass = MyClassA.InstanceSelf as MyClassA;
// 不带self的属性则会访问到 MyClassB
myBclass = MyClassA.Instance;
// 顺带一提,可以将两个脚本互为单例,编译器不会报错,就是不知道有什么用。
public class MyClassA : SingleMonoBase<MyClassB> { }
public class MyClassB : SingleMonoBase<MyClassA> { }
```
在`MyClassA`中可以与`MyClassB`完全隔离的用法,不会继承`MyClassB`的任何内容。
在`MyClassB`中可以与`MyClassB`完全隔离的用法,不会继承`MyClassA`的任何内容。
但又可以继续使用MyClassA的属性和方法,和普通的单例几乎一样。
> 解释一下为什么这么做,你有一个很好用的基类,里面定义了一些你想用的方法,但可惜这些方法都是实例状态下调用的,而且它不能用在你当前的环境下。
> 比如这个基类是设计给3d场景的,而你的脚本用于ui环境下,基类挂不上,或者不能挂上去。那么可以声名成这样的形式,你的单例仍然是继承自MonoBehaviour,而不是那个基类。
> 而那个基类则会自动创建,在使用过程中直接调用即可。
### 代理单例