(以下内容主要来源于ChatGPT,仅记录以供复习)
静态类:
在Unity中,你可以创建一个静态类来包含一些静态方法和静态属性,这些方法和属性可以在整个项目中直接调用,而无需实例化类对象。静态类的实例在整个应用程序中只有一个,而不是只有一个场景。这意味着在同一应用程序的不同场景中,你可以通过静态类来共享数据和功能。如果你重新加载场景(例如使用SceneManager.LoadScene
),则静态类的实例不会重置。如果你需要在场景切换时重置静态类的数据,你可以在场景加载时手动重置它们。
静态类中的成员只能是静态的,不能包含实例成员(非静态成员)。
包含静态类的脚本应该作为一个独立的文件存在于项目中,而不是挂载在场景中的物体上(unity会阻止你挂上去)
下面是一个示例代码,展示了如何使用静态类在多个场景中共享数据:
using UnityEngine;
using UnityEngine.SceneManagement;
public static class Game
{
public static int score;
// 在 Awake() 方法中注册场景加载完成的回调
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]//用于标记静态方法,指示在场景加载之前调用该方法。
private static void Initialize()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
// 场景加载完成时的回调函数
private static void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// 可以在此处进行数据初始化或其他处理
Debug.Log("Scene loaded: " + scene.name);
score++;
Debug.Log("Current score: " + score);
}
}
用按钮切换场景三次后的运行结果如下:
以下是使用静态类的基本步骤:
1、创建一个静态类: 在C#中,静态类是使用 static
关键字声明的类。例如,创建一个名为 MyStaticClass
的静态类可以使用以下代码:
public static class MyStaticClass
{
// 静态方法和属性
}
2、添加静态方法和属性: 在静态类中,你可以添加任意数量的静态方法和属性。这些方法和属性可以直接从静态类中访问,而无需创建类的实例。例如,以下是一个包含静态方法和属性的静态类的示例
public static class MyStaticClass
{
public static int MyStaticProperty { get; set; }
public static void MyStaticMethod()
{
// 执行代码
}
}
3、在其他类中使用静态类: 一旦你创建了一个静态类,你可以从任何其他类中直接使用它的静态方法和属性,而无需实例化类对象。使用类名和点操作符即可访问静态成员。例如:
// 调用静态属性
int value = MyStaticClass.MyStaticProperty;
// 调用静态方法
MyStaticClass.MyStaticMethod();
静态对象:
普通类的静态对象是指在类的定义中声明为静态的类实例。它与静态类是不同的概念。
在普通类中,你可以声明一个静态字段来创建一个静态对象。这个静态对象将在类加载时初始化,并且在整个应用程序中只有一个实例。以下是使用普通类的静态对象的基本步骤:
1、创建一个普通类: 首先,创建一个普通的C#类。这是一个没有使用 static
关键字声明的普通类。
2、添加静态字段和实例: 在这个普通类中,你可以添加一个静态字段来表示该类的静态对象,并在类的构造函数中进行初始化。这将确保在类加载时只创建一个实例。例如:
public class MyClass
{
private static MyClass instance;
public MyClass()
{
// 构造函数
}
public static MyClass Instance
{
get
{
if (instance == null)
{
instance = new MyClass();
}
return instance;
}
}
}
3、使用静态对象: 一旦你创建了一个普通类的静态对象,你可以在代码中使用它。通过访问类的静态属性 Instance
来获取该静态对象的实例。例如:
MyClass myObject = MyClass.Instance;
// 使用 myObject 进行操作
ChatGPT的这个“在整个应用程序中只有一个实例”容易混淆,写了一段代码来说明这句话的意思以及测试静态对象场景切换的生存期:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class TestScripts : MonoBehaviour
{
public static TestScripts Instance;
void Awake()
{
Instance = this;
Debug.Log(Instance.GetHashCode());
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnClick(string SceneName)
{
SceneManager.LoadScene(SceneName);
//Instance = this;
Debug.Log("loading" + Instance.GetHashCode());
}
}
Unity中进行的操作:(1)在同一场景的两个对象A,B上分别挂上了该脚本,输出-45202和27342两个不同地址值,说明将这个脚本挂载到多个物体上,每个物体都将有自己的实例。每个实例都是独立的,具有不同的内存空间和状态。
(2)在另一场景SampleScene的某物体上也挂上该脚本,从(1)中场景TestScene切换到SampleScene,按序输出“loading27342”(Onclick)“34076”(Awake)再从SampleScene切换回TestScene,按序输出“34158”(A-Awake)“34166”(B-Awake),说明在切换场景后该脚本是会被销毁的。因此静态对象和一般的数据类型的生存期是一样的,只是静态对象是可以在同一场景全局访问的(以我目前的知识量是这么理解的)
运行结果: