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.mzph.cn/pingmian/3614.shtml

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

相关文章

Windows主机入侵检测与防御内核技术深入解析

第2章 模块防御的设计思想 2.1 执行与模块执行 本章内容为介绍模块执行防御。在此我将先介绍“执行”分类&#xff0c;以及“模块执行”在“执行”中的位置和重要性。 2.1.1 初次执行 恶意代码&#xff08;或者行为&#xff09;要在被攻击的机器上执行起来&#xff0c;看起…

Ubuntu 自己写的程序如何创建快捷方式

在Ubuntu中创建程序的快捷方式通常是通过将一个指向程序可执行文件的.desktop文件放入/usr/share/applications/或用户的~/.local/share/applications/目录来实现的。以下是创建快捷方式的基本步骤和示例&#xff1a; 在application里创建快捷方式 创建一个新的.desktop文件。…

【Linux】详解信号产生的方式

一、kill命令 在命令行中通过kill -数字 pid指令可以给指定进程发送指定信号。这里说明一下几个常见的信号&#xff1a; SIGINT&#xff08;2号信号&#xff09;&#xff1a;中断信号&#xff0c;通常由用户按下CtrlC产生&#xff0c;用于通知进程终止。SIGQUIT&#xff08;3号…

PG修改端口号与error: could not connect to server: could not connect to server 问题解决

刚开始学习PG修改端口号之后数据库端口号没变。 修改端口号&#xff1a;/usr/local/pgsql/data中的postgresql.conf中 修改后并不能直接生效需要重启PG&#xff1a; /usr/local/pgsql/bin/pg_ctl -D /usr/local/pgsql/data -l /usr/local/pgsql/data/logfile restart重启后新…

c++在visual studio上的默认配置

右键 新建项 右键源文件 属性

企业OA管理|基于SprinBoot+vue的企业OA管理系统(源码+数据库+文档)

企业OA管理目录 基于SprinBootvue的企业OA管理系统 一、前言 二、系统设计 三、系统功能设计 1 管理员模块的实现 1.1 用户信息管理 1.2 公告信息管理 1.3 客户关系管理 1.4 通讯录管理 2 用户模块的实现 2.1 客户关系添加 2.2 通讯录添加 2.3 日程安排添加 四、…

3.Docker常用镜像命令和容器命令详解

文章目录 1、Docker镜像命令1.1 获取镜像1.2 查看镜像1.2.1、images命令列出镜像1.2.2、tag命令添加镜像标签1.2.3、inspect命令查看详细信息1.2.4、history命令查看镜像历史 1.3 搜索镜像1.4 删除和清理镜像1.4.1、使用标签删除镜像1.4.2、清理镜像 1.5 创建镜像1.5.1、基于已…

Nginx 从入门到实践(1)

Nginx 从入门到实践 Nginx Nginx 从入门到实践Nginx介绍Nginx常用功能1、Http代理&#xff0c;反向代理2、负载均衡3、动静分离4、Nginx配置文件结构 简述Nginx和Apache的差异编译安装nginx服务在线安装nginxnginx 状态统计nginx 访问控制(用户校验、客户端授权)用户校验基于客…

【vue,unapi】UniApp引入全局js实现全局方法,全局变量

创建一个全局文件utils.js export const baseUrl "https://www.baidu.com/"export const fn () > {console.log("demo"); } export const obj {baseUrl : "https://www.baidu.com/",demo(){console.log("demo2");} }第一种&#…

4月25日 C++day4

#include <iostream> using namespace std;class Person {const string name;int age;char sex; public:Person():name("lisi"){cout << "Person无参构造" << endl;}Person(string name,int age,char sex):name(name),age(age),sex(sex)…

最新windows版本erlang26.0和rabbitmq3.13下载

Erlang下载 官网下载&#xff1a;https://www.erlang.org/patches/otp-26.0 百度网盘&#xff1a;https://pan.baidu.com/s/1xU4syn14Bh7QR-skjm_hOg 提取码&#xff1a;az1t RabbtitMQ下载 官网下载&#xff1a;https://www.rabbitmq.com/docs/install-windows 百度网盘…

Python二进制文件转换为文本文件

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在日常编程中&#xff0c;我们经常会遇到需要将二进制文件转换为文本文件的情况。这可能是因…

Python请求示例电商商品详情数据(API接口开发系列),从入门到实战

在电商系统中&#xff0c;商品详情数据通常通过API接口提供。以下是一个从入门到实战的Python请求示例&#xff0c;展示如何获取电商商品详情数据。 入门篇&#xff1a;理解API接口 首先&#xff0c;你需要了解API&#xff08;应用程序接口&#xff09;的基本概念。API允许不…

Spring Boost + Elasticsearch 实现检索查询

需求&#xff1a;对“昵称”进行“全文检索查询”&#xff0c;对“账号”进行“精确查询”。 认识 Elasticsearch 1. ES 的倒排索引 正向索引 对 id 进行检索速度很快。对其他字段即使加了索引&#xff0c;只能满足精确查询。模糊查询时&#xff0c;逐条数据扫描&#xff0c…

VMware17Pro虚拟机安装macOS教程(超详细)

目录 1. 前言2. 下载所需文件3. 安装VMware3.1 安装3.2 启动并查看版本信息3.3 虚拟机默认位置配置 4. 安装补丁4.1 解压补丁4.2 结束VMware相关进程4.3 运行补丁包 5. 安装macOS5.1 新建虚拟机5.2 修改虚拟机配置5.3 安装操作系统5.3.1 选择 ISO 映像文件5.3.2 开启虚拟机5.2.…

重仓比特币

作者&#xff1a;Arthur Hayes Co-Founder of 100x. 编译&#xff1a;liam ccvalue (下文中表达的任何观点均为作者的个人观点&#xff0c;不应作为投资决策的依据&#xff0c;也不应被视为参与投资交易的建议或意见&#xff09;。 我们中断牛市常规节目&#xff0c;为您播报这…

SpringCloud 之 服务提供者

前提 便于理解,我修改了本地域名》这里!!! 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 eureka7003.com学习Rest实例之提供者 提供者模块展示 1、导入依赖 <!-- 实体类 Web--><dependency><groupId>com.jyl</groupId><…

C语言中浮点型存储方式

前言 这次是上次博客的续写哦&#xff0c;如果有小伙伴不了解&#xff0c;可以点击链接跳转 C语言中整数与浮点数在内存中的存储 我们在上次的博客中给大家留了一段代码&#xff0c;不知道大家现在有没有想明白呢&#xff0c;让我来为大家揭秘吧&#xff01;&#xff01; int m…

RakSmart美国VPS评测分析你了解多少

在当前的云计算市场中&#xff0c;RakSmart美国VPS以其出色的性能与稳定性&#xff0c;受到了广大用户的青睐。本文将对RakSmart美国VPS进行新的评测分析&#xff0c;帮助大家更好地了解这款产品。 首先&#xff0c;从性能角度来看&#xff0c;RakSmart美国VPS无疑是一款高性能…

C语言学习/复习34--内存相关笔试题/C与C++的内存/柔性数组

一、动态内存管理笔试题 1.值传递 注意事项1&#xff1a;指针的地址传递需要将指针的地址用二级指针接收&#xff0c;本题属于值传递不属于地址传递 修改&#xff1a;1改为地址传递&#xff0c;2释放malloc()函数申请的空间 注意事项2&#xff1a;printf()字符串时&#xff0c;…