Unity 代理模式(实例详解)

文章目录

      • 实例1:资源加载代理(Asset Loading Proxy)
      • 实例2:网络请求代理(Network Request Proxy)
      • 实例3:性能优化代理(Performance Optimization Proxy)
      • 实例4:权限控制代理(Authorization Control Proxy)
      • 实例5:热更新代理(Hot Reload Proxy)

在Unity游戏开发中,代理模式(Proxy Design Pattern)用于为另一个对象提供一个代理以控制对这个对象的访问。以下是在Unity环境下实现代理模式的5个不同代码实例说明:

实例1:资源加载代理(Asset Loading Proxy)

// 原始资源加载接口
public interface IResourceLoader
{
    Texture2D LoadTexture(string path);
}

// 真实资源加载器
public class RealResourceLoader : IResourceLoader
{
    public Texture2D LoadTexture(string path)
    {
        return Resources.Load<Texture2D>(path);
    }
}

// 资源加载代理,负责异步加载并缓存资源
public class AssetLoadingProxy : IResourceLoader
{
    private Dictionary<string, IEnumerator> _loadingTasks;
    private RealResourceLoader _realLoader;

    public AssetLoadingProxy()
    {
        _loadingTasks = new Dictionary<string, IEnumerator>();
        _realLoader = new RealResourceLoader();
    }

    public IEnumerator LoadTextureAsync(string path, Action<Texture2D> onLoaded)
    {
        if (!_loadingTasks.ContainsKey(path))
        {
            var www = UnityWebRequestTexture.GetTexture(path);
            yield return www.SendWebRequest();

            if (www.result == UnityWebRequest.Result.Success)
            {
                var texture = DownloadHandlerTexture.GetContent(www);
                _loadingTasks[path] = null; // 移除任务记录,避免重复加载
                onLoaded?.Invoke(texture);
            }
            else
            {
                Debug.LogError($"Failed to load texture: {www.error}");
            }
        }
        else
        {
            while (_loadingTasks[path] != null)
            {
                yield return null; // 等待资源完成加载
            }
            onLoaded?.Invoke(_realLoader.LoadTexture(path)); // 加载完成后调用回调
        }
    }
}

实例2:网络请求代理(Network Request Proxy)

// 网络请求接口
public interface INetworkService
{
    void SendRequest(string url, Action<string> onResponse);
}

// 真实网络服务类
public class RealNetworkService : INetworkService
{
    public void SendRequest(string url, Action<string> onResponse)
    {
        StartCoroutine(SendRequestCoroutine(url, onResponse));
    }

    private IEnumerator SendRequestCoroutine(string url, Action<string> onResponse)
    {
        using (var request = UnityWebRequest.Get(url))
        {
            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {
                onResponse(request.downloadHandler.text);
            }
            else
            {
                Debug.LogError($"Error sending network request: {request.error}");
            }
        }
    }
}

// 网络请求代理,添加了请求队列和错误重试机制
public class NetworkRequestProxy : INetworkService
{
    private INetworkService _realService;
    private Queue<Action> _requestQueue;
    private int _maxRetryCount;

    public NetworkRequestProxy(INetworkService realService, int maxRetries)
    {
        _realService = realService;
        _requestQueue = new Queue<Action>();
        _maxRetryCount = maxRetries;
    }

    public void SendRequest(string url, Action<string> onResponse)
    {
        _requestQueue.Enqueue(() => _realService.SendRequest(url, response =>
        {
            if (!string.IsNullOrEmpty(response) || --_maxRetryCount < 0)
            {
                onResponse(response);
            }
            else
            {
                SendRequest(url, onResponse); // 重试请求
            }
        }));

        ProcessNextRequest(); // 开始处理队列中的下一个请求
    }

    private void ProcessNextRequest()
    {
        if (_requestQueue.Count > 0)
        {
            var nextAction = _requestQueue.Dequeue();
            StartCoroutine(ProcessRequestCoroutine(nextAction));
        }
    }

    private IEnumerator ProcessRequestCoroutine(Action action)
    {
        yield return new WaitForSeconds(0.1f); // 假设这里有防止频繁请求的间隔
        action();
    }
}

实例3:性能优化代理(Performance Optimization Proxy)

// 高级图形渲染组件接口
public interface IAdvancedRenderer
{
    void RenderHighQualityMesh(Mesh mesh);
}

// 真实高级渲染组件
public class RealAdvancedRenderer : IAdvancedRenderer
{
    public void RenderHighQualityMesh(Mesh mesh)
    {
        // 执行高质量、高消耗的渲染操作
        // ...
    }
}

// 性能优化代理,根据设备性能动态调整渲染质量
public class PerformanceProxyRenderer : IAdvancedRenderer
{
    private IAdvancedRenderer _realRenderer;
    private bool _isLowEndDevice;

    public PerformanceProxyRenderer(IAdvancedRenderer realRenderer, SystemInfo systemInfo)
    {
        _realRenderer = realRenderer;
        _isLowEndDevice = systemInfo.graphicsMemorySize < 1024; // 假设低于1GB显存的设备是低端设备
    }

