Unity 桥接模式(实例详解)

文章目录

      • 示例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)
————————————————

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

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

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

相关文章

kafka(一)快速入门

一、kafka&#xff08;一&#xff09;是什么&#xff1f; kafka是一个分布式、支持分区、多副本&#xff0c;基于zookeeper协调的分布式消息系统&#xff1b; 二、应用场景 日志收集&#xff1a;一个公司可以用Kafka收集各种服务的log&#xff0c;通过kafka推送到各种存储系统…

php基础学习之整型进制

不同进制的整型数据定义 在 PHP中提供了四种整型的定义方式&#xff1a;十进制定义&#xff0c;二进制定义&#xff0c;八进制定义和十六进制。 定义格式如下&#xff1a; 十进制是最基础的&#xff1a;$a 110;二进制需要在值前面加上0b&#xff1a;$a 0B1101110;&#xf…

Java线程池,看这一篇足够

目录一览 Java线程池1. Executors提供6个线程池快捷创建方式2. ThreadPoolExecutor的7大参数3. 自定义线程池 Java线程池 上一篇《Async注解的注意事项》说到Async注解要配合自定义线程池一起使用&#xff0c;这一节说下Java的线程池。 1. Executors提供6个线程池快捷创建方式…

第八篇 交叉编译华为云Iot SDK到Orangepi3B

本篇主要内容&#xff1a; 一、交叉编译华为云Iot SDK依赖1.宿主机安装交叉编译工具链&#xff08;1&#xff09;选择下载交叉编译工具链&#xff08;2&#xff09;解压、添加环境变量、重启2.交叉编译依赖库&#xff08;0&#xff09; 准备工作&#xff08;1&#xff09; 交叉…

MySQL>基础sql语句

阅读目录 1.进入数据库2.数据库操作&#xff08;增删改查用&#xff09;3.表操作(增删改查)4.语句操作(增删改查) 回到顶部 1.进入数据库 打开终端,输入&#xff1a; /usr/local/mysql/bin/mysql -uroot -p回车 输入密码&#xff1a; 回到顶部 2.数据库操作&#xff08;增…

RabbitMQ环境配置

文章目录 安装Erlang安装RabbitMQ 安装Erlang 下载地址&#xff1a;http://erlang.org/download/otp_win64_25.3.2.7.exe 安装RabbitMQ 下载地址&#xff1a;https://www.rabbitmq.com/install-windows.html 进入RabbitMQ安装目录下的sbin目录 输入以下命令启动管理功能 …

Java 设计者模式以及与Spring关系(七) 命令和迭代器模式

简介: 本文是个系列一次会出两个设计者模式作用&#xff0c;如果有关联就三个&#xff0c;除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式&#xff0c;标红是特别重要的设计者模式建议都会&#xff0c;而且熟读于心&#…

Django开发_17_表单类

一、介绍 为了简化前端form表单代码 二、步骤 &#xff08;一&#xff09;创建form.py 创建一个表单类 from django import formsclass RegisterForm(forms.Form):reg_name forms.CharField(max_length10, label用户名)reg_pwd forms.CharField(max_length20, label密码…

python Seq2Seq模型源码实战,超详细Encoder-Decoder模型解析实战;早期机器翻译模型源码demo

1.Seq2Seq&#xff08;Encoder-Decoder&#xff09;模型简介 Seq2Seq&#xff08;Encoder-Decoder&#xff09;模型是一种常用于序列到序列&#xff08;sequence-to-sequence&#xff09;任务的深度学习模型。它由两个主要的组件组成&#xff1a;编码器&#xff08;Encoder&am…

顶顶通呼叫中心中间件机器人压力测试配置(mod_cti基于FreeSWITCH)

介绍 顶顶通呼叫中心中间件机器人压力测试(mod_cit基于FreeSWITCH) 一、配置acl.conf 打开ccadmin-》点击配置文件-》点击acl.conf-》我这里是已经配置好了的&#xff0c;这里的192.168.31.145是我自己的内网IP&#xff0c;你们还需要自行修改 二、配置线路 打开ccadmin-&g…

社区分享|百果园选择DataEase搭档蜜蜂微搭实现企业数据应用一体化

