Unity 实现原神中的元素反应

一、元素反应

  • 原神中共有七种元素,分别是水、火、冰、岩、风、雷、草。这七种元素能互相作用
  • Demo下载:Download

image-20240424150440824

  • 元素反应表格图示,可能不够精准
/绽放原激化
/蒸发超载融化燃烧结晶扩散烈绽放/
蒸发/感电冻结/碎冰绽放结晶扩散//
超载感电/超导原激化结晶扩散超绽放超激化
融化冻结/碎冰超导//结晶扩散//
燃烧绽放原激化/////蔓激化
结晶结晶结晶结晶/////
扩散扩散扩散扩散/////

二、实现效果

GIF 2024-4-24 星期三 11-17-38

三、代码示例

  • 卡牌类

既然我们是以卡牌打出的方式实现元素反应,首先我们要定义一个卡牌类

using System;
using UnityEngine;public enum CardElement
{Fire,  // 火Water, // 水Thunder, // 雷Ice,    // 冰Grass,  // 草Rock,   // 岩Wind,   // 风//Bloom,   // 绽放//Sharpen   // 激化
}[Serializable]
public class Card
{public string EName;public CardElement Element; // 卡牌的属性public Card(CardElement element, int value){Element = element;EValue = value;}
}
  • 定义接口

因为元素反应涉及10多种,如果要考虑先后顺序的话可能会更多。所以我们要创建一个接口,接口里定义一个事件和反应方法。

using System;public interface IElementalReaction
{event Action OnReactionOccurred;void React(Card card1, Card card2);
}
  • 实现接口

假设火元素卡牌和水元素卡牌打出会触发蒸发反应,那么我们需要创建一个蒸发反应的类,并继承元素反应的接口

using System;
using UnityEngine;//蒸发=水+火
public class EvaporationReaction : IElementalReaction
{public event Action OnReactionOccurred;public void React(Card card1, Card card2){Debug.Log($"{card1.Element} + {card2.Element} = 蒸发");OnReactionOccurred?.Invoke();}
}

如果你有多个反应类,那么就要创建多个元素反应类,这里就不一一展示。都是同样的代码。

  • 元素反应检测类

光有元素元素反应类还不够,我们还需要注册那些元素之间会触发对应的反应,所以这里我定义了一个元素反应类,在不考虑卡牌先后顺序的情况下,我们使用switch语句来返回产生反应的类型。

public static class ElementalReactionFactory
{public static IElementalReaction GetReaction(CardElement element1, CardElement element2){// 使用元组排序元素,确保顺序无关性var key = element1 < element2 ? (element1, element2) : (element2, element1);return key switch{(CardElement.Fire, CardElement.Water) => new EvaporationReaction(),//蒸发(CardElement.Fire, CardElement.Thunder) => new OverloadReaction(),//超载(CardElement.Fire, CardElement.Ice) => new MeltReaction(),//融化(CardElement.Fire, CardElement.Grass) => new BurningReaction(),//燃烧(CardElement.Water, CardElement.Thunder) => new ElectrifyReaction(),//感电(CardElement.Water, CardElement.Ice) => new FrozenReaction(),//冻结(CardElement.Water, CardElement.Grass) => new BloomReaction(),//绽放(CardElement.Thunder, CardElement.Ice) => new SuperconDuctivityReaction(),//超导(CardElement.Thunder, CardElement.Grass) => new SharpenReaction(),//原激化(CardElement.Water, CardElement.Rock) => new RockCrystallizeReaction(),//结晶(CardElement.Thunder, CardElement.Rock) => new RockCrystallizeReaction(),(CardElement.Ice, CardElement.Rock) => new RockCrystallizeReaction(),(CardElement.Fire, CardElement.Rock) => new RockCrystallizeReaction(),(CardElement.Water, CardElement.Wind) => new WindDiffuseReaction(),//扩散(CardElement.Thunder, CardElement.Wind) => new WindDiffuseReaction(),(CardElement.Ice, CardElement.Wind) => new WindDiffuseReaction(),(CardElement.Fire, CardElement.Wind) => new WindDiffuseReaction(),//(CardElement.Fire, CardElement.Bloom) => new FierceBloomReaction(),//烈绽放// (CardElement.Thunder, CardElement.Bloom) => new OverBloomReaction(),//超绽放// (CardElement.Thunder, CardElement.Sharpen) => new HyperActivationReaction(),//超激化//(CardElement.Grass, CardElement.Sharpen) => new RamificationReaction(),//蔓激化_ => null,};}
}

基础设置已经差不多了,接下来我们创建一个Test脚本用来实现卡牌,这里不要照抄我的,可以根据自己的需求来实现。

