【Unity-本地化】简单的游戏本地化处理方案

news2024/11/13 12:05:07

目录

  • 0 前言
  • 1 多语言配置
  • 2 本地化实现
    • 2.1 读取多语言文本的通用方法
    • 2.2 动态文本本地化
    • 2.3 静态文本本地化
  • 3 方案扩展
    • 3.1 LanguageText扩展
      • 3.1.1 展示Excel里对应ID的文本
      • 3.1.2 自动填充ID
      • 3.1.3 同步prefab的修改
      • 3.1.4 完整代码
    • 3.2 自动LanguageText挂载
  • 4* 内嵌文本图片的本地化

0 前言

这套本地化处理方案是基于Excel实现的,可以先扒一下我之前这篇文章的代码:Unity-Excel数据处理,这里会用到。

另外,这篇文章主要讲了纯文本的本地化方案,对于有内嵌字的图片,在最后会简单说一下处理方式。

1 多语言配置

通常情况下,项目内的文本会分散在各个表格之中,比如道具描述、技能说明等。但文本太过分散,会增加翻译难度,还可能会产生遗漏。所以我采取的方案是将多语言文本全部配置在同一张表格中,而其他表格则记录多语言文本的ID。

像这样:

Player.xlsx

在这里插入图片描述

LanguageLocalization.xlsx

在这里插入图片描述

像Player里的基础技能描述一般是便于制表人看,程序读取文本时用的是后面配置的本地化ID。

2 本地化实现

在开始之前先对LanguageLocalization.xlsx使用前言提到的excel数据处理方案,得到对应的CSharp和JsonData文件。

2.1 读取多语言文本的通用方法

这个通用方法应该是传入一个参数,然后根据当前语言环境返回对应的文本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LanguageTool
{
    public static SystemLanguage? defaultLanguage = SystemLanguage.Chinese;
    private static Dictionary<int, LanguageLocalization> languageDict;

    public static string GetLanguage(int id) {
        if (languageDict == null) {
            languageDict = LanguageLocalization.LoadJson();
        }

        //默认语言>系统语言
        if (defaultLanguage != null) {
            return GetLanguage(id, defaultLanguage.Value);
        }
        else {
            return GetLanguage(id, Application.systemLanguage);
        }
    }

    private static string GetLanguage(int id,SystemLanguage curLanguage) {
        switch (curLanguage) {
            case SystemLanguage.Chinese:
                //Excel里的换行符可能是\r\n的形式
                return languageDict[id].Text_Cn.Replace("\r\n", "\n");
            default:
                return languageDict[id].Text_En.Replace("\r\n", "\n");
        }
    }
}

2.2 动态文本本地化

动态文本指的是
1.像多语言配置中提到的Player的例子,技能描述、道具描述等。
2.像“失去2个道具”这样数字不确定的文本。

对于1直接根据表格内配置的Id读取多语言文本。
对于2需要先在多语言表格里自己配置一项,如失去{0}个道具,然后在代码里通过这样的形式获取文本:

tipText.text = string.Format(LanguageTool.GetLanguage(Id),num);

2.3 静态文本本地化

静态文本指的是写死在项目里,如Prefab上的文本。这种文本我写了一个组件挂在Text下,该组件会在Awake时将Text替换为对应语言环境的文本。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(Text))]
public class LanguageText : MonoBehaviour
{
    public int LanguageId = -1;

    private void Awake() {
        if (LanguageId == -1) {
            return;
        }
        var text = transform.GetComponent<Text>();
        text.text = LanguageTool.GetLanguage(LanguageId);
    }
}

3 方案扩展

除了以上必要的功能实现外,我们发现其实还可以从便利性出发去扩展当前这套方案。

3.1 LanguageText扩展

对于LanguageText组件,我们会希望有这些功能去辅助我们开发:

1.Inspector下展示所填写ID在Excel里对应的中英文,这样我们可以确定当前填写的ID正确。