    public void RenderHighQualityMesh(Mesh mesh)
    {
        if (!_isLowEndDevice)
        {
            _realRenderer.RenderHighQualityMesh(mesh);
        }
        else
        {
            // 执行低质量、低消耗的替代渲染操作
            RenderLowQualityMesh(mesh);
        }
    }

    private void RenderLowQualityMesh(Mesh mesh)
    {
        // ...
    }
}

实例4:权限控制代理(Authorization Control Proxy)

// 数据库访问接口
public interface IDataAccess
{
    void SaveData(UserData data);
}

// 真实数据库访问类
public class RealDataAccess : IDataAccess
{
    public void SaveData(UserData data)
    {
        // 存储用户数据到数据库
        // ...
    }
}

// 权限控制代理,确保只有管理员可以写入数据
public class AuthorizationProxy : IDataAccess
{
    private IDataAccess _realAccess;
    private IUserService _userService;

    public AuthorizationProxy(IDataAccess realAccess, IUserService userService)
    {
        _realAccess = realAccess;
        _userService = userService;
    }

    public void SaveData(UserData data)
    {
        if (_userService.IsCurrentUserAdmin())
        {
            _realAccess.SaveData(data);
        }
        else
        {
            Debug.LogWarning("Non-admin user attempted to save data.");
        }
    }
}

实例5:热更新代理(Hot Reload Proxy)

// MonoBehavior基类
public abstract class MonoBehaviourBase : UnityEngine.MonoBehaviour
{
    // 公共方法声明...
}

// 热更脚本接口
public interface IHotReloadable
{
    void OnHotReload();
}

// 热更代理MonoBehavior
public class HotReloadProxy : MonoBehaviourBase
{
    private IHotReloadable _hotReloadTarget;

    public void SetHotReloadTarget(IHotReloadable target)
    {
        _hotReloadTarget = target;
    }

    void Update()
    {
        // 如果目标实现了热更接口,则在Update时触发OnHotReload
        if (_hotReloadTarget != null && Application.isEditor && UnityEditor.EditorUtility.IsDirty(targetScript))
        {
            _hotReloadTarget.OnHotReload();
        }
    }
}

// 真实业务逻辑脚本,通过ILRuntime或类似技术热更新
[HotReloading]
public class RealBusinessLogic : IHotReloadable
{
    public void OnHotReload()
    {
        // 重新加载业务逻辑
        // ...
    }

    // 其他业务逻辑...
}

这些例子展示了如何在Unity中使用代理模式来解决资源管理、网络请求、性能优化、权限控制以及热更新等场景下的问题。每个代理类都封装了一个真实对象,并提供了额外的功能或控制层。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/351156.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LC 2846. 边权重均等查询

2846. 边权重均等查询 难度&#xff1a; 困难 题目大意&#xff1a; 现有一棵由 n 个节点组成的无向树&#xff0c;节点按从 0 到 n - 1 编号。给你一个整数 n 和一个长度为 n - 1 的二维整数数组 edges &#xff0c;其中 edges[i] [ui, vi, wi] 表示树中存在一条位于节点 …

银行数据仓库体系实践(11)--数据仓库开发管理系统及开发流程

数据仓库管理着整个银行或公司的数据&#xff0c;数据结构复杂&#xff0c;数据量庞大&#xff0c;任何一个数据字段的变化或错误都会引起数据错误&#xff0c;影响数据应用&#xff0c;同时业务的发展也带来系统不断升级&#xff0c;数据需求的不断增加&#xff0c;数据仓库需…

EventSource 长链接执行

EventSource 说明文档MDN 其他参考文档 一、利用node启服务 import fs from fs import express from express const app express() // eventSource 仅支持 get 方法 // 服务器端发送的数据必须是纯文本格式&#xff0c;不能是二进制数据。 app.get(/api, (req, res) > …

项目性能优化之用compression-webpack-plugin插件开启gzip压缩

背景&#xff1a;vue项目打包发布后&#xff0c;部分js、css文件体积较大导致页面卡顿&#xff0c;于是使用webpack插件compression-webpack-plugin开启gzip压缩 前端配置vue.config.js 先通过npm下载compression-webpack-plugin包&#xff0c;npm i compression-webpack-plug…

Android SharedPreferences源码分析

文章目录 Android SharedPreferences源码分析概述基本使用源码分析获取SP对象初始化和读取数据写入数据MemoryCommitResultcommitToMemory()commit()apply()enqueueDiskWrite()writeToFile() 主动等待写回任务结束 总结 Android SharedPreferences源码分析 概述 SharedPrefer…

EXCEL VBA抓取网页JSON数据并解析

EXCEL VBA抓取网页JSON数据并解析 链接地址&#xff1a; https://api.api68.com/CQShiCai/getBaseCQShiCaiList.do?lotCode10036&date2024-01-26 Sub test() On Error Resume Next Sheet.Select Sheet1.Cells.ClearContents [a1:g1] Split("preDrawIssue|preDrawTi…

