Unity 桥接模式(实例详解)

news2025/2/23 6:57:22

文章目录

      • 示例1:角色与装备系统
      • 示例2:UI控件库
      • 示例3:渲染引擎模块
      • 示例4:AI决策树算法
      • 示例5:物理模拟引擎

在Unity游戏开发中,桥接模式(Bridge Pattern)是一种设计模式,它用于将抽象部分与其实现部分分离,从而允许它们独立变化。这种模式适用于以下场景:

  1. 当一个类有多个维度的变化,并且希望这些变化可以独立扩展而不影响彼此时。
  2. 如果直接使用继承来处理多维度变化会导致类爆炸问题,即需要创建大量子类。

桥接模式的组成部分:

  • 抽象(Abstraction):定义了抽象接口,并包含对实现部分(Implementor)的操作。在Unity中,这可能是某个基础组件或接口,它提供了通用的功能描述,但不关心具体的实现细节。

例如:

public interface ICharacterControl
{
    void Move();
    void Attack();
    void SetWeapon(IWeapon weapon);
}

public interface IWeapon
{
    void Fire();
    void Reload();
}
  • 提炼的抽象(Refined Abstraction):继承自抽象类的具体角色,它可能会添加更多特定的行为,同时调用实现部分的方法。
public class Soldier : MonoBehaviour, ICharacterControl
{
    private IWeapon _currentWeapon;

    public void Move()
    {
        // 实现移动逻辑
    }

    public void Attack()
    {
        if (_currentWeapon != null)
            _currentWeapon.Fire();
    }

    public void SetWeapon(IWeapon weapon)
    {
        _currentWeapon = weapon;
    }
}
  • 实现(Implementor):定义了实现接口,这个接口通常代表了可变的部分,如不同的武器类型。
public abstract class WeaponBase : IWeapon
{
    public abstract void Fire();
    public abstract void Reload();
}

public class Pistol : WeaponBase
{
    public override void Fire()
    {
        Debug.Log("Pistol fires!");
    }

    public override void Reload()
    {
        Debug.Log("Pistol is reloading...");
    }
}

public class Shotgun : WeaponBase
{
    public override void Fire()
    {
        Debug.Log("Shotgun fires!");
    }

    public override void Reload()
    {
        Debug.Log("Shotgun is reloading...");
    }
}

五个实例说明:

  1. 角色和装备系统:游戏角色可以有不同的移动方式(跑、走、跳等)以及不同的武器(枪、剑、魔法等),通过桥接模式可以使角色类型和武器类型相互独立地扩展。

  2. 渲染引擎模块:抽象层为渲染器接口,具体实现包括不同的渲染技术(如Direct3D、OpenGL、Vulkan等)。不论游戏采用哪种渲染技术,上层的游戏对象渲染逻辑保持不变。

  3. UI控件库:抽象层定义了一系列UI控件(按钮、文本框、滑块等)的公共行为,而具体实现可能基于不同的图形API或框架(Unity UI、NGUI、TextMeshPro等)。

  4. AI决策树算法:抽象层是决策树接口,不同类型的AI实体可以根据需求选择不同的决策树实现(简单状态机、有限状态机、蒙特卡洛搜索树等)。

  5. 物理模拟引擎:抽象层提供物理模拟功能,如碰撞检测、刚体运动等,而具体实现可以切换为不同的物理引擎(Unity内置物理引擎、PhysX、Box2D等)。

以下是在Unity中应用桥接模式的五个不同场景的简化代码示例:

示例1:角色与装备系统

// 抽象部分 - 角色接口
public interface ICharacter
{
    void Move();
    void ChangeWeapon(IWeapon weapon);
}

// 实现部分 - 武器接口
public interface IWeapon
{
    void Use();
    void Reload();
}

// 具体抽象 - 战士类,继承自ICharacter
public class Warrior : MonoBehaviour, ICharacter
{
    private IWeapon currentWeapon;

    public void Move()
    {
        // 移动逻辑
    }

    public void ChangeWeapon(IWeapon weapon)
    {
        currentWeapon = weapon;
    }

    public void Attack()
    {
        if (currentWeapon != null)
            currentWeapon.Use();
    }
}

// 实现部分的具体类 - 短剑和长弓
public class ShortSword : IWeapon
{
    public void Use()
    {
        Debug.Log("Short sword is used for attack!");
    }

    public void Reload()
    {
        // 无需重新加载
    }
}

public class LongBow : IWeapon
{
    public void Use()
    {
        Debug.Log("Long bow fires an arrow!");
    }

    public void Reload()
    {
        Debug.Log("Reloading the long bow...");
    }
}

