Unity 组合模式(实例详解)

news2024/11/16 13:32:05

文章目录

      • 示例1:Unity中的图形界面元素组合
      • 示例2:Unity中的游戏对象层级组合
      • 示例3:Unity中的场景图节点组合
      • 示例4:Unity中的场景管理组合
      • 示例5:Unity中的角色技能树组合

在Unity中,组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构来表现“整体-部分”的层次结构,并且用户可以一致地处理单个对象和组合对象。下面我会提供三个简化的代码实例来说明组合模式在Unity中的应用:

示例1:Unity中的图形界面元素组合

// 抽象组件接口
public abstract class UIComponent
{
    public string Name { get; set; }
    
    public abstract void Render();
    public abstract void Add(UIComponent component);
    public abstract void Remove(UIComponent component);
}

// 叶子节点(具体组件)
public class UIButton : UIComponent
{
    private Texture2D buttonTexture;

    // 构造函数等...

    public override void Render()
    {
        GUI.DrawTexture(new Rect(0, 0, buttonSize.x, buttonSize.y), buttonTexture);
    }

    // 叶子节点不支持添加或删除子组件
    public override void Add(UIComponent component) {}
    public override void Remove(UIComponent component) {}
}

// 组合节点(容器组件)
public class UIMenu : UIComponent
{
    private List<UIComponent> components = new List<UIComponent>();

    public override void Render()
    {
        foreach (var component in components)
            component.Render();
    }

    public override void Add(UIComponent component)
    {
        components.Add(component);
    }

    public override void Remove(UIComponent component)
    {
        components.Remove(component);
    }
}

// 使用示例:
var menu = new UIMenu("MainMenu");
menu.Add(new UIButton("Button1"));
menu.Add(new UIButton("Button2"));

// 渲染整个菜单及其包含的所有按钮
menu.Render();

示例2:Unity中的游戏对象层级组合

// 抽象的游戏对象类
public abstract class GameObjectComposite
{
    public string Name { get; set; }
    protected List<GameObjectComposite> children = new List<GameObjectComposite>();

    public virtual void Update() 
    {
        foreach (var child in children)
            child.Update();
    }

    public void Add(GameObjectComposite obj)
    {
        children.Add(obj);
    }

    public void Remove(GameObjectComposite obj)
    {
        children.Remove(obj);
    }
}

// 具体的游戏对象叶子节点
public class GameObjectLeaf : GameObjectComposite
{
    public override void Update()
    {
        // 实现叶子节点的更新逻辑,如移动、动画播放等
    }
}

// 具体的游戏对象容器节点
public class GameObjectGroup : GameObjectComposite
{
    // 可能会有额外的方法和属性用于管理子对象
    // ...

    public override void Update()
    {
        base.Update();
        // 实现容器节点自身的更新逻辑
    }
}

// 使用示例:
var group = new GameObjectGroup("Enemies");
group.Add(new GameObjectLeaf("Enemy1"));
group.Add(new GameObjectLeaf("Enemy2"));

// 更新所有敌人
group.Update();

示例3:Unity中的场景图节点组合

// 抽象场景图节点接口
public abstract class SceneNode
{
    public string Name { get; set; }
    protected List<SceneNode>childNodes = new List<SceneNode>();

    public abstract void Draw();

    public void AddChild(SceneNode node)
    {
        childNodes.Add(node);
    }

    public void RemoveChild(SceneNode node)
    {
        childNodes.Remove(node);
    }
}

// 叶子节点:一个具体的3D模型
public class ModelNode : SceneNode
{
    public MeshRenderer Renderer { get; private set; }

    public ModelNode(MeshFilter meshFilter, MeshRenderer renderer)
    {
        Renderer = renderer;
        // 初始化其他必要组件...
    }

    public override void Draw()
    {
        Renderer.enabled = true;
        // 调用渲染方法或其他绘制逻辑
    }
}

// 容器节点:一个场景图分支
public class GroupNode : SceneNode
{
    public override void Draw()
    {
        foreach (var node in childNodes)
            node.Draw();
    }
}

