Unity 访问者模式(实例详解)

文章目录

      • 实例1:简单的形状与统计访客
      • 实例2:游戏对象组件访问者
      • 实例4:Unity场景对象遍历与清理访客
      • 实例5:角色行为树访问者

访问者模式(Visitor Pattern)在Unity中主要用于封装对一个对象结构中各个元素的操作,使得可以在不改变这些元素类的前提下增加新的操作。下面我将提供五个简化版的代码实例来说明如何在C#中为Unity项目实现访问者模式:

实例1:简单的形状与统计访客

// 抽象元素接口
public interface IShape
{
    void Accept(IVisitor visitor);
}

// 具体元素类
public class Circle : IShape
{
    public float Radius { get; set; }

    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class Square : IShape
{
    public float SideLength { get; set; }

    public void Accept(IVisitor visitor)
    {
        visitor.Visit(this);
    }
}

// 访问者接口
public interface IVisitor
{
    void Visit(Circle circle);
    void Visit(Square square);
}

// 具体访问者:面积计算器
public class AreaCalculator : IVisitor
{
    public float TotalArea { get; private set; }

    public void Visit(Circle circle)
    {
        TotalArea += Mathf.PI * circle.Radius * circle.Radius;
    }

    public void Visit(Square square)
    {
        TotalArea += square.SideLength * square.SideLength;
    }
}

// 使用示例
public class ShapeExample : MonoBehaviour
{
    public List<IShape> shapes;

    void Start()
    {
        IVisitor areaVisitor = new AreaCalculator();
        foreach (var shape in shapes)
        {
            shape.Accept(areaVisitor);
        }
        Debug.Log("Total area: " + areaVisitor.TotalArea);
    }
}

实例2:游戏对象组件访问者

// 抽象游戏对象组件接口
public interface IGameObjectComponent
{
    void Accept(IGameObjectVisitor visitor);
}

// 具体游戏对象组件
public class TransformComponent : IGameObjectComponent
{
    public Vector3 Position { get; set; }

    public void Accept(IGameObjectVisitor visitor)
    {
        visitor.VisitTransform(this);
    }
}

public class RenderComponent : IGameObjectComponent
{
    public Material Material { get; set; }

    public void Accept(IGameObjectVisitor visitor)
    {
        visitor.VisitRender(this);
    }
}

// 访问者接口
public interface IGameObjectVisitor
{
    void VisitTransform(TransformComponent component);
    void VisitRender(RenderComponent component);
}

// 具体访问者:序列化器
public class GameObjectSerializer : IGameObjectVisitor
{
    public void VisitTransform(TransformComponent component)
    {
        // 序列化Transform组件数据
    }

    public void VisitRender(RenderComponent component)
    {
        // 序列化渲染组件数据
    }
}

// 使用示例
public class GameObjectManager : MonoBehaviour
{
    public GameObject targetObject;

    void SerializeComponents()
    {
        IGameObjectVisitor serializer = new GameObjectSerializer();
        foreach (var component in targetObject.GetComponents<IGameObjectComponent>())
        {
            component.Accept(serializer);
        }
    }
}

// ... 更多具体访问者的实现 ...

实例4:Unity场景对象遍历与清理访客

// 抽象游戏对象接口,扩展自MonoBehaviour以适应Unity环境
public interface ISceneGameObject : MonoBehaviour
{
    void Accept(ISceneVisitor visitor);
}

// 具体的游戏对象类
public class GameObjectWithComponents : MonoBehaviour, ISceneGameObject
{
    public Transform MyTransform;
    public MeshRenderer Renderer;

    // 接受访问者
    public void Accept(ISceneVisitor visitor)
    {
        visitor.Visit(this);
    }
}

// 访问者接口
public interface ISceneVisitor
{
    void Visit(GameObjectWithComponents gameObject);
}

// 清理访客:销毁无用的MeshRenderer
public class UnusedRendererCleaner : ISceneVisitor
{
    void Visit(GameObjectWithComponents gameObject)
    {
        if (gameObject.Renderer == null || !gameObject.Renderer.enabled)
        {
            GameObject.Destroy(gameObject.Renderer);
        }
    }
}

// 使用示例
public class SceneManager : MonoBehaviour
{
    public List<ISceneGameObject> sceneObjects;

    void Start()
    {
        ISceneVisitor cleaner = new UnusedRendererCleaner();
        foreach (var obj in sceneObjects)
        {
            obj.Accept(cleaner);
        }
    }
}

// ... 更多具体访问者的实现 ...

实例5:角色行为树访问者

// 抽象行为节点接口
public interface IBehaviorTreeNode
{
    void Accept(BehaviorTreeVisitor visitor);
    bool Evaluate();
}

// 具体的行为节点
public class MoveToTargetNode : IBehaviorTreeNode
{
    public Transform Target;
    public float DistanceThreshold;