// 在游戏运行时切换武器
var warrior = GetComponent<Warrior>();
warrior.ChangeWeapon(new ShortSword());
warrior.Attack(); // 输出:"Short sword is used for attack!"
warrior.ChangeWeapon(new LongBow());
warrior.Attack(); // 输出:"Long bow fires an arrow!"

示例2:UI控件库

// 抽象部分 - UI控件接口
public interface IUIControl
{
    void Render();
    void SetText(string text);
}

// 实现部分 - 不同UI框架下的文本框实现
public abstract class TextControlBase : IUIControl
{
    public abstract void Render();
    public abstract void SetText(string text);
}

public class UnityUITextControl : TextControlBase
{
    public UnityEngine.UI.Text unityText; // Unity UI组件

    public override void Render()
    {
        // 使用Unity UI渲染文本
    }

    public override void SetText(string text)
    {
        unityText.text = text;
    }
}

public class NGUITextControl : TextControlBase
{
    // 假设NGUI有对应的文本组件引用

    public override void Render()
    {
        // 使用NGUI渲染文本
    }

    public override void SetText(string text)
    {
        // 设置NGUI文本内容
    }
}

// 在游戏运行时创建不同的UI文本框实例
var uiText = new UnityUITextControl();
uiText.SetText("Hello from Unity UI");
uiText.Render();

var nguiText = new NGUITextControl();
nguiText.SetText("Hello from NGUI");
nguiText.Render();

示例3:渲染引擎模块

// 抽象部分 - 渲染器接口
public interface IRenderer
{
    void RenderScene(GameObject scene);
}

// 实现部分 - 不同的渲染引擎实现
public class DirectXRenderer : IRenderer
{
    public void RenderScene(GameObject scene)
    {
        // 使用DirectX渲染场景
        Debug.Log("Rendering scene with DirectX...");
    }
}

public class OpenGLRenderer : IRenderer
{
    public void RenderScene(GameObject scene)
    {
        // 使用OpenGL渲染场景
        Debug.Log("Rendering scene with OpenGL...");
    }
}

// 游戏中的场景管理器调用渲染逻辑
public class SceneManager
{
    private IRenderer _renderer;

    public SceneManager(IRenderer renderer)
    {
        _renderer = renderer;
    }

    public void RenderCurrentScene()
    {
        _renderer.RenderScene(currentScene);
    }
}

// 在游戏启动时根据需要选择渲染引擎
var directXRenderer = new DirectXRenderer();
var sceneManager = new SceneManager(directXRenderer);
sceneManager.RenderCurrentScene(); // 输出:"Rendering scene with DirectX..."

// 如果需要切换到OpenGL,只需更改渲染器实例
var openGLRenderer = new OpenGLRenderer();
sceneManager._renderer = openGLRenderer;
sceneManager.RenderCurrentScene(); // 输出:"Rendering scene with OpenGL..."

示例4:AI决策树算法

// 抽象部分 - 决策树接口
public interface IDecisionTree
{
    Action Decide(AIState state);
}

// 实现部分 - 简单状态机和有限状态机
public class SimpleStateMachine : IDecisionTree
{
    public Action Decide(AIState state)
    {
        // 根据简单状态机决定动作
        Debug.Log($"Decided action based on Simple State Machine: {state}");
        return () => { /* 执行具体动作 */ };
    }
}

public class FiniteStateMachine : IDecisionTree
{
    public Action Decide(AIState state)
    {
        // 根据有限状态机决定动作
        Debug.Log($"Decided action based on Finite State Machine: {state}");
        return () => { /* 执行具体动作 */ };
    }
}

// AI角色类使用决策树接口
public class AIBot
{
    private IDecisionTree _decisionTree;

    public AIBot(IDecisionTree decisionTree)
    {
        _decisionTree = decisionTree;
    }

    public void TakeAction(AIState currentState)
    {
        var action = _decisionTree.Decide(currentState);
        action?.Invoke();
    }
}

// 在游戏运行时选择不同的决策树
var simpleBot = new AIBot(new SimpleStateMachine());
simpleBot.TakeAction(AIState.Idle);

var fsmBot = new AIBot(new FiniteStateMachine());
fsmBot.TakeAction(AIState.Patrolling);

示例5:物理模拟引擎

// 抽象部分 - 物理引擎接口
public interface IPhysicsEngine
{
    void Simulate();
    Rigidbody CreateRigidbody(GameObject obj);
}

// 实现部分 - Unity内置物理引擎和Box2D
public class UnityPhysicsEngine : IPhysicsEngine
{
    public void Simulate()
    {
        // 调用Unity内置物理引擎进行模拟
        Physics.Simulate(Time.fixedDeltaTime);
    }