// 使用示例:
var groupNode = new GroupNode("BuildingParts");
groupNode.AddChild(new ModelNode(meshFilter1, renderer1));
groupNode.AddChild(new ModelNode(meshFilter2, renderer2));

// 绘制整个建筑群
groupNode.Draw();

以上每个示例都展示了如何使用组合模式来表示一个树形结构,其中抽象基类定义了对组件进行添加、移除以及执行通用操作的方法,而叶子节点和组合节点分别实现这些方法以适应各自的具体功能。

示例4:Unity中的场景管理组合

// 抽象场景类,作为组合模式的组件基类
public abstract class SceneComposite
{
    public string Name { get; set; }
    
    protected List<SceneComposite> childScenes = new List<SceneComposite>();

    public abstract void Load();
    public abstract void Unload();

    public void AddChildScene(SceneComposite scene)
    {
        childScenes.Add(scene);
    }

    public void RemoveChildScene(SceneComposite scene)
    {
        childScenes.Remove(scene);
    }
}

// 叶子节点:具体场景
public class ConcreteScene : SceneComposite
{
    private Scene unityScene;

    public ConcreteScene(Scene scene)
    {
        unityScene = scene;
    }

    public override void Load()
    {
        SceneManager.LoadScene(unityScene, LoadSceneMode.Additive);
    }

    public override void Unload()
    {
        SceneManager.UnloadSceneAsync(unityScene);
    }
}

// 组合节点:复合场景
public class CompositeScene : SceneComposite
{
    public override void Load()
    {
        foreach (var child in childScenes)
            child.Load();
    }

    public override void Unload()
    {
        foreach (var child in childScenes.Reverse())
            child.Unload();
    }
}

// 使用示例:
var mainScene = new ConcreteScene(SceneUtility.GetSceneByPath("Assets/Scenes/Main"));
var subScene1 = new ConcreteScene(SceneUtility.GetSceneByPath("Assets/Scenes/Sub1"));
var subScene2 = new ConcreteScene(SceneUtility.GetSceneByPath("Assets/Scenes/Sub2"));

var compositeScene = new CompositeScene();
compositeScene.AddChildScene(mainScene);
compositeScene.AddChildScene(subScene1);
compositeScene.AddChildScene(subScene2);

// 加载整个复合场景
compositeScene.Load();

// 游戏流程中某个时刻卸载所有场景
compositeScene.Unload();

在以上示例中,我们创建了一个抽象场景类SceneComposite,它拥有加载和卸载的方法以及添加、移除子场景的功能。叶子节点ConcreteScene对应于Unity中的具体场景实例,它们有自己的加载和卸载逻辑。而组合节点CompositeScene则负责统一管理多个子场景,并调用它们的相应方法来实现整体加载或卸载。这种设计允许更灵活地管理和组织游戏中的场景层次结构。

示例5:Unity中的角色技能树组合

// 抽象技能类,作为组合模式的组件基类
public abstract class SkillComposite
{
    public string Name { get; set; }
    protected List<SkillComposite> childSkills = new List<SkillComposite>();

    public abstract void Use(Character character);

    public void AddChildSkill(SkillComposite skill)
    {
        childSkills.Add(skill);
    }

    public void RemoveChildSkill(SkillComposite skill)
    {
        childSkills.Remove(skill);
    }
}

// 叶子节点:具体技能
public class ConcreteSkill : SkillComposite
{
    private float damage;
    private float cooldown;

    public ConcreteSkill(string name, float damage, float cooldown)
    {
        Name = name;
        this.damage = damage;
        this.cooldown = cooldown;
    }

    public override void Use(Character character)
    {
        if (!character.IsOnCooldown(this))
        {
            character.ApplyDamage(damage);
            character.SetCooldown(this, cooldown);
        }
    }
}

// 组合节点:技能组合(例如连招)
public class ComboSkill : SkillComposite
{
    public override void Use(Character character)
    {
        foreach (var child in childSkills)
            child.Use(character);
    }
}

