Unity 策略模式(实例详解)

news2024/11/27 22:37:06

文章目录

      • 简介
      • 示例1:角色攻击行为
      • 示例2:游戏内购折扣策略
      • 示例3:NPC寻路策略
      • 示例4:动画过渡策略
      • 示例5:敌人AI决策策略

简介

在Unity中使用策略模式,我们可以将不同的行为或算法封装成独立的类(策略),然后根据需要在运行时动态选择和切换这些策略。下面我将通过5个简化的代码示例来说明如何在Unity中实现策略模式。

示例1:角色攻击行为

// 定义策略接口(抽象策略类)
public abstract class AttackStrategy
{
    public abstract void ExecuteAttack(Character target);
}

// 具体策略类 - 近战攻击
public class MeleeAttack : AttackStrategy
{
    public override void ExecuteAttack(Character target)
    {
        Debug.Log($"{target.name} 使用近战攻击了 {target.Target.name}");
        // 实现具体的近战攻击逻辑...
    }
}

// 具体策略类 - 远程攻击
public class RangedAttack : AttackStrategy
{
    public override void ExecuteAttack(Character target)
    {
        Debug.Log($"{target.name} 发射了一枚远程攻击向 {target.Target.name}");
        // 实现具体的远程攻击逻辑...
    }
}

// 上下文类 - 角色
public class Character
{
    public AttackStrategy CurrentAttackStrategy { get; set; }

    public void ChangeAttackStrategy(AttackStrategy newStrategy)
    {
        CurrentAttackStrategy = newStrategy;
    }

    public void PerformAttack()
    {
        if (CurrentAttackStrategy != null)
        {
            CurrentAttackStrategy.ExecuteAttack(this);
        }
    }
}

// 使用示例
Character player = new Character();
player.CurrentAttackStrategy = new MeleeAttack(); // 设置初始攻击策略为近战
player.PerformAttack();

// 游戏进程中动态切换策略
player.ChangeAttackStrategy(new RangedAttack());
player.PerformAttack();

示例2:游戏内购折扣策略

// 抽象折扣策略
public abstract class DiscountStrategy
{
    public abstract float CalculateDiscount(float originalPrice);
}

// 具体折扣策略 - 普通价格
public class NormalDiscount : DiscountStrategy
{
    public override float CalculateDiscount(float originalPrice)
    {
        return originalPrice; // 不打折
    }
}

// 具体折扣策略 - 五折优惠
public class HalfOffDiscount : DiscountStrategy
{
    public override float CalculateDiscount(float originalPrice)
    {
        return originalPrice * 0.5f;
    }
}

// 上下文类 - 购物车
public class ShoppingCart
{
    public DiscountStrategy CurrentDiscountStrategy { get; set; }

    public float GetFinalPrice(float itemPrice)
    {
        return itemPrice * CurrentDiscountStrategy.CalculateDiscount(itemPrice);
    }

    public void SetDiscountStrategy(DiscountStrategy newDiscount)
    {
        CurrentDiscountStrategy = newDiscount;
    }
}

// 使用示例
ShoppingCart cart = new ShoppingCart();
cart.CurrentDiscountStrategy = new NormalDiscount();
float finalPrice = cart.GetFinalPrice(100); // 原价购买

cart.SetDiscountStrategy(new HalfOffDiscount());
finalPrice = cart.GetFinalPrice(100); // 半价购买

示例3:NPC寻路策略

// 抽象寻路策略
public abstract class PathfindingStrategy
{
    public abstract List<Vector3> FindPath(Vector3 start, Vector3 end);
}

// 具体寻路策略 - A*寻路
public class AStarPathfinding : PathfindingStrategy
{
    public override List<Vector3> FindPath(Vector3 start, Vector3 end)
    {
        // 实现A*算法寻找路径
        // ...
        return pathList;
    }
}

