Unity 实现原神中的元素反应

news2025/1/19 3:25:54

一、元素反应

  • 原神中共有七种元素,分别是水、火、冰、岩、风、雷、草。这七种元素能互相作用
  • 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.coloradmin.cn/o/1622552.html

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

相关文章

揭秘高效秘诀:并行工作方法论助你事半功倍!

当一个人在一段时间面对多项工作内容的时候&#xff0c;有的人可以顺利高效地完成任务&#xff1b;有的人经过大量的加班也可以完成任务&#xff1b;有的人不用通过加班就能高效地完成任务。 如何高效地完成每项工作内容而实现目标&#xff0c;就变得相当重要了。“并行工作方法…

李宏毅2022机器学习/深度学习 个人笔记(1)

本系列用于推导、记录该系列视频中本人不熟悉、或认为有价值的知识点 本篇记录第一讲&#xff08;选修&#xff09;&#xff1a;神奇宝贝分类 如图&#xff0c;为了估算某个样本属于某类的概率&#xff0c;在二分类问题中&#xff0c;我们需要计算红框所示的4个参数&#xff0…

Web前端开发之HTML_1

第一个前端程序VS Code安装VS Code 快捷键 1. 第一个前端程序 使用记事本&#xff0c;新建一个文本文档&#xff0c;重命名为Welcome.html&#xff0c;如下图&#xff1a; 用记事本打开文档&#xff0c;内容输入如下&#xff1a; <html> <head> <t…

精酿啤酒:从酿造到包装的严格质量控制流程

在啤酒酿造行业中&#xff0c;质量控制是确保产品品质和口感的重要环节。Fendi Club啤酒在从酿造到包装的整个过程中&#xff0c;实施了严格的质量控制流程&#xff0c;确保每一瓶啤酒都达到了高标准的质量要求。 在酿造过程中&#xff0c;Fendi Club啤酒严格控制原料的质量。他…

SAP FI SD UKM_ITEMS_READ 信贷读取 注意点

营销核算反馈说是 以上连个客户之间 有从属关系&#xff0c;但是通过接口获取的信贷数据缺了一部分&#xff0c;只有组代码的那一部分&#xff0c;经查询总欠款是通过 UKM_ITEMS_READ 获取的。要求改正确&#xff0c;但是TMD没有给逻辑&#xff0c;也没有查其他是否正常。果断找…

BSV区块链协会上线首个版本的ARC交易处理器

​​发表时间&#xff1a;2024年3月28日 BSV区块链协会近期上线了首个版本的ARC交易处理器。ARC是一项区块链交易处理服务&#xff0c;能在通过P2P网络广播交易之前验证并存储相关的交易。一旦新区块被挖出&#xff0c;一条与该交易相关的Merkle路径将被发回给交易发起者作为确…

数值积分——复化梯形求积公式 | 北太天元

复化求积法的思想&#xff1a; 将区间 [ a , b ] [a,b] [a,b]进行 n n n等分&#xff0c;步长 h b − a n h\frac{b-a}{n} hnb−a​&#xff0c;等分点 x k a k h , k 0 , 1 , 2 , ⋯ , n x_{k}akh,k0,1,2,\cdots,n xk​akh,k0,1,2,⋯,n, 先在每个子区间 [ x k , x k 1 ] …

FANUC发那科机器人如何进行维修

FANUC发那科机器人是一种广泛应用于制造业的自动化设备&#xff0c;其可靠性和稳定性对于生产线的正常运行至关重要。然而&#xff0c;随着使用时间的增加&#xff0c;机器人难免会出现各种法兰克机械手故障和维修FANUC机器人需求。 一、了解发那科机器人故障现象 首先&#xf…

智慧城市标准化白皮书(2022版)发布

2022年7月25日&#xff0c;国家智慧城市标准化总体组2022年度全体会议召开期间&#xff0c;《智慧城市标准化白皮书&#xff08;2022版&#xff09;》正式发布。 城市作为一个复杂巨系统&#xff0c;是多元主体融合及多元活动集聚的复杂综合体。城市的运行发展关联 到发展、治…

2024年教你学会如何把学浪视频下载到本地

今年是2024年&#xff0c;依然有很多小伙伴想下载学浪却不知道怎么下载&#xff0c;本文就教大家如何使用小浪助手工具下载学浪视频 小浪助手工具我已经打包好了&#xff0c;有需要的自己取一下 学浪下载工具链接&#xff1a;https://pan.baidu.com/s/1-axc7xDtwU_KtupCe52sV…