// 使用示例:
var punch = new ConcreteSkill("Punch", 10f, 2f);
var kick = new ConcreteSkill("Kick", 15f, 3f);
var combo = new ComboSkill();
combo.AddChildSkill(punch);
combo.AddChildSkill(kick);

// 角色使用连招技能
combo.Use(playerCharacter);

在这个示例中,我们创建了一个抽象技能类SkillComposite,它定义了技能的基本操作如使用方法以及添加和移除子技能的方法。叶子节点ConcreteSkill代表具体的单个技能,它们有自己的伤害值、冷却时间及使用逻辑。而组合节点ComboSkill则是一个由多个子技能组成的连招,当调用其Use方法时,会依次触发所有子技能的效果。

这种设计模式在游戏开发中非常有用,比如构建角色技能树系统,玩家可以根据自己的策略自由组合不同的技能来形成独特的连招或战术。

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/1410733.html

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

相关文章

哈希的基本概念(开散列和闭散列)(附代码)

哈希 哈希概念哈希冲突哈希函数常见的哈希函数 哈希冲突的解决闭散列开散列 哈希概念 传统的查找函数&#xff0c;搜索的效率取决于比较的次数。而hash算法&#xff1a;在理想情况下&#xff0c;可以不经过任何比较&#xff0c;一次就能得到要搜索的结果。 存储结构&#xff1…

四、MyBatis 动态语句

本章概要 动态语句需求和简介if 和 where 标签set 标签trim 标签(了解)choose/when/otherwise 标签foreach 标签sql 片段 4.1 动态语句需求和简介 经常遇到很多按照很多查询条件进行查询的情况&#xff0c;比如智联招聘的职位搜索等。其中经常出现很多条件不取值的情况&#…

电脑监控系统:企业网络安全解决方案

在当今数字化的世界里&#xff0c;企业的网络安全已经成为一项至关重要的任务。电脑监控系统作为一种有效的解决方案&#xff0c;正在被越来越多的企业所采用。 电脑监控系统是一种集成了多种安全功能的综合性解决方案&#xff0c;旨在为企业提供全面的网络安全防护。该系统能够…

【操作系统】实验七 显示进程列表

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

Java 报错java.Net.UnknownHostException:raw.githubusercontent.com

1.问题 今天在vscode 学习如何使用 plantUML生成图片的时候&#xff0c;发生错误 java.util.concurrent.ExecutionException: java.net.UnknownHostException: raw.githubusercontent.com issue raw.githubusercontent.com java.util.concurrent.ExecutionException: java.n…

手写一个图形验证码

文章目录 需求分析 需求 使用 JS 写一个验证码&#xff0c;并在前端进行校验 分析 新建文件 VueImageVerify.vue <template><div class"img-verify"><canvas ref"verify" :width"state.width" :height"state.height&qu…

“研学测”好帮手,三步带你安装体验TDH社区开发版

星环科技TDH社区开发版&#xff0c;作为一款单机可部署、开箱即用的大数据基础平台产品&#xff0c;大幅降低了用户的资源成本和使用门槛。与此同时&#xff0c;TDH社区开发版兼顾此前TDH社区版&#xff08;分布式&#xff09;组件成熟、简单易用、易运维等特点&#xff0c;可以…

《剑指 Offer》专项突破版 - 面试题 28 : 展平多级双向链表(C++ 实现)

题目连接&#xff1a;LCR 028. 扁平化多级双向链表 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 在一个多级双向链表中&#xff0c;节点除了有两个指针分别指向前后两个节点&#xff0c;还有一个指针指向它的子链表&#xff0c;并且子链表也是一个双向链表&…

深入理解MySQL InnoDB线程模型

当我们谈论数据库性能时&#xff0c;存储引擎的线程模型是一个不可忽视的方面。MySQL的InnoDB存储引擎&#xff0c;作为目前最受欢迎的存储引擎之一&#xff0c;其线程模型的设计对于实现高并发、高性能的数据操作至关重要。在本文中&#xff0c;我们将深入探讨MySQL InnoDB线程…