// 具体寻路策略 - Dijkstra寻路
public class DijkstraPathfinding : PathfindingStrategy
{
    public override List<Vector3> FindPath(Vector3 start, Vector3 end)
    {
        // 实现Dijkstra算法寻找路径
        // ...
        return pathList;
    }
}

// 上下文类 - NPC实体
public class NPC
{
    public PathfindingStrategy CurrentPathfindingStrategy { get; set; }

    public void MoveTo(Vector3 destination)
    {
        var path = CurrentPathfindingStrategy.FindPath(transform.position, destination);
        // 根据路径移动NPC
        // ...
    }

    public void SetPathfindingStrategy(PathfindingStrategy newPathfinding)
    {
        CurrentPathfindingStrategy = newPathfinding;
    }
}

// 使用示例
NPC npc = new NPC();
npc.CurrentPathfindingStrategy = new AStarPathfinding();
npc.MoveTo(targetPosition);

// 更改寻路策略
npc.SetPathfindingStrategy(new DijkstraPathfinding());
npc.MoveTo(anotherTargetPosition);

示例4:动画过渡策略

// 抽象动画过渡策略
public abstract class TransitionStrategy
{
    public abstract void ApplyTransition(Animator animator, string targetState);
}

// 具体动画过渡策略 - 直接切换
public class DirectTransition : TransitionStrategy
{
    public override void ApplyTransition(Animator animator, string targetState)
    {
        animator.CrossFade(targetState, 0f);
    }
}

// 具体动画过渡策略 - 平滑过渡
public class SmoothTransition : TransitionStrategy
{
    public override void ApplyTransition(Animator animator, string targetState)
    {
        animator.CrossFade(targetState, 0.5f);
    }
}

// 上下文类 - 动画控制器
public class AnimationController
{
    public TransitionStrategy CurrentTransitionStrategy { get; set; }

    public void ChangeAnimation(string stateName)
    {
        CurrentTransitionStrategy.ApplyTransition(animator, stateName);
    }

    public void SetTransitionStrategy(TransitionStrategy newStrategy)
    {
        CurrentTransitionStrategy = newStrategy;
    }
}

// 使用示例
AnimationController animCtrl = new AnimationController();
animCtrl.CurrentTransitionStrategy = new DirectTransition();
animCtrl.ChangeAnimation("Run");

// 更改过渡策略
animCtrl.SetTransitionStrategy(new SmoothTransition());
animCtrl.ChangeAnimation("Idle");

示例5:敌人AI决策策略

// 抽象AI决策策略
public abstract class AIActionStrategy
{
    public abstract void DecideAction(Enemy enemy);
}

// 具体AI决策策略 - 随机行动
public class RandomAI : AIActionStrategy
{
    public override void DecideAction(Enemy enemy)
    {
        int randomChoice = Random.Range(0, 3);
        switch (randomChoice)
        {
            case 0:
                enemy.Attack();
                break;
            case 1:
                enemy.Defend();
                break;
            case 2:
                enemy.Flee();
                break;
        }
    }
}

// 具体AI决策策略 - 精确计算行动
public class CalculatedAI : AIActionStrategy
{
    public override void DecideAction(Enemy enemy)
    {
        // 根据战场情况、玩家状态等精确计算并执行动作
        // ...
    }
}

// 上下文类 - 敌人实体
public class Enemy
{
    public AIActionStrategy CurrentAIAction { get; set; }

    public void UpdateAI()
    {
        CurrentAIAction.DecideAction(this);
    }

    public void SetAIAction(AIActionStrategy newAI)
    {
        CurrentAIAction = newAI;
    }
}

// 使用示例
Enemy enemy = new Enemy();
enemy.CurrentAIAction = new RandomAI();
enemy.UpdateAI(); // 随机执行动作

// 更改AI策略
enemy.SetAIAction(new CalculatedAI());
enemy.UpdateAI(); // 根据计算结果执行动作

以上每个示例都展示了策略模式的基本应用,在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/1425684.html

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

相关文章