    public Rigidbody CreateRigidbody(GameObject obj)
    {
        return obj.AddComponent<Rigidbody>();
    }
}

public class Box2DPhysicsEngine : IPhysicsEngine
{
    // 假设有一个用于与Box2D交互的封装类Box2DBody

    public void Simulate()
    {
        // 使用Box2D进行物理模拟
        // ...
    }

    public Rigidbody CreateRigidbody(GameObject obj)
    {
        // 创建一个Box2D对应的刚体组件并附加到对象上
        // 返回Box2DBody的引用或包装对象
        return null; // 这里简化处理,实际需要实现创建Box2D刚体
    }
}

// 游戏中的物理世界管理器使用物理引擎接口
public class PhysicsWorldManager
{
    private IPhysicsEngine _physicsEngine;

    public PhysicsWorldManager(IPhysicsEngine physicsEngine)
    {
        _physicsEngine = physicsEngine;
    }

    public void UpdatePhysics()
    {
        _physicsEngine.Simulate();
    }

    public Rigidbody AddRigidbody(GameObject obj)
    {
        return _physicsEngine.CreateRigidbody(obj);
    }
}

// 在游戏启动时选择物理引擎
var unityPhysics = new UnityPhysicsEngine();
var physicsManager = new PhysicsWorldManager(unityPhysics);
// ...

// 如果要切换到Box2D
var box2DPhysics = new Box2DPhysicsEngine();
physicsManager._physicsEngine = box2DPhysics;

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

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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

语义分割常用评价指标

在图像处理领域中&#xff0c;语义分割是很重要的一个任务。在实际项目开发中,评估模型预测效果以及各指标的含义对于优化模型极为重要。 本文将主要评价指标的计算算法进行了详细说明,并加上注释解释每个指标的含义。这对理解各指标背后的数学原理以及能否在实践中应用或许有…

【MATLAB基础绘图第20棒】云雨图

MATLAB绘制云雨图 云雨图(Raincloud plots)MATLAB绘制云雨图横向云雨图竖向云雨图 参考 云雨图(Raincloud plots) 云雨图&#xff08;Raincloud plots&#xff09;其实是可以看成核密度估计曲线图、箱形图和抖动散点图的组合图&#xff0c;清晰、完整、美观地展示了所有数据信…

数组与 Web 程序打包

5. 数组 在Java中&#xff0c;数组是一种用于存储相同类型元素的数据结构。以下是如何定义和赋值Java数组的基本方法&#xff1a; 1. 定义数组&#xff1a; 一维数组&#xff1a; // 语法&#xff1a;elementType[] arrayName; int[] intArray; // 声明一个整型数组&#…

操作系统【OS】Ch2【大题】 PV题型分类

生产者-消费者问题&#xff1a;生产资源-消费资源理发师问题&#xff1a;服务-被服务读者-写者问题&#xff1a;同类进程不互斥、异类进程互斥哲学家进餐问题&#xff1a;只有一类进程&#xff0c;每个进程需要同时拥有多种资源才能运行单纯的同步问题&#xff1a;前驱后继图 生…

​第14节-高质量简历写作求职通关-在线测试

在线测试主要包括性格测试、综合能力测试、技能测试三类 性格测试 性格测试主要用于考察个人与工岗位的匹配程度 考察内容包含性格、能力、动机、价值观等&#xff0c;考察形式一般为给出相应的工作场景&#xff0c;让你选择最喜欢或者最不喜欢的答案 技能考试 这类测试一般是针…

xxe漏洞之scms靶场漏洞

xxe-scms 代码审核 &#xff08;1&#xff09;全局搜索simplexml_load_string simplexml_load_string--将XML字符串解释为对象 &#xff08;2&#xff09;查看源代码 ID1 $GLOBALS[HTTP_RAW_POST_DATA]就相当于file_get_contents("php://input"); 因此这里就存…

AI搜索引擎Perplexity来了,谷歌等老牌搜索引擎或许会有新的威胁?

Perplexity AI 是一家 AI 搜索初创公司&#xff0c;它通过结合内容索引技术和大型语言模型的推理能力&#xff0c;提供更便捷和高效的搜索体验。另外&#xff0c;最近很火的小兔子Rabbit R1硬件AI设备中的搜索功能正是这家公司的杰作。在短短一年半的时间里&#xff0c;一个企业…

快速了解工业交换机

工业交换机是专门为工业环境设计的数据通信设备。该设备的主要作用是满足工业控制系统对数据通信的要求&#xff0c;实现不同设备之间的数据传输和网络连接。工业交换机在适应恶劣环境、抗干扰和稳定性等方面表现更出色&#xff0c;相较于传统的商用交换机。 它的基本原理是利用…