2.当我们添加Prefab上的文本时,我们需要填写对应的多语言ID,如果去Excel里查找和编辑就有点麻烦,所以我们希望有一个方法可以实现:
1)如果Excel表里已经有这个文本了,那么自动填充对应ID。
2)如果Excel表里没有对应文本,那么在Excel里新增一行,然后填充对应ID。

3.修改Prefab上的文本时,我们希望有一个方法可以同步修改Excel里的文本。

表格:
在这里插入图片描述

3.1.1 展示Excel里对应ID的文本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;

[CustomEditor(typeof(LanguageText))]
public class LanguageTextEx : Editor
{
    private Dictionary<int, LanguageLocalization> languageDict;
    private LanguageText languageText;
    private Text textComponent;

    public override void OnInspectorGUI() {
        base.OnInspectorGUI();
        if (languageDict == null) {
            languageDict = LanguageLocalization.LoadJson();
        }

        if (textComponent == null) {
            languageText = target as LanguageText;
            textComponent = languageText.transform.GetComponent<Text>();
        }
		
		if (languageText.LanguageId <= -1 || !languageDict.ContainsKey(languageText.LanguageId)) {
            GUILayout.Label("当前ID不合法");
            return;
        }

        ShowExcelText();
    }

    /// <summary>
    /// 展示Excel对应ID的文本
    /// </summary>
    private void ShowExcelText() {
        GUILayout.Label($"Prefab上文本:{textComponent.text}");
        GUILayout.Label($"Excel上英文:{languageDict[languageText.LanguageId].Text_Cn}");
        GUILayout.Label($"Excel上中文:{languageDict[languageText.LanguageId].Text_En}");
    }
}

ID为0

在这里插入图片描述
ID为-1

在这里插入图片描述

3.1.2 自动填充ID

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.Linq;
using System.IO;
using OfficeOpenXml;

[CustomEditor(typeof(LanguageText))]
public class LanguageTextEx : Editor
{
    private string languageExcelPath = "/Excel/LanguageLocalization.xlsx";
    //...

    public override void OnInspectorGUI() {
		
		//...
		
        if (GUILayout.Button("匹配中文填充LanguageId")) {
            RecalculateLanguageId();
        }
		
		if (languageText.LanguageId <= -1 || !languageDict.ContainsKey(languageText.LanguageId)) {
    		GUILayout.Label("当前ID不合法");
    		return;
		}

		ShowExcelText();
    }

   	//...

    /// <summary>
    /// 填充LanguageID
    /// </summary>
    private void RecalculateLanguageId() {
        var list = languageDict.Where(x => IsTwoStrsSame(textComponent.text, x.Value.Text_Cn)).Select(x => x.Key).ToList();
        if (list.Count > 0) {
            //有匹配项
            languageText.LanguageId = list[0];
        }
        else {
            //无匹配项->写入Excel
            var file = new FileInfo(Application.dataPath+languageExcelPath);
            using (ExcelPackage package = new ExcelPackage(file)) {
                var worksheet = package.Workbook.Worksheets["Sheet1"];
                if (worksheet == null) {
                    Debug.Log($"没有找到路径为{languageExcelPath}的工作表");
                }
                else {
                    var endRow = worksheet.Dimension.End.Row;
                    var endIndex = -1;
                    for (var i = endRow; i >= 0; i--) {
                        var indexStr = worksheet.Cells[i, 2].Value?.ToString();
                        //找到最后一行非空数据
                        if (!string.IsNullOrEmpty(indexStr) && int.TryParse(indexStr, out endIndex)) {
                            endRow = i;
                            break;
                        }
                    }
                    //第二项指的是第几列,从1开始计数
                    worksheet.Cells[endRow + 1, 2].Value = endIndex + 1;
                    worksheet.Cells[endRow + 1, 3].Value = textComponent.text;
                    languageText.LanguageId = endIndex + 1;
                }
                package.Save();
            }
            //重新生成CSharp和JsonData
            ExcelToCSharpClass.ExcelToCSharpClassMethod(Application.dataPath + languageExcelPath);
            //刷新
            languageDict = LanguageLocalization.LoadJson();
            AssetDatabase.Refresh();
        }
        Debug.Log("LanguageId填充成功");
    }

