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

news2024/12/23 10:44:41

文章目录

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

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

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

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

相关文章

用Audio2Face导出Unity面部动画

开始之前说句话&#xff0c;新年前最后一篇文章了 一定别轻易保存任何内容&#xff0c;尤其是程序员不要轻易Ctrl S 在A2F去往Unity的路上&#xff0c;还要经历特殊Blender&#xff0c;自己电脑中已下载好的可能不是很好使。 如果想查看UE相关的可以跳转到下边这两篇链接 1. …

Qt QWidget Loading界面并覆盖在其他控件上面

目录 一、效果图二、Loading三、使用 一、效果图 界面中有一个Label&#xff0c;一个Button 点击Buttion&#xff0c;显示Loading的界面&#xff0c;并覆盖到Label和Button上面 二、Loading loadingwidget.h #ifndef LOADINGWIDGET_H #define LOADINGWIDGET_H#include <…

曲线拟合、多项式拟合、最小二乘法

最近在做自车轨迹预测的工作&#xff0c;遇到 曲线拟合、多项式拟合、最小二乘法这些概念有点不清晰&#xff0c; 做一些概念区别的总结&#xff1a; 曲线拟合用于查找一系列数据点的“最佳拟合”线或曲线。 大多数情况下&#xff0c;曲线拟合将产生一个函数&#xff0c;可用于…

1.26模拟退火

模拟退火是爬山算法的一种&#xff0c;是搜索算法 初始阶段 即只有在每次更新方案时&#xff0c;才会使循环次数增加

Maven安装,学习笔记,详细整理maven的一些配置

Maven 1. 初识Maven 2. Maven概述 Maven模型介绍 Maven仓库介绍 Maven安装与配置 3. IDEA集成Maven 4. 依赖管理 01. Maven课程介绍 1.1 课程安排 学习完前端Web开发技术后&#xff0c;我们即将开始学习后端Web开发技术。做为一名Java开发工程师&#xff0c;后端 Web开发技术…

屈子祠镇黑鱼岭,不可移动文物预防性保护系统守遗珍

一、何止秦俑 秦陵苑囿青铜水禽等文物集中展出 文物保护&#xff0c;尤其是不可移动文物的保护&#xff0c;一直都是文化遗产的重要环节。湖南省汨罗市屈子祠镇双楚村黑鱼岭墓地&#xff0c;作为长江中游地区的重大考古发现&#xff0c;其商朝晚期的历史背景赋予其不可估量的历…

鸿蒙开发实战-运动app开发

主要开发内容 3.1 开发准备 想要实现以下功能的话&#xff0c;需要学习“Tabs”&#xff0c;“TabContent”&#xff0c;“Row”&#xff0c;“Column”&#xff0c;等等相关技术。 主页 静坐页面   除此之外&#xff0c;还需要先准备8张图标的图片以及应用开发所需要的图片…

Python下载安装与环境配置

本文将指导您完成Python的下载、安装以及环境配置过程&#xff0c;确保您在编写和运行Python代码时能够获得最佳体验。我们将提供详细的步骤和代码示例&#xff0c;帮助您顺利完成设置。 一、Python下载与安装 访问Python官网&#xff1a;首先&#xff0c;您需要访问Python的官…

Django模型(六)

一、其它查询 文档:https://docs.djangoproject.com/zh-hans/4.1/ref/models/querysets/#count 1.1、排序 Queryset.order_by(*fields) 默认情况下,QuerySet 返回的结果是按照模型 Meta 中的 ordering 选项给出的排序元组排序的 可以通过使用 order_by 方法在每个 QueryS…

RocketMq5源码搭建

最近公司使用到了RocketMQ,所以打算研究一下RocketMQ 准备自己动手搭建一下RocketMq源码 前提 需要搭建jdk环境&#xff0c;jdk版本需要高于1.8 首先 从github 拉源码 源码地址&#xff1a;rocketMq源码传送门 启动namesrv 启动之前需要配置一下ROCKERMQ_HOME 配置如下&a…

