生成程序集的方式
{和当前程序集同等文件位置的脚本文件(.cs)或在当前文件夹下的脚本文件 会同属于这个程序集,}如果在这个程序集之上的脚本文件或没有创建程序集则同属于Assembly-CSharp.dll** 程序集
如果多层程序集嵌套,则按上面{}里面的分类。
查看当前项目包含的程序集文件
XXX项目名\Library\ScriptAssemblies
真正影响程序集名称的是他的Name 属性 而不是它在项目中的名字
不同程序集之间的类不能相互调用 当想在属于A程序集的脚本文件中调用B程序集中的脚本文件 则可以在A程序集中的References 中添加B程序集 之后在A中脚本文件中输入B中的类名即可
资源加载的四种方式
一,直接拖拽
public GameObject m_Prefab
GameObject obj = GameObject.Instantiate(m_Prefab)
二,Resources.Load
前提条件 项目中有Resources 文件夹,Resources 文件夹下面不能放太多资源 大概容量2G 左右
GameObject obj = GameObject.Instantiate("Prefabs/Man") as GameObject
三,通过加载AssetBundle
前提条件项目中有StreamAssets文件夹 以及需要加载的文件是Assetsbundle 资源
AssetBundle assetBundle = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/attack");
//GameObject obj = GameObject.Instantiate(assetBundle.LoadAsset<GameObject>("attack"));
四,通过UnityEditor.AssetDatabase.LoadAssetAtPath 加载
GameObject obj = GameObject.Instantiate(UnityEditor.AssetDatabase.LoadAssetAtPath<GameObject>("Assets/GameData/Prefabs/Attack.prefab"));
后面路径下的文件名一定要带后缀**
文件夹下的资源打成AssetBundle资源 方式
先选中资源 然后将设置该资源的usename, 然后建一个Ediotr文件夹 新建一个脚本 加入编辑器拓展代码
【MenuItem(Tools/打包AssetBundle)】
public static void CreatABPack(string outputPath)
{
BuildPipeline.BuildAssetBundles (packagePath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
AssetDatabase.Refresh (); (刷新项目文件)
}
XML 序列化和反序列化
先创建我们需要序列化的数据的结构和格式
Xml 序列化
void SerilizeTest()
{
TestSerilize testSerilize = new TestSerilize();
testSerilize.Id = 1;
testSerilize.Name = "测试";
testSerilize.List = new List<int>();
testSerilize.List.Add(2);
testSerilize.List.Add(3);
XmlSerilize(testSerilize);
}
void XmlSerilize(TestSerilize testSerilize)
{
FileStream fileStream = new FileStream(Application.dataPath + "/test.xml", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fileStream, System.Text.Encoding.UTF8);
XmlSerializer xml = new XmlSerializer(testSerilize.GetType());
xml.Serialize(sw, testSerilize);
sw.Close();
fileStream.Close();
}
以上代码便能在指定路径创建出含数据的xml 文件
Xml反序列化
TestSerilize XmlDeSerilize()
{
FileStream fs = new FileStream(Application.dataPath + "/test.xml", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
XmlSerializer xs = new XmlSerializer(typeof(TestSerilize));
TestSerilize testSerilize = (TestSerilize)xs.Deserialize(fs);
fs.Close();
return testSerilize;
}
void DeSerilizerTest()
{
TestSerilize testSerilize = XmlDeSerilize();
Debug.Log(testSerilize.Id +" " + testSerilize.Name);
foreach (int a in testSerilize.List)
{
Debug.Log(a);
}
}
二进制文件序列化
void BinarySerTest()
{
TestSerilize testSerilize = new TestSerilize();
testSerilize.Id = 5;
testSerilize.Name = "二进制测试";
testSerilize.List = new List<int>();
testSerilize.List.Add(10);
testSerilize.List.Add(18);
BinarySerilize(testSerilize);
}
void BinarySerilize(TestSerilize serilize)
{
FileStream fs = new FileStream(Application.dataPath + "/test.bytes", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, serilize);
fs.Close();
}
以上代码可在指定路径生成二进制文件
二进制文件反向序列化
TestSerilize BinaryDeserilize()
{
TextAsset textAsset = UnityEditor.AssetDatabase.LoadAssetAtPath<TextAsset>("Assets/test.bytes");
MemoryStream stream = new MemoryStream(textAsset.bytes);
BinaryFormatter bf = new BinaryFormatter();
TestSerilize testSerilize = (TestSerilize)bf.Deserialize(stream);
stream.Close();
return testSerilize;
}
void BinaryDeSerTest()
{
TestSerilize testSerilize = BinaryDeserilize();
Debug.Log(testSerilize.Id + " " + testSerilize.Name);
foreach (int a in testSerilize.List)
{
Debug.Log(a);
}
}
Asset 序列化
首先先创建一个Asset 文件
void ReadTestAssets()
{
//AssetsSerilize assets = UnityEditor.AssetDatabase.LoadAssetAtPath<AssetsSerilize>("Assets/Scripts/TestAssets.asset");
//Debug.Log(assets.Id);
//Debug.Log(assets.Name);
//foreach (string str in assets.TestList)
//{
// Debug.Log(str);
//}
}
通过上面代码读取Asset 文件中的数据
此方法可以找到指定文件下所有指定文件类型的文件名
**string[] allStr = AssetDatabase.FindAssets("t:Prefab", abConfig.m_AllPrefabPath.ToArray());**
生成进度条窗口
**EditorUtility.DisplayProgressBar("清除AB包名", "名字:" + oldABNames[i], i * 1.0f / oldABNames.Length);**
public class BundleEditor
{
private static string m_BunleTargetPath = Application.dataPath+"/../AssetBundle/" + EditorUserBuildSettings.activeBuildTarget.ToString();
private static string ABCONFIGPATH = "Assets/RealFram/Editor/Resource/ABConfig.asset";
private static string ABBYTEPATH = RealConfig.GetRealFram().m_ABBytePath;
//key是ab包名,value是路径,所有文件夹ab包dic
private static Dictionary<string, string> m_AllFileDir = new Dictionary<string, string>();
//过滤的list
private static List<string> m_AllFileAB = new List<string>();
//单个prefab的ab包
private static Dictionary<string, List<string>> m_AllPrefabDir = new Dictionary<string, List<string>>();
//储存所有有效路径
private static List<string> m_ConfigFil = new List<string>();
[MenuItem("Tools/打包")]
public static void Build()
{
DataEditor.AllXmlToBinary();
m_ConfigFil.Clear();
m_AllFileAB.Clear();
m_AllFileDir.Clear();
m_AllPrefabDir.Clear();
ABConfig abConfig = AssetDatabase.LoadAssetAtPath<ABConfig>(ABCONFIGPATH);
foreach (ABConfig.FileDirABName fileDir in abConfig.m_AllFileDirAB)
{
if (m_AllFileDir.ContainsKey(fileDir.ABName))
{
Debug.LogError("AB包配置名字重复,请检查!");
}
else
{
m_AllFileDir.Add(fileDir.ABName, fileDir.Path);
m_AllFileAB.Add(fileDir.Path);
m_ConfigFil.Add(fileDir.Path);
}
}
string[] allStr = AssetDatabase.FindAssets("t:Prefab", abConfig.m_AllPrefabPath.ToArray());
for (int i = 0; i < allStr.Length; i++)
{
string path = AssetDatabase.GUIDToAssetPath(allStr[i]);
EditorUtility.DisplayProgressBar("查找Prefab", "Prefab:" + path, i * 1.0f / allStr.Length);
m_ConfigFil.Add(path);
if (!ContainAllFileAB(path))
{
GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
string[] allDepend = AssetDatabase.GetDependencies(path);
List<string> allDependPath = new List<string>();
for (int j = 0; j < allDepend.Length; j++)
{
if (!ContainAllFileAB(allDepend[j]) && !allDepend[j].EndsWith(".cs"))
{
m_AllFileAB.Add(allDepend[j]);
allDependPath.Add(allDepend[j]);
}
}
if (m_AllPrefabDir.ContainsKey(obj.name))
{
Debug.LogError("存在相同名字的Prefab!名字:" + obj.name);
}
else
{
m_AllPrefabDir.Add(obj.name, allDependPath);
}
}
}
foreach (string name in m_AllFileDir.Keys)
{
SetABName(name, m_AllFileDir[name]);
}
foreach (string name in m_AllPrefabDir.Keys)
{
SetABName(name, m_AllPrefabDir[name]);
}
BunildAssetBundle();
string[] oldABNames = AssetDatabase.GetAllAssetBundleNames();
for (int i = 0; i < oldABNames.Length; i++)
{
AssetDatabase.RemoveAssetBundleName(oldABNames[i], true);
EditorUtility.DisplayProgressBar("清除AB包名", "名字:" + oldABNames[i], i * 1.0f / oldABNames.Length);
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.ClearProgressBar();
}
static void SetABName(string name, string path)
{
AssetImporter assetImporter = AssetImporter.GetAtPath(path);
if (assetImporter == null)
{
Debug.LogError("不存在此路径文件:" + path);
}
else
{
assetImporter.assetBundleName = name;
}
}
static void SetABName(string name, List<string> paths)
{
for (int i = 0; i < paths.Count; i++)
{
SetABName(name, paths[i]);
}
}
static void BunildAssetBundle()
{
string[] allBundles = AssetDatabase.GetAllAssetBundleNames();
//key为全路径,value为包名
Dictionary<string, string> resPathDic = new Dictionary<string, string>();
for (int i = 0; i < allBundles.Length; i++)
{
string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]);
for (int j = 0; j < allBundlePath.Length; j++)
{
if (allBundlePath[j].EndsWith(".cs"))
continue;
Debug.Log("此AB包:" + allBundles[i] + "下面包含的资源文件路径:" + allBundlePath[j]);
resPathDic.Add(allBundlePath[j], allBundles[i]);
}
}
if (!Directory.Exists(m_BunleTargetPath))
{
Directory.CreateDirectory(m_BunleTargetPath);
}
DeleteAB();
//生成自己的配置表
WriteData(resPathDic);
AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(m_BunleTargetPath, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
if (manifest == null)
{
Debug.LogError("AssetBundle 打包失败!");
}
else
{
Debug.Log("AssetBundle 打包完毕");
}
}
static void WriteData(Dictionary<string ,string> resPathDic)
{
AssetBundleConfig config = new AssetBundleConfig();
config.ABList = new List<ABBase>();
foreach (string path in resPathDic.Keys)
{
if (!ValidPath(path))
continue;
ABBase abBase = new ABBase();
abBase.Path = path;
abBase.Crc = Crc32.GetCrc32(path);
abBase.ABName = resPathDic[path];
abBase.AssetName = path.Remove(0, path.LastIndexOf("/") + 1);
abBase.ABDependce = new List<string>();
string[] resDependce = AssetDatabase.GetDependencies(path);
for (int i = 0; i < resDependce.Length; i++)
{
string tempPath = resDependce[i];
if (tempPath == path || path.EndsWith(".cs"))
continue;
string abName = "";
if (resPathDic.TryGetValue(tempPath, out abName))
{
if (abName == resPathDic[path])
continue;
if (!abBase.ABDependce.Contains(abName))
{
abBase.ABDependce.Add(abName);
}
}
}
config.ABList.Add(abBase);
}
//写入xml
string xmlPath = Application.dataPath + "/AssetbundleConfig.xml";
if (File.Exists(xmlPath)) File.Delete(xmlPath);
FileStream fileStream = new FileStream(xmlPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fileStream, System.Text.Encoding.UTF8);
XmlSerializer xs = new XmlSerializer(config.GetType());
xs.Serialize(sw, config);
sw.Close();
fileStream.Close();
//写入二进制
foreach (ABBase abBase in config.ABList)
{
abBase.Path = "";
}
FileStream fs = new FileStream(ABBYTEPATH, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
fs.Seek(0, SeekOrigin.Begin);
fs.SetLength(0);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs, config);
fs.Close();
AssetDatabase.Refresh();
SetABName("assetbundleconfig", ABBYTEPATH);
}
/// <summary>
/// 删除无用AB包
/// </summary>
static void DeleteAB()
{
string[] allBundlesName = AssetDatabase.GetAllAssetBundleNames();
DirectoryInfo direction = new DirectoryInfo(m_BunleTargetPath);
FileInfo[] files = direction.GetFiles("*", SearchOption.AllDirectories);
for (int i = 0; i < files.Length; i++)
{
if (ConatinABName(files[i].Name, allBundlesName) || files[i].Name.EndsWith(".meta")|| files[i].Name.EndsWith(".manifest") || files[i].Name.EndsWith("assetbundleconfig"))
{
continue;
}
else
{
Debug.Log("此AB包已经被删或者改名了:" + files[i].Name);
if (File.Exists(files[i].FullName))
{
File.Delete(files[i].FullName);
}
if(File.Exists(files[i].FullName + ".manifest"))
{
File.Delete(files[i].FullName + ".manifest");
}
}
}
}
/// <summary>
/// 遍历文件夹里的文件名与设置的所有AB包进行检查判断
/// </summary>
/// <param name="name"></param>
/// <param name="strs"></param>
/// <returns></returns>
static bool ConatinABName(string name, string[] strs)
{
for (int i = 0; i < strs.Length; i++)
{
if (name == strs[i])
return true;
}
return false;
}
/// <summary>
/// 是否包含在已经有的AB包里,做来做AB包冗余剔除
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
static bool ContainAllFileAB(string path)
{
for (int i = 0; i < m_AllFileAB.Count; i++)
{
if (path == m_AllFileAB[i] || (path.Contains(m_AllFileAB[i]) && (path.Replace(m_AllFileAB[i],"")[0] == '/')))
return true;
}
return false;
}
/// <summary>
/// 是否有效路径
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
static bool ValidPath(string path)
{
for (int i = 0; i < m_ConfigFil.Count; i++)
{
if (path.Contains(m_ConfigFil[i]))
{
return true;
}
}
return false;
}
}
此方法可以获取所有的AB 包并且移除他们的useName
string[] oldABNames = AssetDatabase.GetAllAssetBundleNames();
for (int i = 0; i < oldABNames.Length; i++)
{
AssetDatabase.RemoveAssetBundleName(oldABNames[i], true);
EditorUtility.DisplayProgressBar("清除AB包名", "名字:" + oldABNames[i], i * 1.0f / oldABNames.Length);
}
此方法可以获取 当前AB包名(allBundles[i]) 下包含的所有资源文件路径
string[] allBundles = AssetDatabase.GetAllAssetBundleNames();
//key为全路径,value为包名
Dictionary<string, string> resPathDic = new Dictionary<string, string>();
for (int i = 0; i < allBundles.Length; i++)
{
string[] allBundlePath = AssetDatabase.GetAssetPathsFromAssetBundle(allBundles[i]);
for (int j = 0; j < allBundlePath.Length; j++)
{
if (allBundlePath[j].EndsWith(".cs"))
continue;
Debug.Log("此AB包:" + allBundles[i] + "下面包含的资源文件路径:" + allBundlePath[j]);
resPathDic.Add(allBundlePath[j], allBundles[i]);
}
}
Crc 资源的唯一识别码,虽然不如MD5值稳定 但还勉强够用
大致代码如下
public class Crc32
{
//crc表
static uint[] crcTable =
{
0x0, 0x77073096, 0xee0e612c, 0x990951ba, 0x76dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0xedb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x9b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x1db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x6b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0xf00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x86d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x3b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x4db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0xd6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0xa00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x26d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x5005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0xcb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0xbdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
//返回字符串的crc
public static uint GetCrc32(string msg)
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(msg);
int iCount = bytes.Length;
uint crc = 0xFFFFFFFF;
for (int i = 0; i < iCount; i++)
{
crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];
}
return crc ^ 0xffffffff;
}
如果拥有当前资源路径
Assets/GameResources/Prefabs/model.prefab
想获取资源名 model.prefab
则可以用字符串移除的方式
abBase.AssetName = path.Remove(0, path.LastIndexOf("/") + 1);
防止因为文件夹相似而过滤掉正确路径的方法
剔除相同部分 如果第一个字符是斜杠/ 则代表在同一路径
static bool ContainAllFileAB(string path)
{
for (int i = 0; i < m_AllFileAB.Count; i++)
{
if (path == m_AllFileAB[i] || (path.Contains(m_AllFileAB[i]) && (path.Replace(m_AllFileAB[i],"")[0] == '/')))
return true;
}
return false;
}
Application.streamingAssetsPath路径 特点
1)只读不可写。
2)主要用来存放二进制文件。
3)只能用过WWW类来读取。
4)可以异步加载,ab包存放于此,项目中常用。
Resources路径 特点
1)只读,即不能动态修改。所以想要动态更新的资源不要放在这里。
2)会将文件夹内的资源打包集成到.asset文件里面。因此建议可以放一些Prefab,因为Prefab在打包时会自动过滤掉不需要的资源,有利于减小资源包的大小。
3)资源读取常用Resources.Load(),不过是同步的,阻塞模式,不建议使用加载大的资源。
4)Resources.LoadAsync(),是异步的,非阻塞模式。
5)不常用 建议你忘掉它,只是用来入门用的。实际开发中很少用到。
Application.streamingAssetsPath路径特点
1)内容可读写,不过只能运行时才能写入或者读取。 提前将数据存入这个路径是不可行的。无内容限制。
2)你可以从 StreamingAsset 中读取二进制文件或者从 AssetBundle 读取文件来写入 PersistentDataPath 中。
3)需要使用WWW类来读取。
4)热更的重要路径,该文件夹可读可写,在移动端唯一一个可读写操作的文件夹。
以上更多特点参考文章
https://zhuanlan.zhihu.com/p/208870436
总结
//要序列化当前类为XML文件必须添加此命名空间
**using System.Xml.Serialization;
给类添加上System.Serializable 之后
便可让下面类型的对象在编辑器面板上可以显示对象中的变量值(类中的属性显示不出来)
类对象池知识当我们想要创建很多单利Manager类时,我们可以创建一个单利泛型原型类来给其他类继承
public class Singleton<T> where T : new()
{
private static T m_Instance;
public static T Instance
{
get
{
if (m_Instance == null)
{
m_Instance = new T();
}
return m_Instance;
}
}
}
where 限定New() 只要类是New成的都可
类里面析构函数的写法
一个类只能有一个解构器。
解构器不能被继承或重载。
解构器不能被调用。他们是自动被(编译器)调用的。
解构器不能带修饰或参数。
析构函数和构造bai函数正好相反.
构造函数du是和类同名.没有返zhi回值dao.
析构函数zhuan是在类名前shu加~.也没有返回值.
构造函数上在对象创建时执行.
析构函数是在程序结束时执行.
一般时候析构函数里面写的都是一些资源回收之类的东西.
不过C#的析构函数的调用机制和C++不同.并不能保证每次都会调用.所以最好不要利用C#的析构函数来回收资源.