防止单例随场景销毁和跨场景两个物体脚本问题
通过泛型封装单例类
NormalSingleton.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;//标准单例类public class NormalSingleton where T : class, new(){ private static T _single; public static T Singel { get { if (_single == null) { T t = new T(); if (t is MonoBehaviour) { Debug.LogError("Mono类请使用MonoSingleTon!"); return null; } _single = t; } return _single; } }}
MonoSingleton.cs
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//Mono单例类public class MonoSingleton : MonoBehaviour where T : MonoBehaviour{ private static T _singleton; public static T SingleTon { get { if (_singleton == null) { _singleton = FindObjectOfType(); if (_singleton == null) { Debug.LogError("场景中未找到类的对象,类名为:"+typeof(T).Name); } } return _singleton; } } private void Awake() { if (_singleton == null) { DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } }}
通过物体路径自动挂载脚本(游戏预制物体名字 和 脚本名字得一样)(方式一)
ILoader接口 给ResourceLoder 和 ABLoader实现
ILoader.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public interface ILoader { /// /// Resource方法加载物体 /// /// 加载物体的路径 /// 指定父物体 /// GameObject LoadPrefab(string path, Transform parent = null);}
Resource加载器
ResourceLoader.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class ResourceLoader : ILoader{ /// /// Resource方法加载物体 /// /// 加载物体的路径 /// 指定父物体 /// public GameObject LoadPrefab(string path,Transform parent = null) { GameObject go = Resources.Load(path); GameObject go2 = Object.Instantiate(go, parent); return go2; } }
AB包加载器 (没有实现 共理清逻辑使用)
ABLoader.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;public class ABLoader : ILoader{ public GameObject LoadPrefab(string path, Transform parent = null) { throw new System.NotImplementedException(); }}
LoadManager场景加载器
LoadManager.cs
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//加载管理器public class LoadManager : NormalSingleton{ [SerializeField] private ILoader iLoader; public LoadManager() { //Resource加载方式 iLoader = new ResourceLoader(); //AB包加载方式 // iLoader = new ABLoader(); } //自动挂载脚本加载物体方式一(通过脚本与游戏物体同名) public GameObject LoadPrefab(string path, Transform parent = null) { GameObject go = iLoader.LoadPrefab(path, parent); //通过物体名 自动挂载脚本(游戏物体名字 和 脚本名字得一样) Type type = Type.GetType(go.name.Remove(go.name.Length - 7)); go.AddComponent(type); return go; } //自动挂载脚本加载物体方式二(通过反射特性) // public GameObject LoadPrefab(string path, Transform parent = null) // { // GameObject go = iLoader.LoadPrefab(path, parent); // Type type = BindUtil.GetType(path); // go.AddComponent(type); // return go; // }}using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//加载管理器public class LoadManager : NormalSingleton{ [SerializeField] private ILoader iLoader; public LoadManager() { //Resource加载方式 iLoader = new ResourceLoader(); //AB包加载方式 // iLoader = new ABLoader(); } //自动挂载脚本加载物体方式一(通过脚本与游戏物体同名) public GameObject LoadPrefab(string path, Transform parent = null) { GameObject go = iLoader.LoadPrefab(path, parent); //通过物体名 自动挂载脚本(游戏物体名字 和 脚本名字得一样) Type type = Type.GetType(go.name.Remove(go.name.Length - 7)); go.AddComponent(type); return go; } //自动挂载脚本加载物体方式二(通过反射特性) // public GameObject LoadPrefab(string path, Transform parent = null) // { // GameObject go = iLoader.LoadPrefab(path, parent); // Type type = BindUtil.GetType(path); // go.AddComponent(type); // return go; // }}
启动游戏入口 需要挂在在游戏物体上
using System.Collections;using System.Collections.Generic;using UnityEngine;//启动游戏入口public class LaunchGame : MonoBehaviour{ // Start is called before the first frame update void Start() { //通过反射特性 加载方式二 // InitCustermonAttribute initCustermonAttribute = new InitCustermonAttribute(); // initCustermonAttribute.init(); LoadManager.Singel.LoadPrefab("Prefab/StartView",transform); } }
启动入口挂载在Cavas上 加载的预制体 会做为其子物体
运行效果:
通过游戏物体路径 反射特性 自动加载预制体和脚本(方式二)
绑定物体特性
BindPrefab.cs
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//绑定物体特性[AttributeUsage(AttributeTargets.Class)]public class BindPrefab : Attribute{ public string Path { get; private set;} public BindPrefab(string path) { Path = path; }}
加载物体同名脚本 通过路径反射
StartView.cs
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//加载物体同名脚本 通过路径反射[BindPrefab("Prefab/StartView")]public class StartView : MonoBehaviour{ }
绑定工具类
BindUtil.cs
using System;using System.Collections;using System.Collections.Generic;using System.Linq;using UnityEngine;//绑定工具类public class BindUtil : MonoBehaviour{ public static Dictionary _Dictionary = new Dictionary(); public static void Bind(string path,Type type) { if (!_Dictionary.ContainsKey(path)) { _Dictionary.Add(path,type); } else { Debug.LogError("当前数据已存在路径: "+path); } } public static Type GetType(string path) { if (_Dictionary.ContainsKey(path)) { return _Dictionary[path]; } else { Debug.LogError("数据未包含路径:"+path); return null; } }}
初始化自定义特性
InitCustermonAttribute.cs
using System;using System.Collections;using System.Collections.Generic;using System.Reflection;using UnityEngine;//初始化自定义特性public class InitCustermonAttribute : MonoBehaviour{ public void init() { Assembly assembly = Assembly.GetAssembly(typeof(BindPrefab)); Type[] types = assembly.GetExportedTypes(); foreach (Type type in types) { foreach (Attribute attribute in Attribute.GetCustomAttributes(type,true)) { if (attribute is BindPrefab) { BindPrefab data = attribute as BindPrefab; BindUtil.Bind(data.Path,type); } } } }}
加载管理器
LoadManager.cs
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;//加载管理器public class LoadManager : NormalSingleton{ [SerializeField] private ILoader iLoader; public LoadManager() { //Resource加载方式 iLoader = new ResourceLoader(); //AB包加载方式 // iLoader = new ABLoader(); } //自动挂载脚本加载物体方式一(通过脚本与游戏物体同名) // public GameObject LoadPrefab(string path, Transform parent = null) // { // GameObject go = iLoader.LoadPrefab(path, parent); // //通过物体名 自动挂载脚本(游戏物体名字 和 脚本名字得一样) // Type type = Type.GetType(go.name.Remove(go.name.Length - 7)); // go.AddComponent(type); // return go; // } //自动挂载脚本加载物体方式二(通过反射特性) public GameObject LoadPrefab(string path, Transform parent = null) { GameObject go = iLoader.LoadPrefab(path, parent); Type type = BindUtil.GetType(path); go.AddComponent(type); return go; }}
启动游戏入口
LaunchGame.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;//启动游戏入口public class LaunchGame : MonoBehaviour{ // Start is called before the first frame update void Start() { //通过反射特性 加载方式二 InitCustermonAttribute initCustermonAttribute = new InitCustermonAttribute(); initCustermonAttribute.init(); LoadManager.Singel.LoadPrefab("Prefab/StartView",transform); } }