【C++】 C++入门—内联函数

C入门 1 内联函数1.1 定义1.2 查看方式1.3 注意 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下一篇文章见&#xff01;&#xff01;&#xff01; 1 内联函数 1.1 定义 程序在执行一个函数前需要做准备工作&#xff1a;要将实参、局部变量、返回地址以及若干寄存…

pnpm : 无法加载文件 D:\tool\nvm\nvm\node_global\pnpm.ps1,因为在此系统上禁止运行脚本

你们好&#xff0c;我是金金金。 场景 新创建的项目&#xff0c;在vscode编辑器终端输入 pnpm i&#xff0c;显示报错如上 解决 在终端输入get-ExecutionPolicy(查看执行策略/权限) 输出Restricted(受限的) 终端再次输入Set-ExecutionPolicy -Scope CurrentUser命令给用户赋予…

如何在淘宝和Shopee上进行选品:策略和原则

在当今数字化时代&#xff0c;电商平台已经成为卖家们扩展业务和增加销售额的重要渠道。而在淘宝和Shopee这两个知名电商平台上进行选品时&#xff0c;卖家可以遵循一些相似的原则和策略&#xff0c;以确保他们的产品能够吸引目标客户并取得成功。本文将为您介绍一些在淘宝和Sh…

uniapp H5 px转换rpx

uniapp H5 px转换rpx 安装 px2rpx 重启 HBuilderX在要转换的文件 点击右键 点击 开启px2rpx(1px转成2rpx) 开启成功&#xff01;使用 编辑页面后 按下键盘 Ctrl s 保存&#xff01;转化成功&#xff01;当然 你也需要对使用的插件 进行转换&#xff01;否则可能导致样式出现…

基于Python的Selenium详细教程_

一、PyCharm安装配置Selenium 本文使用环境&#xff1a;windows11、Python 3.10.5、PyCharm 2022.1.3、Selenium 4.3.0 需要你懂的技术&#xff1a;Python、HTML、CSS、JavaScript 1.Seleium安装&#xff1a; 在PyCharm终端或window命令窗口输入以下命令 #查看已安装的Pytho…

指针深入了解7

1.qsort的模拟实现&#xff08;冒泡排序的原型制作&#xff09; 1.排序整型 int cmp_int(const void* p1, const void* p2) {return *((int*)p1) - *((int*)p2); } void swap(char* p1, char* p2)//完成交换 {int tmp *p1;*p1 *p2;*p2 tmp;} void bubble_sort(void* base,…

Docker本地部署可编辑开源导航页并发布公网分享好友可访问

文章目录 1. 使用Docker搜索镜像2. 下载镜像3. 查看镜像4. 启动容器5. 浏览器访问6. 远程访问6.1 内网穿透工具安装6.2 创建远程连接公网地址6.3 使用固定二级子域名地址远程访问 今天和大家分享如何使用Docker本地部署一个开源的简约风格网址导航页&#xff0c;支持五种搜索引…

成熟的汽车制造供应商协同平台 要具备哪些功能特性?

汽车行业是一个产业链长且“重”的行业&#xff0c;整个业务流程包括了研发、设计、采购、库存、生产、销售、售后等一系列环节&#xff0c;在每一个环节都涉及到很多信息交换的需求。对内要保证研发、采购、营销等业务环节信息流通高效安全&#xff0c;对外要与上、下游合作伙…

【LeetCode每日一题】1109. 航班预订统计1094. 拼车 (差分数组)

差分数组 差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。 一、基本概念&#xff1a; 差分数组的定义如下&#xff1a; 假设原始数组为arr&#xff0c;差分数组为diff&#xff0c;其中diff[i] arr[i] - arr[i-1]&#xff08;0 < i < n&#xff0…

机器学习 | 掌握逻辑回归在实践中的应用

目录 初识逻辑回归 逻辑回归实操 分类评估方法 初识逻辑回归 逻辑回归&#xff08;LogisticRegression&#xff09;是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单…