    /// <summary>
    /// 去换行符影响
    /// </summary>
    private bool IsTwoStrsSame(string str1, string str2) {
        str1 = str1.Replace("\r\n", "\n");
        str2 = str2.Replace("\r\n", "\n");
        return str1 == str2;
    }
}

匹配前

在这里插入图片描述
匹配后

在这里插入图片描述

3.1.3 同步prefab的修改

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.Linq;
using System.IO;
using OfficeOpenXml;

[CustomEditor(typeof(LanguageText))]
public class LanguageTextEx : Editor
{
    //...

    public override void OnInspectorGUI() {
        //...

        if (GUILayout.Button("匹配中文填充LanguageId")) {
            RecalculateLanguageId();
        }

        if (GUILayout.Button("同步Prefab上的文本到Excel的中文文本")) {
            SetTextToExcel(SystemLanguage.Chinese);
        }

        if (GUILayout.Button("同步Prefab上的文本到Excel的英文文本")) {
            SetTextToExcel(SystemLanguage.English);
        }
    }

    //...

    /// <summary>
    /// 同步文本到Excel表格里
    /// </summary>
    public void SetTextToExcel(SystemLanguage languageType) {
        if (languageType != SystemLanguage.Chinese && languageType != SystemLanguage.English)
        {
            return;
        }
        var file = new FileInfo(Application.dataPath + languageExcelPath);
        using (ExcelPackage package = new ExcelPackage(file))
        {
            var worksheet = package.Workbook.Worksheets["Sheet1"];
            if (worksheet == null)
            {
                Debug.Log($"没有找到路径为{languageExcelPath}的工作表");
            }
            else
            {
                var endRow = worksheet.Dimension.End.Row;
                for(var i = 4; i <= endRow; i++)
                {
                    var id = int.Parse(worksheet.Cells[i, 2].Value.ToString().Trim());
                    if (id == languageText.LanguageId)
                    {
                        switch (languageType) {
                            case SystemLanguage.Chinese:
                                worksheet.Cells[i, 3].Value = textComponent.text;
                                break;
                            case SystemLanguage.English:
                                worksheet.Cells[i, 4].Value = textComponent.text;
                                break;
                            default:
                                break;
                        }
                        break;
                    }
                }
            }
            package.Save();
        }
        //重新生成CSharp和JsonData
        ExcelToCSharpClass.ExcelToCSharpClassMethod(Application.dataPath + languageExcelPath);
        //刷新
        languageDict = LanguageLocalization.LoadJson();
        AssetDatabase.Refresh();
    }
}

更改Prefab上的文字

在这里插入图片描述

点击同步

在这里插入图片描述
在这里插入图片描述

3.1.4 完整代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.Linq;
using System.IO;
using OfficeOpenXml;

[CustomEditor(typeof(LanguageText))]
public class LanguageTextEx : Editor
{
    private string languageExcelPath = "/Excel/LanguageLocalization.xlsx";
    private Dictionary<int, LanguageLocalization> languageDict;
    private LanguageText languageText;
    private Text textComponent;

    public override void OnInspectorGUI() {
        base.OnInspectorGUI();
        if (languageDict == null) {
            languageDict = LanguageLocalization.LoadJson();
        }

        if (textComponent == null) {
            languageText = target as LanguageText;
            textComponent = languageText.transform.GetComponent<Text>();
        }

        if (GUILayout.Button("匹配中文填充LanguageId"))
        {
            RecalculateLanguageId();
        }

        if (languageText.LanguageId <= -1 || !languageDict.ContainsKey(languageText.LanguageId)) {
            GUILayout.Label("当前ID不合法");
            return;
        }

        ShowExcelText();

        if (GUILayout.Button("同步Prefab上的文本到Excel的中文文本"))
        {
            SetTextToExcel(SystemLanguage.Chinese);
        }

        if (GUILayout.Button("同步Prefab上的文本到Excel的英文文本"))
        {
            SetTextToExcel(SystemLanguage.English);
        }
    }