    public void Accept(BehaviorTreeVisitor visitor) => visitor.VisitMoveToTarget(this);
    public bool Evaluate() => Vector3.Distance(transform.position, Target.position) > DistanceThreshold;
}

public class AttackEnemyNode : IBehaviorTreeNode
{
    public Transform Enemy;

    public void Accept(BehaviorTreeVisitor visitor) => visitor.VisitAttackEnemy(this);
    public bool Evaluate() => Enemy != null && Enemy.gameObject.activeSelf;
    
    // 其他评估条件...
}

// 访问者接口
public interface BehaviorTreeVisitor
{
    void VisitMoveToTarget(MoveToTargetNode node);
    void VisitAttackEnemy(AttackEnemyNode node);
    // 更多行为节点类型...
}

// 具体访问者:AI逻辑执行器
public class AIExecutor : BehaviorTreeVisitor
{
    void VisitMoveToTarget(MoveToTargetNode node)
    {
        // 执行移动到目标的行为逻辑
    }

    void VisitAttackEnemy(AttackEnemyNode node)
    {
        // 执行攻击敌人的行为逻辑
    }
    
    // 其他行为节点的处理方法...
}

// 使用示例
public class CharacterAI : MonoBehaviour
{
    public IBehaviorTreeNode rootNode;