大数据开发之离线数仓项目(3数仓数据同步策略)(可面试使用)

第 1 章&#xff1a;实时数仓同步数据 实时数仓由flink源源不断从kafka当中读数据计算&#xff0c;所以不需要手动同步数据到实时数仓。 第 2 章&#xff1a;离线数仓同步数据 2.1 用户行为数据同步 2.1.1 数据通道 用户行为数据由flume从kafka直接同步到hdfs&#xff0c;…

如何从零开始开发一个PS5浏览器 | How to develop a PS5 browser

环境&#xff1a;Windows PS5一台 问题&#xff1a;PS5折腾需要使用PKG浏览器访问特定网址&#xff0c;如何自定义网址呢&#xff1f; 解决办法&#xff1a;使用开发套件PS Multi Tools开发一个空应用&#xff0c;利于deeplinkUri 参数访问网页 背景&#xff1a;PS5折腾后&…

应用keras建立ANN模型.

介绍&#xff1a; Keras是一个开源的神经网络库&#xff0c;它基于Python语言&#xff0c;并能够在多个深度学习框架上运行&#xff0c;包括TensorFlow、Theano和CNTK。Keras提供了一种简洁而高层次的API&#xff0c;使得用户能够快速构建、训练和部署神经网络模型。 Keras的设…

R-kknn包-类别插值可视化绘制

前面的推文我们介绍了使用scikit-learn结合分类散点数据&#xff0c;构建机器学习分类模型并将模型结果可视化展示&#xff0c;具体链接如下&#xff1a; 机器学习和可视化还能一起这样用&#xff1f;Python教你全搞定。今天这篇推文&#xff0c;我们就使用R语言的kknn包进行类…

解锁视频号带货小程序的成功密码:策略、技巧与实践

随着社交电商的兴起&#xff0c;越来越多的人开始在视频号上直播带货。而上线带货小程序&#xff0c;不仅可以方便观众购买商品&#xff0c;还可以提高商品的转化率。那么&#xff0c;如何上线带货小程序呢&#xff1f; 首先&#xff0c;我们需要选择一个可靠的第三方平台来搭建…

消息中间件之RocketMQ源码分析(四)

消费者的Rebalance机制 客户端是通过Rebalance服务做到高可靠的。当发生Broker掉线、消费者实例掉线、 Topic扩容等各种突发情况时&#xff0c;消费者组中的消费者实例是怎么重平衡的&#xff0c;以支持全部队列的正常消费的? Rebalance服务的类图 RebalanceImpl的核心属性 …

面试了字节大模型算法岗(实习),快被问哭了。。。。

最近技术群组织了一次算法面试讨论会&#xff0c;今天分享的是一位小伙子的痛苦面试经历&#xff0c;如果你想加入我们的讨论群&#xff0c;见文末。 本次分享的内容如下&#xff1a; 应聘岗位&#xff1a;字节大模型算法实习生 面试轮数&#xff1a;第一轮 整体面试感觉&…

银行数据仓库体系实践(17)--数据应用之营销分析

营销是每个银行业务部门重要的工作任务&#xff0c;银行产品市场竞争激烈&#xff0c;没有好的营销体系是不可能有立足之地&#xff0c;特别是随着互联网金融发展,金融脱媒”已越来越普遍&#xff0c;数字化营销方兴未艾&#xff0c;银行的营销体系近些年也不断发展&#xff0c…

基于SpringBoot开发的JavaWeb智能家电商城[附源码]

基于SpringBoot开发的JavaWeb智能家电商城[附源码] &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统 &a…

Linux系统中的日志管理工具和技术

Linux系统中的日志管理工具和技术 在Linux系统中&#xff0c;日志管理对于系统管理员和开发人员来说至关重要。它能够帮助用户监视系统运行时的行为、故障和安全问题。以下是一些常用的日志管理工具和技术&#xff0c;包括使用logrotate和ELK堆栈。 1. 日志管理工具 - **rsys…

