当前位置: 首页 > news >正文

Unity_飞机大战_防止单例随场景销毁和跨场景两个物体脚本问题_自动加载物体挂载脚本的两种方式

防止单例随场景销毁和跨场景两个物体脚本问题

通过泛型封装单例类 

NormalSingleton.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//标准单例类
public class NormalSingleton<T> 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<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T _singleton;

    public static T SingleTon
    {
        get
        {
            if (_singleton == null)
            {
                _singleton = FindObjectOfType<T>();
                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 
{
    /// <summary>
    /// Resource方法加载物体
    /// </summary>
    /// <param name="path">加载物体的路径</param>
    /// <param name="parent">指定父物体</param>
    /// <returns></returns>
    GameObject LoadPrefab(string path, Transform parent = null);
}

Resource加载器

ResourceLoader.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ResourceLoader : ILoader
{
   /// <summary>
   /// Resource方法加载物体
   /// </summary>
   /// <param name="path">加载物体的路径</param>
   /// <param name="parent">指定父物体</param>
   /// <returns></returns>
   public GameObject LoadPrefab(string path,Transform parent = null)
   {
      GameObject go = Resources.Load<GameObject>(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<LoadManager>
{   
    [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<LoadManager>
{   
    [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<string, Type> _Dictionary = new Dictionary<string, Type>();

    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<LoadManager>
{   
    [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);
    }
    
}

运行效果:

加载器结构目录

 

相关文章:

  • taro 兼容支付宝小程序和微信小程序<七>-- 上传图片及图片转base64
  • 【附源码】计算机毕业设计SSM汽车交易平台
  • 购买域名-腾讯云
  • 【Linux练习生】Linux多线程
  • JavavEE中网络编程Socket套接字Ⅱ(TCP)
  • Intel汇编-函数使用堆栈传递数据
  • 【Android程序开发】常用布局--线性布局LinearLayout
  • 基于Dijkstra、A*和动态规划的移动机器人路径规划(Matlab代码实现)
  • 国产EDA与FPGA芯片验证方案
  • 一种更优雅书写Python代码的方式
  • 自定义类型(结构体、位段、联合体、枚举)
  • 如何基于 GORM 实现 CreateOrUpdate 方法
  • Spring Boot核心之基本配置、日志配置、自动配置、条件注解
  • ArcGIS校园3D展示图制作详细教程
  • 【算法 | 实验6-1】n*n的网格,从左上角开始到右下角结束遍历所有的方块仅一次,总共有多少种不同的遍历路径
  • Google 是如何开发 Web 框架的
  • 【Linux系统编程】快速查找errno错误码信息
  • CSS 提示工具(Tooltip)
  • ES6之路之模块详解
  • Java 最常见的 200+ 面试题:面试必备
  • Java,console输出实时的转向GUI textbox
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Node + FFmpeg 实现Canvas动画导出视频
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 创建一个Struts2项目maven 方式
  • 从PHP迁移至Golang - 基础篇
  • 代理模式
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 使用权重正则化较少模型过拟合
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 一些关于Rust在2019年的思考
  • 硬币翻转问题,区间操作
  • PostgreSQL之连接数修改
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​iOS安全加固方法及实现
  • ​力扣解法汇总946-验证栈序列
  • (¥1011)-(一千零一拾一元整)输出
  • (C)一些题4
  • (pojstep1.1.2)2654(直叙式模拟)
  • (Ruby)Ubuntu12.04安装Rails环境
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转载)虚函数剖析
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .a文件和.so文件
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core使用NPOI导出复杂,美观的Excel详解