    /// <summary>
    /// 展示Excel对应ID的文本
    /// </summary>
    private void ShowExcelText() {
        GUILayout.Label($"Prefab上文本:{textComponent.text}");
        GUILayout.Label($"Excel上中文:{languageDict[languageText.LanguageId].Text_Cn}");
        GUILayout.Label($"Excel上英文:{languageDict[languageText.LanguageId].Text_En}");
    }

    /// <summary>
    /// 填充LanguageID
    /// </summary>
    private void RecalculateLanguageId() {
        var list = languageDict.Where(x => IsTwoStrsSame(textComponent.text, x.Value.Text_Cn)).Select(x => x.Key).ToList();
        if (list.Count > 0) {
            //有匹配项
            languageText.LanguageId = list[0];
        }
        else {
            //无匹配项->写入Excel
            var file = new FileInfo(Application.dataPath + languageExcelPath);
            using (ExcelPackage package = new ExcelPackage(file)) {
                var worksheet = package.Workbook.Worksheets["Sheet1"];
                if (worksheet == null) {
                    Debug.Log($"没有找到路径为{languageExcelPath}的工作表");
                }
                else {
                    var endRow = worksheet.Dimension.End.Row;
                    var endIndex = -1;
                    for (var i = endRow; i >= 4; i--) {
                        var indexStr = worksheet.Cells[i, 2].Value?.ToString();
                        if (!string.IsNullOrEmpty(indexStr) && int.TryParse(indexStr, out endIndex)) {
                            endRow = i;
                            break;
                        }
                    }
                    worksheet.Cells[endRow + 1, 2].Value = endIndex + 1;
                    worksheet.Cells[endRow + 1, 3].Value = textComponent.text;
                    languageText.LanguageId = endIndex + 1;
                }
                package.Save();
            }
            //重新生成CSharp和JsonData
            ExcelToCSharpClass.ExcelToCSharpClassMethod(Application.dataPath + languageExcelPath);
            //刷新
            languageDict = LanguageLocalization.LoadJson();
            AssetDatabase.Refresh();
        }
        Debug.Log("LanguageId填充成功");
    }

    /// <summary>
    /// 同步文本到Excel表格里
    /// </summary>
    public void SetTextToExcel(SystemLanguage languageType) {
        if (languageType != SystemLanguage.Chinese && languageType != SystemLanguage.English)
        {
            return;
        }
        var file = new FileInfo(Application.dataPath + languageExcelPath);
        using (ExcelPackage package = new ExcelPackage(file))
        {
            var worksheet = package.Workbook.Worksheets["Sheet1"];
            if (worksheet == null)
            {
                Debug.Log($"没有找到路径为{languageExcelPath}的工作表");
            }
            else
            {
                var endRow = worksheet.Dimension.End.Row;
                for(var i = 4; i <= endRow; i++)
                {
                    var id = int.Parse(worksheet.Cells[i, 2].Value.ToString().Trim());
                    if (id == languageText.LanguageId)
                    {
                        switch (languageType) {
                            case SystemLanguage.Chinese:
                                worksheet.Cells[i, 3].Value = textComponent.text;
                                break;
                            case SystemLanguage.English:
                                worksheet.Cells[i, 4].Value = textComponent.text;
                                break;
                            default:
                                break;
                        }
                        break;
                    }
                }
            }
            package.Save();
        }
        //重新生成CSharp和JsonData
        ExcelToCSharpClass.ExcelToCSharpClassMethod(Application.dataPath + languageExcelPath);
        //刷新
        languageDict = LanguageLocalization.LoadJson();
        AssetDatabase.Refresh();
    }


    /// <summary>
    /// 去换行符影响,因为Excel里的换行符可能是\r\n的形式
    /// </summary>
    private bool IsTwoStrsSame(string str1, string str2) {
        str1 = str1.Replace("\r\n", "\n");
        str2 = str2.Replace("\r\n", "\n");
        return str1 == str2;
    }
}

3.2 自动LanguageText挂载

每次在Text下去挂一个组件有点太麻烦了,需要一个可以遍历选择的Prefab然后自动去挂载的方法。

代码暂略。

4* 内嵌文本图片的本地化

