Unity的live2dgalgame多语言可配置剧情框架

这段代码用于读取表格

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;
    }
}

这个方法里面设置剧情列表,和分支事件

cs 复制代码
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,选项要-2
      SetPlotBar(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}));
   }
   #endregion

   public 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);
   }
   
   
}

最终效果

相关推荐
m0_748251724 小时前
Android webview 打开本地H5项目(Cocos游戏以及Unity游戏)
android·游戏·unity
benben0444 小时前
Unity3D仿星露谷物语开发7之事件创建动画
unity·游戏引擎
林枫依依7 小时前
Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉
unity
虾球xz7 小时前
游戏引擎学习第57天
学习·游戏引擎
异次元的归来20 小时前
Unity DOTS中的share component
unity·游戏引擎
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
_oP_i1 天前
unity webgl部署到iis报错
unity
Go_Accepted1 天前
Unity全局雾效
unity
向宇it1 天前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎
每日出拳老爷子1 天前
【图形渲染】【Unity Shader】【Nvidia CG】有用的参考资料链接
unity·游戏引擎·图形渲染