这段代码用于读取表格
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OfficeOpenXml;
using System.IO;
using UnityEngine.Networking;
using UnityEngine.UI;
using Random = UnityEngine.Random;public class Plots : MonoBehaviour
{public static string ReadingExcel;//正在读取的表格[Header("表格文件夹")] public static string URL = Application.streamingAssetsPath;public static string PlotsEXCEL = "Plots";private static bool m_loaded;public class plot{public string index, CN,NameCN, NameEN,EN,NameJP, JP,Face;}public static List<plot> S_Plots= new List<plot>();public virtual void OnEnable(){initialization();}//初始化public void initialization(){if (!m_loaded){LoadExcel();m_loaded = true;} }void LoadExcel(){//获取Excel文件的信息foreach (var VARIABLE in ReadFile()){Debug.Log("剧情挂载成功");FileInfo fileInfo = new FileInfo(VARIABLE);//加载背包信息if (VARIABLE.Contains(PlotsEXCEL)){//通过Excel表格的文件信息,打开Excel表格//使用using(){}语句命令,在结束时自动关闭文件using (ExcelPackage excelPackage = new ExcelPackage(fileInfo)){//读取Excel中的第一张表, 注意EPPlus的索引值是从1开始的ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets[1];//取得第一行第一列的数据
// Debug.Log("行数"+worksheet.Dimension.End.Row + 1);for (int Left = 2; Left < worksheet.Dimension.End.Row + 1; Left++) //根据行数遍历{if (worksheet.Cells[Left, 1].Value.ToString().Length>0){plot Plot = new plot();Plot.index= worksheet.Cells[Left, 1].Value.ToString();Plot.Face= worksheet.Cells[Left, 2].Value.ToString();Plot.CN= worksheet.Cells[Left, 3].Value.ToString();Plot.NameCN= worksheet.Cells[Left, 4].Value.ToString();Plot.EN= worksheet.Cells[Left, 5].Value.ToString();Plot.NameEN= worksheet.Cells[Left, 6].Value.ToString();Plot.JP= worksheet.Cells[Left, 7].Value.ToString();Plot.NameJP= worksheet.Cells[Left, 8].Value.ToString();S_Plots.Add(Plot);}}}}}}/// <summary>/// 字符串转Enum/// </summary>/// <typeparam name="T">枚举</typeparam>/// <param name="str">字符串</param>/// <returns>转换的枚举</returns>public static T ToEnum<T>(string str){try{return (T)Enum.Parse(typeof(T), str);}catch (ArgumentException e){Debug.LogError("未找到系列"+str);throw;}}static List<string> ReadFile(){List<string> files = GetFiles(URL, "*.xlsx");List<string> GetFiles(string directory, string pattern){List<string> files = new List<string>();foreach (var item in Directory.GetFiles(directory, pattern)){files.Add(item);}foreach (var item in Directory.GetDirectories(directory)){files.AddRange(GetFiles(item, pattern));}return files;}return files;}
}
这个方法里面设置剧情列表,和分支事件
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using DG.Tweening;
using Live2D.Cubism.Rendering;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using UnityEngine;
using UnityEngine.UI;public class PlotReader : MonoBehaviour
{public Button[] ChoiceButton;public Text Text_Plot,Text_Name;public static int[] PlotBar;public static Action PlotFinEvent;public Button BTN_NextStep,BTN_Auto,BTN_Skip;public bool AutoMode,SkipMode;public Button LanguageCN, LanguageEN, LanguageJP;public float DomoveOffeset = 100;public float DomoveTime=0.1f;public GameObject Live2DFolider;public int index=0;private void Start(){LanguageCN.onClick.AddListener(()=>{Center.Language = "CN";RefreshLanguage();});LanguageEN.onClick.AddListener(()=>{Center.Language = "EN";RefreshLanguage();});LanguageJP.onClick.AddListener(()=>{Center.Language = "JP";RefreshLanguage();});BTN_Auto.onClick.AddListener(() =>{AutoMode = !AutoMode;SkipMode = false;});BTN_Skip.onClick.AddListener(() =>{SkipMode = !SkipMode;AutoMode = false;});BTN_NextStep.onClick.AddListener(PlotNext);//注意!!! 剧情要-1,选项要-2SetPlotBar(new int[]{0,1,2,3,4,5,6,7},() => MakeChoice(new int[] { 7, 8 ,16}));PlotNext();}private float AutoTimeindex;private float AutoTimeMax = 3f;private void Update(){if (AutoMode){if (index<=PlotBar.Length){AutoTimeindex -= Time.deltaTime;}if (AutoTimeindex < 0 ){AutoTimeindex = AutoTimeMax;PlotNext();}}if (SkipMode){if (index<=PlotBar.Length){AutoTimeindex -= Time.deltaTime*20;}if (AutoTimeindex < 0 ){AutoTimeindex = AutoTimeMax;PlotNext();}}}public void PlotNext(){if (index<PlotBar.Length){DoMethodEvent(Plots.S_Plots[PlotBar[index]].Face);Text_Plot.text = GetLanguagePlot(PlotBar[index]);Text_Name.text = GetLanguageName(PlotBar[index]);}else if (index== PlotBar.Length){PlotFinEvent();}index++;}public void RefreshLanguage(){try{Text_Plot.text = GetLanguagePlot(PlotBar[index-1]);Text_Name.text = GetLanguageName(PlotBar[index-1]);}catch (IndexOutOfRangeException e){Text_Plot.text = GetLanguagePlot(PlotBar[PlotBar.Length-1]);Text_Name.text = GetLanguageName(PlotBar[PlotBar.Length-1]);}}/// <summary>/// 根据语言获得剧情/// </summary>/// <param name="index"></param>/// <returns></returns>public string GetLanguagePlot(int index){// Debug.LogError(index+Plots.S_Plots[index].CN+Plots.S_Plots[index].NameCN);switch (Center.Language){case "CN":return Plots.S_Plots[index].CN;case "EN":return Plots.S_Plots[index].EN;case "JP":return Plots.S_Plots[index].JP;}
Debug.LogError("语言??");return null;}/// <summary>/// 根据语言获得剧情/// </summary>/// <param name="index"></param>/// <returns></returns>public string GetLanguageName(int index){switch (Center.Language){case "CN":return Plots.S_Plots[index].NameCN;case "EN":return Plots.S_Plots[index].NameEN;case "JP":return Plots.S_Plots[index].NameJP;}Debug.LogError("语言??");return null;}/// <summary>/// 设置对话列表/// </summary>/// <param name="t"></param>public void SetPlotBar(int[] t,Action FinEvent){PlotBar = t;PlotFinEvent = FinEvent;}#region 分支public void MakeChoice(int [] choices){CloseAllButtons();for (int i = 0; i<choices.Length; i++){int i1 = i;ChoiceButton[i1].gameObject.SetActive(true);ChoiceButton[i1].transform.Find("Text").GetComponent<Text>().text = GetLanguagePlot(choices[i1]+1);ChoiceButton[i1].onClick.AddListener(() =>{index = 0;Debug.LogError("执行事件BTN"+(choices[i1]+2));ExecuteMethodByName("BTN"+(choices[i1]+2));CloseAllButtons();PlotNext();});}}public void CloseAllButtons(){foreach (var VARIABLE in ChoiceButton){VARIABLE.onClick.RemoveAllListeners();VARIABLE.gameObject.SetActive(false);}}public void BTN9(){SetPlotBar(new int[]{10,11,12,13},JumpToGameLevel);}public void BTN10(){SetPlotBar(new int[]{14,15,16},JumpToGameLevel);}public void BTN18(){SetPlotBar(new int[]{0,1,2,3,4,5,6,7},() => MakeChoice(new int[] { 7, 8 ,16}));}#endregionpublic void JumpToGameLevel(){Debug.LogError("将跳转场景");}public void ExecuteMethodByName(string methodName){// 使用反射获取类的类型Type type = this.GetType();// 使用反射获取方法信息MethodInfo methodInfo = type.GetMethod(methodName);if (methodInfo != null){// 调用匹配的方法methodInfo.Invoke(this, null);}else{Console.WriteLine("Method not found: " + methodName);}}public string[] CutMethod(string input){return input.Split('+');}public void DoMethodEvent(string input){Debug.LogError(input);foreach (var VARIABLE in CutMethod(input)){if (!VARIABLE.Contains("(")){ExecuteMethodByName(VARIABLE);}else if (VARIABLE.Contains("JOIN_")){Match match = Regex.Match(VARIABLE, @"\(([^)]*)\)");if (match.Success){// 获取括号内的内容,并使用逗号分割string[] parts = match.Groups[1].Value.Split(',');if (parts.Length == 4){string stringValue = parts[0];int intValue1, intValue2;if (int.TryParse(parts[1], out intValue1) && int.TryParse(parts[2], out intValue2)){string stringValue2 = parts[3];GameObject go = Instantiate(Resources.Load<GameObject>($"Live2D/{stringValue}"), Live2DFolider.transform);go.transform.position = new Vector3(-999, -999, 2);go.name = go.name.Replace("(Clone)", "");Vector3 worldCoordinate= Vector3.down;;switch (stringValue2){case "Left":worldCoordinate =Camera.main.ScreenToWorldPoint( new Vector3(intValue1-DomoveOffeset, intValue2, 2));Debug.LogError(worldCoordinate);worldCoordinate.z = 2;go.transform.position = worldCoordinate;worldCoordinate = Camera.main.ScreenToWorldPoint(new Vector3(intValue1, intValue2, 0));worldCoordinate.z = 0;go.transform.DOMove(worldCoordinate,DomoveTime);break;case "Right":worldCoordinate =Camera.main.ScreenToWorldPoint( new Vector3(intValue1+DomoveOffeset, intValue2, 2));Debug.LogError(worldCoordinate);worldCoordinate.z = 2;go.transform.position = worldCoordinate;worldCoordinate = Camera.main.ScreenToWorldPoint(new Vector3(intValue1, intValue2, 0));worldCoordinate.z = 0;go.transform.DOMove(worldCoordinate,DomoveTime);break;}}else{Debug.LogError("Failed to parse integers from the input.");}}else{Debug.LogError("Input does not contain 4 comma-separated values.");}}else{Debug.LogError("Input does not match the expected format.");}}else if (VARIABLE.Contains("SETA_")){Match match = Regex.Match(VARIABLE, @"\(([^)]*)\)");if (match.Success){// 获取括号内的内容,并使用逗号分割string[] parts = match.Groups[1].Value.Split(',');if (parts.Length == 3){string stringValue = parts[0];int intValue1, intValue2;if (int.TryParse(parts[1], out intValue1) && int.TryParse(parts[2], out intValue2)){GameObject go = Live2DFolider.transform.Find(parts[0]).gameObject;SetLive2DAlpha(go,intValue1,intValue2);}else{Debug.LogError("Failed to parse integers from the input.");}}else{Debug.LogError("Input does not contain 3 comma-separated values."+VARIABLE+$"length={parts.Length}");}}else{Debug.LogError("Input does not match the expected format.");}}else if (VARIABLE.Contains("FACE")){Match match = Regex.Match(VARIABLE, @"\(([^)]*)\)");if (match.Success){// 获取括号内的内容,并使用逗号分割string[] parts = match.Groups[1].Value.Split(',');if (parts.Length == 2){string stringValue = parts[0];string stringValue2 = parts[1];GameObject go = Live2DFolider.transform.Find(parts[0]).gameObject;SetFace(go,stringValue2);}else{Debug.LogError("Input does not contain 4 comma-separated values.");}}else{Debug.LogError("Input does not match the expected format.");}}else if (VARIABLE.Contains("LEAV_")){Match match = Regex.Match(VARIABLE, @"\(([^)]*)\)");if (match.Success){// 获取括号内的内容,并使用逗号分割string[] parts = match.Groups[1].Value.Split(',');if (parts.Length == 2){string stringValue = parts[0];GameObject go = Live2DFolider.transform.Find(parts[0]).gameObject;Vector3 worldCoordinate;StartCoroutine(des(go));break;IEnumerator des(GameObject go){SetLive2DAlpha(go,(int)(go.transform.Find("Drawables").GetComponentsInChildren<CubismRenderer>()[0].GetComponent<CubismRenderer>().Color.a)*100, 0);Debug.LogError($"Des{go.name}");yield return new WaitForSeconds(0.3f);Destroy(go);}}else{Debug.LogError("Input does not contain 4 comma-separated values.");}}else{Debug.LogError("Input does not match the expected format.");}}}}public void SetLive2DAlpha(GameObject target, int begin,int end){StartCoroutine(AlphaChangerCoroutine(target, begin / 100.0f, end / 100.0f));}private IEnumerator AlphaChangerCoroutine(GameObject target, float begin, float end){foreach (var renderer in target.transform.Find("Drawables").GetComponentsInChildren<CubismRenderer>()){Color currentColor = renderer.Color;currentColor.a = begin;Debug.LogError(currentColor.a);renderer.Color = currentColor;}float duration = 0.1f;int numSteps = 10;float stepTime = duration / numSteps;for (int step = 0; step <= numSteps; step++){float a = begin;if (end>begin){a += (end - begin) / numSteps * step;}else{a -= (begin - end) / numSteps * step;}foreach (var renderer in target.transform.Find("Drawables").GetComponentsInChildren<CubismRenderer>()){
// Debug.LogError(renderer.name);Color currentColor = renderer.Color;currentColor.a = a;Debug.LogError(currentColor.a);renderer.Color = currentColor;}yield return new WaitForSeconds(stepTime);}}public void SetFace(GameObject go, string Animatorname){go.GetComponent<Animator>().Play(Animatorname);}}
最终效果