  • 测试脚本

简单介绍下Test脚本的内容。大概是设置了打出的卡牌和卡牌按键的预制体,然后运行时动态创建每一种卡牌按键,单机卡牌按键会向上打出卡牌,同时卡池内的卡牌是否会发生元素反应。按Esc清空卡池,代码写的不规范,只做功能示意。

using System;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class Test : MonoBehaviour
{private List<Card> playedCards;public Transform beforContent;public GameObject beforPrefab;public Transform afterContent;public GameObject afterPrefab;private IElementalReaction reaction;private void Start(){InitializedCard();}private void Update(){if (Input.GetKeyDown(KeyCode.Escape)){ClearCards();}}// 初始化private void InitializedCard(){playedCards = new List<Card>();foreach (Transform item in beforContent)Destroy(item.gameObject);foreach (Transform item in afterContent)Destroy(item.gameObject);for (int i = 0; i < Enum.GetValues(typeof(CardElement)).Length; i++){Card card = new((CardElement)i, i);CreateCardButton(card);}}// 创建卡牌按钮private void CreateCardButton(Card newCard){GameObject cardObj = Instantiate(beforPrefab, beforContent);Card card = new(newCard.Element, newCard.EValue);cardObj.GetComponentInChildren<TextMeshProUGUI>().text = card.EName;cardObj.GetComponentInChildren<TextMeshProUGUI>().color = card.EColor;cardObj.GetComponent<Button>().onClick.AddListener(() => PlayCard(card));}// 玩家打出一张卡牌时调用此方法private void PlayCard(Card card){CreateCard(card);playedCards.Add(card);CheckForElementalReaction();// 检查是否可以触发元素反应}// 创建打出的卡牌private void CreateCard(Card card){GameObject game = Instantiate(afterPrefab, afterContent);game.name = card.EName;game.transform.GetChild(0).GetComponent<TextMeshProUGUI>().text = card.EName;game.transform.GetChild(0).GetComponent<TextMeshProUGUI>().color = card.EColor;game.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = card.EValue.ToString();}// 检查并触发元素反应private void CheckForElementalReaction(){// 需要至少两张卡来触发反应if (playedCards.Count < 2) return;// 检查最新的两张卡是否会产生元素反应var card1 = playedCards[^2];var card2 = playedCards[^1];reaction = ElementalReactionFactory.GetReaction(card1.Element, card2.Element);// 如果存在反应,则执行if (reaction != null){reaction.OnReactionOccurred += Reaction_OnReactionOccurred;reaction.React(card1, card2);}else{ClearCards();PlayCard(card2);Debug.Log($"{card1.EName}:{card2.EName} 不发生反应");}}// 所有反应通用的特效private void Reaction_OnReactionOccurred(){reaction.OnReactionOccurred -= Reaction_OnReactionOccurred;ClearCards();//if (reaction is BloomReaction)//PlayCard(new Card(CardElement.Bloom, (int)CardElement.Bloom));//else if (reaction is SharpenReaction)//PlayCard(new Card(CardElement.Bloom, (int)CardElement.Bloom));}// 清空卡池private void ClearCards(){playedCards.Clear(); // 清除所有已打出的卡牌foreach (Transform item in afterContent){Destroy(item.gameObject);}}}

以上代码仅代表个人水平,水平有限,这里仅提供想法思路,如有更好的方法欢迎评论区讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql优化面试总结

mysql优化 和 mysql优化之索引 两篇文章有大量的实验性的内容&#xff0c;我暂时没时间理解&#xff0c;把八股部分总结到这篇文章中&#xff0c;方便记忆 我们为什么要对sql进行优化 我们开发项目上线初期&#xff0c;由于业务数据量相对较少&#xff0c;一些SQL的执行效率对…

计算机服务器中了mkp勒索病毒怎么办,mkp勒索病毒解密数据恢复流程

网络技术的不断应用与发展&#xff0c;为企业的生产运营带来了极大便利&#xff0c;越来越多的企业依赖网络开展各项工作业务&#xff0c;网络也大大提升了企业的生产运营效率&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企业的数据安全…

泽攸科技无掩膜光刻机在MEMS压力传感器制造中的应用

在当今的科技快速发展时代&#xff0c;微电子机械系统&#xff08;MEMS&#xff09;技术已成为推动现代传感器技术革新的关键力量。MEMS压力传感器&#xff0c;作为其中的重要分支&#xff0c;广泛应用于生物医学、航空航天、汽车工业等多个领域。随着对传感器性能要求的不断提…

后台架构总结

前言 疫情三年&#xff0c;全国各地的健康码成为了每个人的重要生活组成部分。虽然过去一年&#xff0c;但是回想起来任然历历在目。 今天我就通过当时基于小程序的健康码架构&#xff0c;来给大家讲一下如何基于java&#xff0c;springboot等技术来快速搭建一个后台业务系统…

Docker基本操作 挂载数据卷

在创建一个容器的时候让容器挂载到一个数据卷: 命令:docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx 这里的数据卷如果没有提前创好会自动创建 下边是命令解析 将容器挂载到一个数据卷之后 可以在查看数据卷的目录 在数据卷的目录可以找到容器的内容…

自然语言处理 (NLP) 和文本分析

自然语言处理 (NLP) 和文本分析&#xff1a;NLP 在很多领域都有着广泛的应用&#xff0c;如智能助手、语言翻译、舆情分析等。热门问题包括情感分析、命名实体识别、文本生成等。 让我们一起来详细举例子的分析讲解一下自然语言处理&#xff08;NLP&#xff09;和文本分析的应用…

电子式汽车机油压力传感器的接线方法及特点

电子式机油压力传感器由厚膜压力传感器芯片、信号处理电路、外壳、固定电路板装置和两根引线&#xff08;信号线和报警线&#xff09;组成。信号处理电路由电源电路、传感器补偿电路、调零电路、电压放大电路、电流放大电路、滤波电路和报警电路组成。 厚膜压力传感器是20世纪…

Deckset for Mac激活版:MD文档转幻灯片软件

Deckset for Mac是一款专为Mac用户打造的Markdown文档转幻灯片软件。它凭借简洁直观的界面和强大的功能&#xff0c;成为许多用户的心头好。 Deckset for Mac激活版下载 Deckset支持Markdown语法&#xff0c;让用户在编辑文档时无需分心于复杂的格式设置&#xff0c;只需专注于…

探索的时光 (整数三分)

本题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 题目&#xff1a; 样例&#xff1a; 输入 5 3 2 1 2 3 输出 28 思路&#xff1a; 根据题意&#xff0c;已经给出了运算函数 当我们看到这些函数的时候&#xff0c;联想一下&#xff0c;它们的单调性&#xff0c;以…

Spark集群配置Hive

Spark搭建过程 Spark集群搭建-CSDN博客 1.首先先下载并解压对应的hive压缩包&#xff0c;要选择适配自己系统的&#xff0c;我这个用的是3.1.2 2.配置环境变量 vim ~/.bashrc export HIVE_HOME/usr/local/hive export PATH$PATH:$HIVE_HOME/bin source ~/.bashrc 3.修改hiv…

半导体制造工艺之分类浅述

半导体制造工艺分为逻辑制程(也叫逻辑工艺)和特殊制程(也叫特色工艺)。 1、逻辑工艺概述 随着集成电路行业沿着摩尔定律不断发展,晶体管数量增加的同时,工艺节点不断缩小。先进逻辑工艺是相对的概念,2005年全球先进逻辑工艺的工艺节点在65/55纳米,现在则变为3纳米。中…

达梦(DM) SQL聚集函数及日期运算操作

达梦DM SQL聚集函数及日期运算操作 聚集函数MAX、MIN、SUM、AVG、COUNT使用分析函数 sum (…) over (order by…) 可以生成累计和更改累计和的值计算出现次数最多的值 日期运算加减日、月、年加减时、分、秒日期间隔之时、分、秒日期间隔之日、月、年求两个日期间的工作天数确定…

Microsoft Access Database使用

“小规模数据用Excel&#xff0c;大规模数据用Access。” 当涉及到大规模数据时&#xff0c;使用excel非常的卡顿&#xff0c;使用access就不会出现这个问题。 一、常用操作 1.新建一个数据库 直接右键&#xff0c;新建 access数据库 2.excel内容导入到access中&#xff08;成…

阿里云服务器(Ubuntu22)上的MySQL8更改为大小写不敏感

因为windows上默认的mysql8.0是大小写不敏感的&#xff0c;部署到服务器上之后发现ubuntu默认的是大小写敏感&#xff0c;所以为了不更改代码&#xff0c;需要将mysql数据库设置为大小写不敏感的。 &#xff01;&#xff01;&#xff01;重要一定要做好数据库的备份&#xff0…

零基础HTML教程(31)--HTML5多媒体

文章目录 1. 背景2. audio音频3. video视频4. audio与video常用属性5. 小结 1. 背景 在H5之前&#xff0c;我们要在网页上播放音频、视频&#xff0c;需要借助第三方插件。 这些插件里面最火的就是Flash了&#xff0c;使用它有几个问题&#xff1a; 首先要单独安装Flash&…

机器学习:逻辑回归

概念 首先&#xff0c;逻辑回归属于分类算法&#xff0c;是线性分类器。我们可以认为逻辑回归是在多元线性回归的基础上把结果给映射到0-1的区间内&#xff0c;hθ&#xff08;x&#xff09;越接近1越有可能是正例&#xff0c;反之&#xff0c;越接近0越有可能是负例。那么&am…

前端如何将接口传来的列表数据(数组)直接下载成csv文件

前言&#xff1a;最近遇到一个需求&#xff0c;需要实现一个下载表格数据的操作&#xff0c;一般来说是前端请求后端的下载接口&#xff0c;将文件流下载下来&#xff0c;但是因为这个项目任务时间比较紧&#xff0c;后端没时间做下载接口&#xff0c;所以暂时由前端直接调列表…

JAVA基础---Stream流

Stream流出现背景 背景 在Java8之前&#xff0c;通常用 fori、for each 或者 Iterator 迭代来重排序合并数据&#xff0c;或者通过重新定义 Collections.sorts的 Comparator 方法来实现&#xff0c;这两种方式对 大数量系统来说&#xff0c;效率不理想。 Java8 中添加了一个…

张大哥笔记:服务器有挖矿木马程序,该如何处理?

这篇文章发表于2021年&#xff0c;今天借这个平台再发布一下&#xff0c;希望对大家有所帮助&#xff01; 今天收到一个粉丝求助&#xff0c;说收到了阿里云官方短信通知提示有挖矿程序&#xff0c;要求立即整改&#xff0c;否则会关停服务器&#xff0c;以下是我和他的对话内…

代码学习录打卡Day13

1 滑动窗口最大值 使用单调队列&#xff0c;需要一个队列&#xff0c;这个队列呢&#xff0c;放进去窗口里的元素&#xff0c;然后随着窗口的移动&#xff0c;队列也一进一出&#xff0c;每次移动之后&#xff0c;队列告诉我们里面的最大值是什么。 class MyQueue { public:vo…