百果园&#xff0c;全称为深圳百果园实业&#xff08;集团&#xff09;股份有限公司&#xff0c;2001年12月成立于深圳&#xff0c;2002年开出中国第一家水果专卖店。截至2022年11月&#xff0c;百果园全国门店数量超过5600家&#xff0c;遍布全国140多个城市&#xff0c;消费会…

实现单链表的增删改查

实现单链表的增删改查的功能&#xff1a;头部插入删除/尾部插入删除&#xff0c;查找&#xff0c;在指定位置之前插入数据&#xff0c;删除pos节点&#xff0c;在指定位置之后插入数据&#xff0c;删除pos之后的节点&#xff0c;销毁链表。 SListNode.h #pragma once #includ…

工程化代码管理高频面试题

1. git常用命令以及工作中都怎么工作 git init 初始化仓库 ​ git status 查看当前各个区域的代码状态。 ​ git log查看commit记录 ​ git reflog查看完整记录 ​ git add 添加工作区代码到暂存区 ​ Git commit 暂存区代码的提交 ​ git reset 代码的版本回退 ​ git stash …

Python中的open与JSON的使用

目录 1 使用 open 函数进行文件操作 2 使用 json 模块进行 JSON 数据处理&#xff1a; 2.1 写入JSON 文件 2.2 读取JSON 文件 在 Python 中&#xff0c;open 函数和 json 模块常用于文件的读写和 JSON 数据的处理。 1 使用 open 函数进行文件操作 open 函数用于打开文件…

docker安装Rabbitmq教程(详细图文)

目录 1.下载Rabbitmq的镜像 2.创建并运行rabbitmq容器 3.启动web客户端 4.访问rabbitmq的微博客户端 5.遇到的问题 问题描述&#xff1a;在rabbitmq的web客户端发现界面会弹出如下提示框Stats in management UI are disabled on this node 解决方法 &#xff08;1&#…

【JAVA语言-第14话】集合框架(一)——Collection集合,迭代器,增强for,泛型

目录 集合框架 1.1 概述 1.2 集合和数组的区别 1.3 Collection集合 1.3.1 概述 1.3.2 常用方法 1.4 迭代器 1.4.1 概述 1.4.2 常用方法 1.4.3 使用步骤 1.5 增强for循环 1.5.1 概述 1.5.2 使用 1.6 泛型 1.6.1 概述 1.6.2 使用泛型的利弊 1.6.2.1 好处 1…

06章【Eclipse与异常处理】

Eclipse开发环境使用入门 Eclipse开发环境使用入门 下载安装配置环境Eclipse入门 异常处理 异常 异常是阻止当前方法或作用域继续执行的问题&#xff0c;在程序中导致程序中断运行的一些指令 try与catch关键字 在程序中出现异常&#xff0c;就必须进行处理&#xff0c;处理格…

vue的模板语法-指令-事件绑定-条件渲染

VSCode代码片段生成 我们在前面练习Vue的过程中&#xff0c;有些代码片段是需要经常写的&#xff0c;我们再VSCode中我们可以生成一个代码片段&#xff0c;方便我们快速生成。 VSCode中的代码片段有固定的格式&#xff0c;所以我们一般会借助于一个在线工具来完成。 具体的步…

Shell脚本 2

一、变量 变量来源于数学&#xff0c;是计算机语言中能储存计算结果或能表示值的抽象概念。 保存将来会变化的数据&#xff0c;即使数据变化&#xff0c;直接调用变量即可&#xff0c;各种 Shell 环境中都使用到了“变量”的概念。Shell 变量用来存放系统和用户需要使用的特定…

基于JavaSwing+百度OCR开发的题库管理系统源码+数据库,能够将图片中的文字提取出来,保存题库中

题库管理系统 介绍 具备上传本地图片及截屏功能&#xff0c;并利用百度OCR技术&#xff0c;能够将图片中的文字提取出来&#xff0c;保存题库中&#xff0c;供以后查找。 技术方面&#xff0c;为制作exe可执行文件&#xff0c;该软件将JavaSwing,MybatisPlus,Spring三者进行集…