牛客网-----跳石头

题目描述&#xff1a; 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行&#xff0c;河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间&#xff0c;有N块岩石(不含起点和终点的岩石)。在比赛过程中&#xff0…

[Linux 杂货铺] —— 权限(文件权限和目录配置)

目录 &#x1f308;前言 &#x1f4c1; 文件的属性 &#x1f4c1; 权限的概念 &#x1f4c2;拥有者和所属组&#xff08;角色&#xff09;&#xff1a; &#x1f4c2;用户&#xff08;具体的人&#xff09;&#xff1a; &#x1f4c1; 权限的管理 &#x1f4c2;1. chmod…

对读取的Excel文件数据进行拆分并发请求发送到后端服务器

首先&#xff0c;我们先回顾一下文件的读取操作&#xff1a; 本地读取Excel文件并进行数据压缩传递到服务器-CSDN博客 第一步&#xff1a;根据以上博客&#xff0c;我们将原先的handleFile方法&#xff0c;改为以下内容&#xff1a; const handleFile async(e) > {conso…

gitlab.rb主要配置

根据是否docker安装,进入挂载目录或安装目录 修改此文件,我一般是在可视化窗口中修改,有时候也在命令行手敲 将下面的配置复制到该文件中 external_url http://192.168.100.50 # nginx[listen_port] = 8000 (docker安装的这一行不需要,因为端口映射导致此处修改会导致访问…

Python 自动化办公:一键批量生成 PPT

Stata and Python 数据分析 一、导读 在实际工作中&#xff0c;经常需要批量处理Office文件&#xff0c;比如需要制作一个几十页的PPT进行产品介绍时&#xff0c;一页一页地制作不仅麻烦而且格式可能不统一。那么有什么办法可以一键生成PPT呢&#xff1f;Python提供的pptx 包…

常见PCB封装

表面贴片封装 通孔封装 公众号 | FunIO 微信搜一搜 “funio”&#xff0c;发现更多精彩内容。 个人博客 | blog.boringhex.top

Web 开发 1: Flask 框架介绍和使用

在 Web 开发中&#xff0c;Flask 是一个流行且灵活的 Python Web 框架&#xff0c;用于构建 Web 应用程序。它简洁而易于上手&#xff0c;适用于小型到中型的项目。在本篇博客中&#xff0c;我将为你介绍 Flask 框架的基础知识和常用技巧&#xff0c;帮助你更好地掌握 Web 开发…

android audio framework

linux ALSA ALSA表示高级Linux声音体系结构(Advanced Linux Sound Architecture)。它由一系列内核驱动&#xff0c;应用程序编译接口(API)以及支持Linux下声音的实用程序组成。 最上层是音频应用和声卡服务&#xff1b;ALSA Library&#xff1a;alsa 提高用户空间访问声卡设备…

【就现在这个市场环境,还是别选游戏开发行业了】

就现在这个市场环境&#xff0c;还是别选游戏开发行业了 最近上网闲逛时我发现&#xff0c;一提到“怎样进入游戏开发行业&#xff1f;”&#xff0c; 大部分都是劝退。 劝退的点大致有以下几点&#xff1a; &#x1f7e5; 游戏开发经常需要加班&#xff0c;尤其是项目快要…

如何在Shopee平台上选择LED产品进行销售的步骤和策略

在如今的电商市场中&#xff0c;Shopee平台是一个非常受欢迎的在线销售平台。如果您计划在Shopee上销售LED产品&#xff0c;那么了解如何选择合适的产品是至关重要的。在本文中&#xff0c;我们将为您介绍一些在Shopee平台上选择LED产品进行销售的步骤和策略&#xff0c;以帮助…

防御保护-防火墙

1.防火墙的主要职责&#xff1a; 控制和防护--安全策略&#xff08;本质ACL&#xff09;--防火墙可以根据安全策略来抓取流量之后做出相应的动作 2-4层 2.防火墙分类&#xff1a; 吞吐量&#xff1a;防火墙同一时间处理的数据量 3.防火墙的发展历程 包过滤防火墙 应用代理防…

thinkphp5实战之phpstudy v8环境搭建,解决Not Found找不到路径问题

引言 thinkphp以快速、简约的大道至简的思想广受欢迎&#xff0c;适合开发小型项目。本地环境下&#xff0c;phpstudy v8是一款比较优秀的集成环境软件。部署完项目后&#xff0c;访问的时候傻眼&#xff0c;报错。 解决方案 不要慌&#xff0c;这个是伪静态的原因。选择apach…