在尽量分离项目里的文本和图片之后,对于剩余的还有内嵌文本的图片(一般都是为了实现美术效果),我采用的方式是:让美术切出不同语言环境下要用的图片,然后以不同后缀,如_cn,_en放在项目里面,然后写一个组件挂在Image下,实现的效果类似:如果当前使用的图片后缀含_cn,则替换为对应语言环境下的图片。

挂载组件也可以参考3.2所说的,写一个遍历挂载的方法。

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

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

相关文章

AI预测福彩3D采取888=3策略+和值012路或胆码测试8月14日新模型预测第56弹

好长时间没进行总结了&#xff0c;今天咱们做一个总结&#xff0c;总结一下最新模型经过50多期的测试结果&#xff1a; 经过近50多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率…

restful传值

GetMapping 普通的get请求 后端&#xff1a; restfule的get请求 通过/asd/123这种方式get请求传入后端 前端 url: /system/role/deptTree/ roleId / tenantId, method: get后端PathVariable从path上取对应的值 通过 GetMapping(value "/deptTree/{roleId}/{tenan…

Windows平台RTSP|RTMP播放器如何实时调节音量

我们在做Windows平台RTSP、RTMP播放器的时候&#xff0c;有这样的技术需求&#xff0c;特别是多路监控的时候&#xff0c;并不是每一路audio都需要播放出来的&#xff0c;所以&#xff0c;这时候&#xff0c;需要有针对音量调节的设计&#xff1a; /** smart_player_sdk.cs* C…

3DsMax如何给模型添加一个外壳

3DsMax如何给模型添加一个外壳 在3DsMax中添加外壳 复制一个使用缩放添加一个外壳&#xff08;适用性不多&#xff09; 复制一份&#xff0c;修改复制的模型的缩放&#xff0c;模型套模型作为外壳。&#xff0c;当模型是管道的时候就不大行。 使用壳修改器 添加之后&#…

pyqt5 爬虫开源项目

使用 PyQt5 进行网络爬虫开发通常涉及创建一个图形用户界面(GUI)来管理和展示爬虫的运行状态和结果。以下是一些结合 PyQt5 和网络爬虫技术的开源项目,可以作为学习和参考的好资源: PySpider-GUI: 简介: 一个基于 PyQt5 的网络爬虫 GUI,用于管理和运行爬虫任务。GitHub: P…

DHCP 笔记 + 配置示例

一、概念 DHCP 3 种渠道&#xff1a; 1、基于接口 2、基于全局 3、基于中继 DHCP正常 4 个阶段和 8 种报文&#xff1a; 1、Client&#xff1a;Discover 2、Server&#xff1a;Offer …

python结合csv和正则实现条件筛选数据统计分数

前景提要&#xff1a; 有一个项目的数值和员工统计的对不上&#xff0c;如果一页一页翻找自己手动算&#xff0c;一个就有16、7页&#xff0c; 功能实现 1、创建csv文件 需要将每一个模块的所有数据头提取出来&#xff0c;这个可以直接用爬虫或者手工复制出来&#xff0c;因…

SpringCloud-01

单体架构 将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署 优点 架构简单 部署成本低 缺点 耦合度高 分布式架构 根据业务功能对系统进行拆分&#xff0c;每个业务模块作为单独项目开发&#xff0c;称为一个服务。 优点 降低服务耦合 有利于服务升级…

Spring Cloud Alibaba微服务组件学习笔记

文章目录 一、版本说明版本关系项目创建 二、Nacos注册中心什么是NacosNacos注册中心核心功能Nacos Server部署&#xff08;windows版本&#xff09;Nacos Client服务Nacos Server配置项详解&#xff1a;Nacos集群搭建&#xff1a; 三、Ribbon负载均衡主流的负载方案&#xff1…

网工必备-网络设备配置文件及日志高亮显示Sublime Text

文章目录 下载Sublime Text 4下载高亮配色文件使用方法 之前推荐了一款文本编辑工具【编写脚本及查看日志的高亮文本编辑工具——EverEdit】&#xff0c;可以针对网络工程师们日常的网络设备配置文件及日志的高亮显示&#xff0c;但是需要保存后才可以显示高亮&#xff0c;虽然…