Nodejs--异步编程

异步编程 函数式编程 高阶函数 在通常的语言中&#xff0c;函数的参数只接受基本的数据类型或者是对象引用&#xff0c;返回值只能是基本数据类型和对象引用。 function foo(x) {return x }高阶函数是把函数作为参数&#xff0c;将函数作为返回值的函数 function foo(x) {…

最短路问题之Bellman-Ford,SPFA算法,例题 负环

Bellman-Ford算法&#xff1a; Bellman-Ford算法用于解决带有负权边的单源最短路径问题。其基本思想是通过不断地松弛边来逐步求解最短路径。算法的主要步骤如下&#xff1a; 初始化&#xff1a;将源点到各个顶点的距离初始化为无穷大&#xff0c;源点的距离初始化为0。重复更…

二. 搭建Nginx 直播流程服务器

目录 1. 前言 2. 安装 Nginx 依赖 3.下载源码 4. 编译安装 5.配置 rtmp 服务 6.验证配置 1. 前言 服务器由 NGINXRTMP 构成。 NGINX 是 HTTP 服务器&#xff0c; RTMP 是附加模块。 其中 NGINX 我选择的是用 源码编译方式 进行安装&#xff0c;因为这种方式可以自定义…

Three.js入门学习笔记

学习资料&#xff1a; 【Three.js】Three.js快速上手教程_three.module.js-CSDN博客 2024年了&#xff0c;是该学学Three.js了_three.js 2024-CSDN博客 一、three.js简介 three.js是JavaScript编写的WebGL第三方库。 three.js&#xff0c;webGL&#xff0c;openGL三者的关…

WEB前端-笔记(三)

目录 一、事件 1.1类型 1.2对象 1.3页面加载事件 1.4滚动事件 1.5尺寸事件 1.6捕获&冒泡事件 1.7阻止表单提交 1.8全选案例 1.9事件委托 ​编辑 1.10client&offset 1.11换取元素的位置 1.12创建节点 1.13克隆节点 1.14删除节点 1.15setTimeout 1.16s…

人工智能入门(一):基于Pytorch的手写数字识别模型

前言&#xff1a; 因为还在上学&#xff0c;时间不太够用&#xff0c;很多内容写到后面心有余力不足&#xff0c;未来有时间我会慢慢补充。人工智能的知识涉猎范围广又杂乱无章&#xff0c;啃书或上课学到的知识往往很早就过时了或者离实际的项目无关。所以&#xff0c;我很希…

【Git教程】(十七)发行版交付 — 概述及使用要求,执行过程及其实现,替代解决方案 ~

Git教程 发行版交付 1️⃣ 概述2️⃣ 使用要求3️⃣ 执行过程及其实现3.1 预备阶段&#xff1a;创建 stable 分支3.2 预备并创建发行版3.3 创建补丁 4️⃣ 替代解决方案 对于每个项目或产品来说&#xff0c;发布版本的创建都需要一定的时间&#xff0c;其具体过程因各公司或组…

arm版Linux下安装大数据集群各种组件

背景&#xff1a;由于本人是用的Macbookpro m2来进行开发的&#xff0c;很多环境和Intel芯片的都不一样&#xff0c;期间安装各种软件遇到各种问题&#xff0c;为了以后不走之前的老路&#xff0c;现记录各种软件的安装步骤。 系统安装组件说明 序号组件名称组件版本1jdkjdk-…

2024年电子商务与大数据经济国际会议 (EBDE 2024)

2024年电子商务与大数据经济国际会议 (EBDE 2024) 2024 International Conference on E-commerce and Big Data Economy 【会议简介】 2024年电子商务与大数据经济国际会议即将在厦门召开。本次会议旨在汇聚全球电子商务与大数据经济领域的专家学者&#xff0c;共同探讨电子商务…

基于MaxKB搭建一个知识库问答系统

什么是MaxKB MaxKB 是一款基于 LLM 大语言模型的知识库问答系统。MaxKB Max Knowledge Base&#xff0c;旨在成为企业的最强大脑。 开箱即用&#xff1a;支持直接上传文档、自动爬取在线文档&#xff0c;支持文本自动拆分、向量化&#xff0c;智能问答交互体验好&#xff1b…