    void Update()
    {
        var executor = new AIExecutor();
        rootNode.Accept(executor);
        if (rootNode.Evaluate())
        {
            // 根据行为树执行相应动作
        }
    }
}

以上实例展示了访问者模式在不同Unity应用场景下的灵活运用。

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

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

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

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

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

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

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

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

相关文章

【开发实践】python使用 moviepy实现mp4转gif(含可视化界面)

一、分析介绍 MoviePy是一个用于视频编辑和处理的Python库。它提供了一种简单而直观的方式来创建、编辑和合成视频&#xff0c;同时也支持添加音频和图像。 以下是MoviePy的一些主要功能和用法示例&#xff1a; 创建视频剪辑&#xff1a; from moviepy.editor import VideoFi…

批量将本地图片转为webp

-I 后是当前图片的路径目录 -O 后是 输出的webp目录 npx webp-batch-convert -I images -O images_webp npx webp-batch-convert -I icon -O icon_webp 在 assets 目录内 执行上面的命令 直接转换

怎么对现在的现货黄金行情进行分析?

进行现货黄金行情分析&#xff0c;很多人一上来就讨论使用什么技术指标&#xff0c;什么基本面的工具等等&#xff0c;其实这些东西并不是首要的。要做现货黄金行情分析&#xff0c;首先我们要掌握一些核心的问题&#xff0c;下面我们就来讨论一下这些核心问题是什么&#xff1…

JNPF低代码平台存在的价值

低代码开发平台是近年来兴起的一种软件开发体例&#xff0c;它为非技术背景的人员提供了编写应用程序的能力&#xff0c;而无需编写任何代码&#xff0c;这种开发体例正在逐渐改变传统的软件开发模式&#xff0c;为企业带来了更高的效率和矫捷性&#xff0c;在低代码开发平台中…

CentOS部署Docker Registry镜像仓库并结合内网穿透实现远程访问

文章目录 1. 部署Docker Registry2. 本地测试推送镜像3. Linux 安装cpolar4. 配置Docker Registry公网访问地址5. 公网远程推送Docker Registry6. 固定Docker Registry公网地址 Docker Registry 本地镜像仓库,简单几步结合cpolar内网穿透工具实现远程pull or push (拉取和推送)…

RT-DETR算法优化改进:上采样算子 | 超轻量高效动态上采样DySample,效果秒杀CAFFE,助力小目标检测

💡💡💡本文独家改进:一种超轻量高效动态上采样DySample, 具有更少的参数、FLOPs,效果秒杀CAFFE和YOLOv8网络中的nn.Upsample 💡💡💡在多个数据集下验证能够涨点,尤其在小目标检测领域涨点显著。 RT-DETR魔术师专栏介绍: https://blog.csdn.net/m0_63774211/…

【目标跟踪】3D点云跟踪

文章目录 一、前言二、代码目录三、代码解读3.1、文件描述3.2、代码框架 四、关联矩阵计算4.1、ComputeLocationDistance4.2、ComputeDirectionDistance4.3、ComputeBboxSizeDistance4.4、ComputePointNumDistance4.5、ComputePointNumDistance4.6、result_distance 五、结果 一…

系统分析师-21年-下午答案

系统分析师-21年-下午答案 更多软考知识请访问 https://ruankao.blog.csdn.net/ 试题一必答&#xff0c;二、三、四、五题中任选两题作答 试题一 (25分) 说明 某软件企业拟开发一套基于移动互联网的在线运动器材销售系统&#xff0c;项目组决定采用FAST 开发方法进行系统分…

SumGNN: 多类型药物相互作用预测 - 通过高效知识图谱概括

SumGNN: 多类型药物相互作用预测 - 通过高效知识图谱概括 在医学领域&#xff0c;准确预测药物之间的相互作用对于药物研发和治疗方案设计至关重要。为了解决这一挑战&#xff0c;我们提出了一种名为"SumGNN"的新方法&#xff0c;旨在通过高效的知识图谱概括实现多类…

PostgreSql和Oracle的事务机制区别以及对程序的影响

前言 几年前IT信息产业的一些核心技术包括架构、产品以及生态都是国外制定&#xff0c;然而自从“遥遥领先”公司被制裁后&#xff0c;国家开始大力支持信息产业“新基建”&#xff0c;自2020年开始市场上涌现出了大量的国产化软件&#xff0c;就国产化数据库而言我所在的公司…

一种轻量分表方案-MyBatis拦截器分表实践|京东零售技术实践

背景 部门内有一些亿级别核心业务表增速非常快&#xff0c;增量日均100W&#xff0c;但线上业务只依赖近一周的数据。随着数据量的迅速增长&#xff0c;慢SQL频发&#xff0c;数据库性能下降&#xff0c;系统稳定性受到严重影响。本篇文章&#xff0c;将分享如何使用MyBatis拦…

企业微信获客助手怎么实现抖音数据回传?

在数字化时代&#xff0c;企业微信获客助手和数灵通外链已经成为企业获取潜在客户的得力助手。通过在微信站外的各个渠道上捕获潜在客户&#xff0c;企业能够更好地满足客户需求并提高业务增长。而抖音作为当前最热门的短视频平台&#xff0c;也成为了企业营销的重要战场。 企业…

OTG -- ULPI接口芯片USB3318讲解(二)

目录 前沿 1 初识USB PHY芯片 2 ULPI接口与USB PHY芯片 3 USB3318简介 3.1 USB3318引脚定义 3.2 USB3318与ULPI接口时序 3.3 STM32F407 OTGHS如何驱动USB3318 3.4 USB3318原理图设计 4 总结 前沿 前面对STM32F407 OTG模块进行了简单的讲解&#xff0c;如果使用OTG_FS模…

期末成绩群发给家长

每当学期结束&#xff0c;老师们的邮箱和手机便会被成绩报告单填满。那么&#xff0c;如何高效地将成绩群发给家长呢&#xff1f; 一、邮件还是短信&#xff1f; 首先&#xff0c;选择一个合适的通讯方式是关键。邮件正式且便于附件&#xff0c;但短信更快捷。考虑到大多数家长…

项目经理如何成功接手做到一半的项目:从0到1的高效指南

最近看到很多帖子&#xff0c;吐槽自己一年到头来一直频繁被拉去救火、去接做到一半的项目。这种情况应该是很多项目经理都会遇见的&#xff0c;大多数情况是因为前任项目经理由于各种原因&#xff0c;如调岗、离职而留下的项目&#xff0c;但往往到大家手上的时候&#xff0c;…

Qt实现窗口吸附屏幕边缘 自动收缩

先看效果&#xff1a; N年前的QQ就可以吸附到屏幕边缘&#xff0c;聊天时候非常方便&#xff0c;不用点击状态栏图标即可呼出QQ界面 自己尝试做了一个糙版的屏幕吸附效果。 关键代码&#xff1a; void Widget::mouseMoveEvent(QMouseEvent *e) {int dx e->globalX() - l…

Java Chassis 3技术解密:与Spring Cloud的互操作

作者&#xff1a;刘宝 原文链接&#xff1a;Java Chassis 3技术解密&#xff1a;与Spring Cloud的互操作-云社区-华为云 Java Chassis 3一个很重要的设计原则&#xff1a;利用架构的韧性设计来解决兼容性问题。 比如通过引入微服务网关&#xff0c;来解决不同语言、不同框架、…

C#,洛布数(Lobb Number)的计算方法与源代码

1 洛布数&#xff08;Lobb Number&#xff09; 在组合数学中&#xff0c;洛布数&#xff08;Lobb Number&#xff09;L(m&#xff0c;n)计算nm开括号的排列方式&#xff0c;以形成一个有效的平衡括号序列的开始。 Lobb数由两个非负整数m和n参数化&#xff0c;其中n>m>0。…

计算机网络实验一

目录 实验一 使用PacketTracer组建简单局域网 1、实验目的 2、实验设备 &#xff08;1&#xff09;内容一&#xff08;组建简单局域网&#xff09;&#xff1a; &#xff08;2&#xff09;内容二&#xff08;使用交叉线直连两台机器&#xff09;&#xff1a; &#xff08…

基于SpringBoot+Vue学科竞赛管理系统

文章目录 基于SpringBootVue学科竞赛管理系统1系统概述1.3系统设计思想 2相关技术2.1 MYSQL数据库2.2 B/S结构2.3 Spring Boot框架简介2.4 Vue简介 3系统分析3.1可行性分析3.1.1技术可行性3.1.2经济可行性3.1.3操作可行性 3.2系统性能分析3.2.1 系统安全性3.2.2 数据完整性 3.4…