AI预测体彩排3采取888=3策略+和值012路或胆码测试8月14日升级新模型预测第51弹

好长时间没进行总结了&#xff0c;今天咱们做一个总结&#xff0c;总结一下最新模型经过50多期的测试结果&#xff1a; 经过近50多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率…

深入探讨Linux的进程调度器

Linux操作系统作为一个开源且广泛应用的操作系统&#xff0c;其内核设计包含了许多核心功能&#xff0c;而进程调度器&#xff08;Scheduler&#xff09;就是其中一个至关重要的模块。进程调度器负责决定在任何给定的时刻哪个进程可以运行&#xff0c;以及其运行的顺序。这篇文…

如何编写一个CMakeLists.txt文件(由简到难,较详细)

在Linux系统下&#xff0c;经常使用CMakeLists.txt文件来链接、编译C工程&#xff0c;大部分人clone的代码里都是有CMakeLists.txt文件的&#xff0c;只需要cmake .. 和make就完事了&#xff0c;但在工作中&#xff0c;你必须要有从无到有编写CMakeLists.txt文件的能力。 一、…

一款简易大众点评项目实战——达人探店、关注、附近商圈、签到、UV统计

一款简易大众点评项目实战——达人探店、关注、附近商圈、签到、UV统计 8.达人探店8.1上传接口与发布笔记接口8.2 达人探店-查看探店笔记8.3 达人探店-点赞功能8.4 达人探店-点赞排行榜 9、好友关注9.1 好友关注-关注和取消关注9.2 好友关注-共同关注9.3 好友关注-Feed流实现方…

Visual Studio 2024安装教程(非常详细),从零基础入门到精通,看完这一篇就够了(附安装包)

软件下载 软件&#xff1a;Visual Studio版本&#xff1a;2022语言&#xff1a;简体中文大小&#xff1a;4.11M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨下载链接&#xff1a;https://pan.baid…

C语言-在主函数中输入10个等长的字符串。用另一函数对他们进行排序,然后再主函数输出这10个排好序的数列(分别用数组法和指针法实现)

在主函数中输入10个等长的字符串。用另一函数对他们进行排序&#xff0c;然后再主函数输出这10个排好序的数列&#xff08;分别用数组法和指针法实现&#xff09; 一、数组法实现 void str_sort(char str[][32], int n) {int i, j;for (i 0; i < n - 1; i){for (j 0; j …

Stable Diffusion WebUI安装ControlNet 遇到的问题

最近研究Stable Diffusion &#xff0c;在安装ControlNet遇到了几个问题&#xff0c;总算解决了 1.第一个是连不上github,可以使用国内的这个 https://gitcode.com/gh_mirrors/sd/sd-webui-controlnet.git 2.第二个问题是一直Installing ,虽然下载下来了&#xff0c;但还是…

【Python】函数练习题

1、定义一个函数&#xff0c;用于计算一个字符串中字符a出现的次数并通过return返回。 代码&#xff1a; 2、写函数&#xff0c;判断用户传入的一个值&#xff08;字符串或列表或字典或元组&#xff09;长度是否大于5&#xff0c;如果大于5返回True,反之返回False. 代码&…

Python实现邮件发送时,如何优化邮件内容?

Python实现邮件发送如何设置&#xff1f;使用Python发信技巧&#xff1f; 无论是个人用途还是企业需求&#xff0c;一封优化良好的邮件能够提升用户体验&#xff0c;提高邮件的打开率和响应率。AokSend将探讨在Python实现邮件发送时&#xff0c;如何通过几个关键步骤来优化邮件…

【C#】中IndexOf的用法

在 C# 中&#xff0c;IndexOf 方法是字符串和列表&#xff08;如 List<T>&#xff09;等数据结构中常用的方法&#xff0c;用于查找指定元素或子串首次出现的位置。以下是针对不同情况使用 IndexOf 的示例。 对于字符串 对于字符串类型&#xff0c;IndexOf 方法返回子字…