Flutter canvas 画一条会动的波浪线 进度条

之前用 Flutter Canvas 画过一个三角三角形&#xff0c;html 的 Canvas 也画过一次类似的&#xff0c; 今天用 Flutter Canvas 试了下 感觉差不多&#xff1a; html 版本 大致效果如下&#xff1a; 思路和 html 实现的类似&#xff1a; 也就是找出点的位置&#xff0c;使用二阶…

PySimpleGUI 综合应用|英语文本朗读以及转换为语音Mp3

PySimpleGUI 综合应用 目录 PySimpleGUI 综合应用 应用界面 完整代码 所需模块 PySimpleGUI pyttsx3 pyaudio rapidfuzz 字典格式 应用界面 完整代码 英语朗读器.pyw import PySimpleGUI as sg import pyttsx3,pyaudio,pyperclip import os,re,datetime,wave,threa…

如何分辨坏信息?

每当有社会热点&#xff0c;大家也许都会遇到一个困扰&#xff1a; 铺天盖地的信息&#xff0c;实在是太多了。究竟哪一些值得信任&#xff0c;哪些不值得信任&#xff1f;哪些可以接受&#xff0c;哪些最好保持怀疑&#xff1f; 我想用这篇文章&#xff0c;彻底把这个问题讲清…

python数据类型-元组

1 元组(tuple)的定义 元组是集合类型&#xff0c;和列表类似&#xff0c;元组中的元组类型可以不同&#xff0c;元素间用逗号隔开&#xff0c;和列表的不同之处在于&#xff1a; 1 元组的元组不可改变&#xff0c;也被称为只读列表 2 且元组用括号()表示&#xff0c;列表用方括…

HTML+JavaScript-06

节点操作 目前对于节点操作还是有些困惑&#xff0c;只是了解简单的案例 具体操作可以看菜鸟教程&#xff1a;https://www.runoob.com/js/js-htmldom-elements.html 案例-1 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8…

前端构建变更:从 webpack 换 vite

现状 这里以一个 op &#xff08;内部运营管理用&#xff09;项目为例&#xff0c;从 webpack 构建改为 vite 构建&#xff0c;提高本地开发效率&#xff0c;顺便也加深对 webpack 、 vite 的了解。 vite 是前端构建工具&#xff0c;使用 一系列预配置进行rollup 打包&#x…

获客助手助力提升企业微信添加客户的效率和精准度

数字化营销时代&#xff0c;企业微信成为企业与客户沟通的重要渠道&#xff0c;但如何快速、精准地添加潜在客户&#xff0c;一直是企业面临的一大挑战。获客助手作为一款企业微信服务商数灵通外链工具提供的营销工具&#xff0c;为企业提供了一种高效、精准的解决方案。 获客助…

【C++】 C++入门 — auto关键字

C入门 auto 关键字1 介绍2 使用细则3 注意事项 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下一篇文章见&#xff01;&#xff01;&#xff01; auto 关键字 1 介绍 编程时常常需要把表达式的值赋给变量&#xff0c;这就要求在声明变量时清楚地知道表达式的类…

服务网格(Service Mesh)流行工具

在这篇博客中&#xff0c;我们将介绍微服务的最佳服务网格工具列表&#xff0c;这些工具提供安全性、金丝雀部署、遥测、负载均衡等。 用于部署和操作微服务的服务网格工具的数量不断增加。在这篇文章中&#xff0c;我们将探讨您应该用来构建自己的服务网格架构的顶级服务网格…

(已解决)spingboot项目如何做QQ邮箱注册功能,如何在邮箱注册中进行随机数添加作为动态验证码,并满足分层解耦

前面我们已经完成了发送静态验证码&#xff0c;现在用随机数作为动态验证码。 文章地址&#xff1a;spingboot 后端发送QQ邮箱验证码 使用注解Component进行分层解耦加入ioc容器&#xff0c;方便调用。 package com.example.tianyidemo.utils; import org.springframework.st…