Ubuntu20.04添加桌面启动、侧边栏启动和终端启动

桌面启动 新建XX.desktop文件 在桌面新建一个XX.desktop文件&#xff0c;以QtCreator为例。 &#xff08;注意这里不能使用sudo&#xff0c;因为这样会把文件的权限归为root&#xff0c;导致后续设置可执行程序不方便&#xff09; gedit qtcreator.desktop在XX.desktop文件中…

第14次修改了可删除可持久保存的前端html备忘录:增加一个翻牌钟,修改背景主题:现代深色

第14次修改了可删除可持久保存的前端html备忘录&#xff1a;增加一个翻牌钟&#xff0c;修改背景主题&#xff1a;现代深色 备忘录代码 <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta http-equiv"X…

设计模式—行为型模式之责任链模式

设计模式—行为型模式之责任链模式 责任链&#xff08;Chain of Responsibility&#xff09;模式&#xff1a;为了避免请求发送者与多个请求处理者耦合在一起&#xff0c;于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链&#xff1b;当有请求发生时&am…

Flink面试题

0. 思维导图 1. 简单介绍一下Flink♥♥ Flink是一个分布式的计算框架&#xff0c;主要用于对有界和无界数据流进行有状态计算&#xff0c;其中有界数据流就是值离线数据&#xff0c;有明确的开始和结束时间&#xff0c;无界数据流就是指实时数据&#xff0c;源源不断没有界限&a…

ES文档索引、查询、分片、文档评分和分析器技术原理

技术原理 索引文档 索引文档分为单个文档和多个文档。 单个文档 新建单个文档所需要的步骤顺序&#xff1a; 客户端向 Node 1 发送新建、索引或者删除请求。节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3&#xff0c;因为分片 0 的主分片目前被分配在 …

Android源码设计模式解析与实战第2版笔记(二)

第二章 应用最广的模式 — 单例模式 单例模式的定义 确保某一个类只有一个实例&#xff0c;而且自行实例化并向整个系统提供这个实例。 单例模式的使用场景 确保某个类有且只有一个对象的场景&#xff0c;避免产生多个对象消耗过多的资源&#xff0c;或者某种类型的对象只应…

DT浏览器浏览网页的技巧

DT浏览器浏览网页的技巧&#xff1a; 1. 使用书签和收藏夹&#xff1a;将常用的网页添加到书签或收藏夹中&#xff0c;方便快速访问。 2. 善用搜索引擎&#xff1a;使用搜索引擎可以快速找到你需要的信息。在搜索时&#xff0c;可以使用关键词和筛选条件来精确查找。 3. 注意网…

【C/C++】详解程序环境和预处理(什么是程序环境?为什么要有程序环境?如何理解程序环境?)

目录 一、前言 二、 什么是程序环境&#xff1f; 三、 为什么要有程序环境&#xff1f; 四、如何理解程序环境&#xff1f; &#x1f34e; ANSI C 标准 &#x1f350; 翻译环境和执行环境 五、详解翻译环境和执行环境 &#x1f347;翻译环境&#xff08;重点&#xff01…

米贸搜|Meta金融科技行业广告政策Facebook

当前全球金融科技行业正处于快速发展阶段&#xff0c;作为全球最大的社交媒体网络之一&#xff0c;Meta平台为金融科技公司提供了一个重要的业务营销渠道&#xff0c;使其能够在广大用户群体中宣传和推广其产品和服务。 金融科技企业通过Meta平台投放广告&#xff0c;要注重政策…

Mac网线上网绿联扩展坞连接网线直接上网-无脑操作

声明&#xff1a;博主使用的绿联扩展坞 以下为绿联扩展坞Mac网线使用方法 1.首先需要下载电脑对应版本的驱动 直接点击即可下载 2. 下载好以后 解压 点进去 对应版本 博主直接使用最新的12-14 3. 安装包好了以后 会提示重启电脑 此时拔掉扩展坞 再重启动 拔掉扩展坞 再重启…

【机组】单元模块实验的综合调试与驻机键盘和液晶显示器的使用方式

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《机组 | 模块单元实验》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 1. 综合实验的调试 1.1 实验…

three.js 鼠标选中模型弹出标签

效果&#xff1a;请关注抖音 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red;position: relative;"></div><…

Emergent Abilities of Large Language Models 机翻mark

摘要 证明通过扩大语言模型可以可靠地提高性能和样本效率在广泛的下游任务。相反&#xff0c;本文讨论了我们称之为大型语言模型的新兴能力的一种不可预测的现象。我们认为如果一个能力不存在于较小的模型中&#xff0c;但在较大的模型中存在&#xff0c;则该能力就是新兴的。…

springboot 整合 Activiti6

1.添加maven依赖 <dependency><groupId>org.activiti</groupId><artifactId>activiti-spring-boot-starter-basic</artifactId><version>6.0.0</version> </dependency>2.添加配置 spring:activiti:check-process-definitio…