day31_CSS

今日内容 CSS概述引入方式 (where)选择器(how)属性(how) 1 CSS介绍 层叠样式表&#xff08;cascading style sheet&#xff09; CSS 用来美化HTML页面,可以让页面更好看,还可以布局页面. 好处 美化页面,布局页面使用外部css文件,可以实现样式文件和html文件分离,便于维护使用外…

JS进阶-内置构造函数(二)

小提示&#xff1a;这些内置函数在开发使用的频率非常的频繁&#xff0c;建议认真看一下&#xff0c;并背一下 目录 知识回顾&#xff1a; • Object 三个常用静态方法&#xff08;静态方法就是只有构造函数Object可以调用的&#xff09; Object.keys Object.values Obj…

【2024】下载安装Cisco Packet Tracer 8.2.1

一、注册账号 进入www.cisco.com 点击右上角的Log in 点击注册 之后输入邮箱和其他相关信息&#xff0c;正常注册即可 唯一注意的点&#xff1a;国家或地区 选项中别选China&#xff0c;否则之后登录软件时会有问题 二、下载安装包 进入packet-tracer下载&#xff0c;下…

【Tailwind】各种样式的进度条

基本样式进度条&#xff1a; <div class"mb-5 h-2 rounded-full bg-gray-200"><div class"h-2 rounded-full bg-orange-500" style"width: 50%"></div> </div>带文字的进度条&#xff1a; <div class"relativ…

品优购项目规划

1&#xff0c;网站favicon图标 favicon.ico 一般用于作为缩略的网站标注&#xff0c;它显示在浏览器的地址栏或者标签上 1&#xff0c;制作favicon图标 ①把品优购图标切成png图片 ②把png图片转换为ico图标&#xff0c;这需要借助于第三方转换网站&#xff0c;比如 比特虫…

基于移动边缘计算 (MEC) 的资源调度分配优化研究(提供MATLAB代码)

一、优化模型简介 边缘计算资源调度优化模型是为了解决边缘计算场景下的资源分配和任务调度问题而提出的一种数学模型。该模型旨在通过优化算法来实现资源的有效利用和任务的高效执行&#xff0c;以提高边缘计算系统的性能和用户的服务体验。 在边缘计算资源调度优化模型中&a…

基于vue实现计数器案例

一、需求 页面显示两个按钮&#xff0c;分别为&#xff1a;增加 和 减少&#xff1b;显示加减后的数字&#xff1b;加到10提示不能再加&#xff0c;减到0提示不能再减&#xff1b; 二、代码演示 1、实现步骤 data中定义数据: 比如 num 值为1methods中添加两个方法: 比如add…

普通人如何打造自己人生的护城河?

哈喽&#xff0c;大家好啊&#xff0c;我是雷工。 今天在看《张一鸣管理日志》时看到这么一句话&#xff1a; 今日头条不断吸引更优秀的工程师&#xff0c;不断更新算法&#xff0c;才有了当前今日头条的算法护城河。 头条的算法有多牛&#xff0c;看你周边就知道了。 越来越多…

《WebKit 技术内幕》学习之十一(2):多媒体

2 视频 2.1 HTML5视频 在HTML5规范定义中&#xff0c;Web开发者可以使用“video”元素来播放视频资源。视频中有个重要的问题就是视频编码格式&#xff0c;对此&#xff0c;目前标准中包含了三种编码格式&#xff0c;它们分别是Ogg、MPEG4和WebM。其中Ogg是由Xiph.org组织开…

鼠标移入/点击子组件,获取选中子组件事件

不管是移入&#xff0c;或者是点击事件 都要知道是触发的哪个组件 这里子组件是个通用小标题title 所以&#xff0c;通过标题内容&#xff0c;获取触发的哪个子组件子组件 <template><div mouseover"tMouseover" mouseleave"tMouseLeave" class&…