添加了一些注释

This commit is contained in:
Empty-ZZJ
2025-03-25 20:02:09 +08:00
parent 5fd1f30d7a
commit 2d2e6b1abe
8 changed files with 390 additions and 182 deletions
+63
View File
@@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
+72
View File
@@ -0,0 +1,72 @@
# This .gitignore file should be placed at the root of your Unity project directory
#
# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
#
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/[Ll]ogs/
/[Uu]ser[Ss]ettings/
# MemoryCaptures can get excessive in size.
# They also could contain extremely sensitive data
/[Mm]emoryCaptures/
# Recordings can get excessive in size
/[Rr]ecordings/
# Uncomment this line if you wish to ignore the asset store tools plugin
# /[Aa]ssets/AssetStoreTools*
# Autogenerated Jetbrains Rider plugin
/[Aa]ssets/Plugins/Editor/JetBrains*
# Visual Studio cache directory
.vs/
# Gradle cache directory
.gradle/
# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.mdb
*.opendb
*.VC.db
# Unity3D generated meta files
*.pidb.meta
*.pdb.meta
*.mdb.meta
# Unity3D generated file on crash reports
sysinfo.txt
# Builds
*.apk
*.aab
*.unitypackage
*.app
# Crashlytics generated file
crashlytics-build.properties
# Packed Addressables
/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
# Temporary auto-generated Android Assets
/[Aa]ssets/[Ss]treamingAssets/aa.meta
/[Aa]ssets/[Ss]treamingAssets/aa/*
+6
View File
@@ -0,0 +1,6 @@
{
"version": "1.0",
"components": [
"Microsoft.VisualStudio.Workload.ManagedGame"
]
}
@@ -38,7 +38,6 @@ RenderSettings:
m_ReflectionIntensity: 1 m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0} m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0} m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0.12731704, g: 0.13414727, b: 0.121078536, a: 1}
m_UseRadianceAmbientProbe: 0 m_UseRadianceAmbientProbe: 0
--- !u!157 &3 --- !u!157 &3
LightmapSettings: LightmapSettings:
@@ -590,6 +589,7 @@ Canvas:
m_OverrideSorting: 0 m_OverrideSorting: 0
m_OverridePixelPerfect: 0 m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0 m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 0 m_AdditionalShaderChannelsFlag: 0
m_SortingLayerID: 0 m_SortingLayerID: 0
m_SortingOrder: 0 m_SortingOrder: 0
@@ -1083,7 +1083,7 @@ Camera:
m_Enabled: 1 m_Enabled: 1
serializedVersion: 2 serializedVersion: 2
m_ClearFlags: 1 m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} m_BackGroundColor: {r: 0, g: 0, b: 0, a: 1}
m_projectionMatrixMode: 1 m_projectionMatrixMode: 1
m_GateFitMode: 2 m_GateFitMode: 2
m_FOVAxisMode: 0 m_FOVAxisMode: 0
@@ -1202,7 +1202,7 @@ RectTransform:
m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0} m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 2136, y: 1068} m_SizeDelta: {x: 1772, y: 886}
m_Pivot: {x: 0.5, y: 0.5} m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1218022793 --- !u!114 &1218022793
MonoBehaviour: MonoBehaviour:
@@ -1449,6 +1449,7 @@ GameObject:
serializedVersion: 6 serializedVersion: 6
m_Component: m_Component:
- component: {fileID: 1534613768} - component: {fileID: 1534613768}
- component: {fileID: 1534613771}
- component: {fileID: 1534613767} - component: {fileID: 1534613767}
- component: {fileID: 1534613766} - component: {fileID: 1534613766}
- component: {fileID: 1534613769} - component: {fileID: 1534613769}
@@ -1623,6 +1624,18 @@ AudioSource:
m_PreInfinity: 2 m_PreInfinity: 2
m_PostInfinity: 2 m_PostInfinity: 2
m_RotationOrder: 4 m_RotationOrder: 4
--- !u!114 &1534613771
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1534613765}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f230b36db320b794d835661011534427, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1699916270 --- !u!1 &1699916270
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@@ -9,67 +9,106 @@ using TetraCreations.Attributes;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using static HGF.GalManager.Struct_PlotData; using static HGF.GalManager.Struct_PlotData;
namespace HGF namespace HGF
{ {
public class GalManager : MonoBehaviour public class GalManager : MonoBehaviour
{ {
/// <summary>
/// 当前剧情的唯一标识符
/// </summary>
public static string PlotID; public static string PlotID;
/// <summary>
/// 当前对话的UI组件
/// </summary>
[Title("当前对话")] [Title("当前对话")]
///
public GalManager_Text Gal_Text; public GalManager_Text Gal_Text;
/// <summary>
/// 当前角色立绘的UI组件
/// </summary>
[Title("当前角色部分")] [Title("当前角色部分")]
public GalManager_CharacterImg Gal_CharacterImg; public GalManager_CharacterImg Gal_CharacterImg;
/// <summary>
/// 控制选项的UI组件
/// </summary>
[Title("控制选项")] [Title("控制选项")]
public GalManager_Choice Gal_Choice; public GalManager_Choice Gal_Choice;
/// <summary>
/// 控制背景图片的UI组件
/// </summary>
[Title("控制背景图片的组件")] [Title("控制背景图片的组件")]
public GalManager_BackImg Gal_BackImg; public GalManager_BackImg Gal_BackImg;
/// <summary> /// <summary>
/// 当前场景角色数量 /// 当前场景中角色的数量
/// </summary> /// </summary>
[Title("当前场景角色数量")] [Title("当前场景角色数量")]
public int CharacterNum; public int CharacterNum;
/// <summary>
/// 音频系统模型,包含角色语音、背景音乐和文本音效的AudioSource
/// </summary>
public class AudioSystemModel public class AudioSystemModel
{ {
public AudioSource Character_Voice; public AudioSource Character_Voice; // 角色语音的AudioSource
public AudioSource BackMix; public AudioSource BackMix; // 背景音乐的AudioSource
public AudioSource TextMix; public AudioSource TextMix; // 文本音效的AudioSource
/// <summary>
/// 音频信息类,包含音频名称和路径
/// </summary>
public class AudioInfo public class AudioInfo
{ {
public string name; public string name;
public string path; public string path;
} }
public List<AudioInfo> AudioList = new();
/// <summary>
/// 背景音乐Clip
/// </summary>
/// <summary>
/// 音频列表,存储所有音频信息
/// </summary>
public List<AudioInfo> AudioList = new();
} }
/// <summary>
/// 音频系统的静态实例
/// </summary>
public static AudioSystemModel AudioSystem = new(); public static AudioSystemModel AudioSystem = new();
/// <summary> /// <summary>
/// 存储整个剧本的XML文档 /// 存储整个剧本的XML文档
/// </summary> /// </summary>
private XDocument PlotxDoc; private XDocument PlotxDoc;
/// <summary>
/// 剧情数据结构,包含角色信息、分支剧情、主剧情等
/// </summary>
[Serializable] [Serializable]
public class Struct_PlotData public class Struct_PlotData
{ {
public JObject ConfigCharacterInfo = new(); public JObject ConfigCharacterInfo = new(); // 角色配置信息
public JObject ConfigDepartment = new(); public JObject ConfigDepartment = new(); // 部门配置信息
public string Title; public string Title; // 剧情标题
public string Synopsis; public string Synopsis; // 剧情简介
public List<XElement> BranchPlot = new(); public List<XElement> BranchPlot = new(); // 分支剧情列表
public Queue<XElement> BranchPlotInfo = new(); public Queue<XElement> BranchPlotInfo = new(); // 分支剧情信息队列
public Queue<XElement> MainPlot = new(); public Queue<XElement> MainPlot = new(); // 主剧情队列
/// <summary>
/// 选项结构,包含选项标题和跳转ID
/// </summary>
public class Struct_Choice public class Struct_Choice
{ {
public string Title; public string Title;
public string JumpID; public string JumpID;
} }
/// <summary>
/// 角色信息结构,包含角色ID、GameObject、名称、所属部门和来源ID
/// </summary>
public class Struct_CharacterInfo public class Struct_CharacterInfo
{ {
public string CharacterID; public string CharacterID;
@@ -78,8 +117,10 @@ namespace HGF
public string Affiliation; public string Affiliation;
public string FromID; public string FromID;
} }
public List<Struct_CharacterInfo> CharacterInfo = new();
public List<Struct_Choice> ChoiceText = new(); public List<Struct_CharacterInfo> CharacterInfo = new(); // 角色信息列表
public List<Struct_Choice> ChoiceText = new(); // 选项文本列表
/// <summary> /// <summary>
/// 当前的剧情节点 /// 当前的剧情节点
/// </summary> /// </summary>
@@ -89,11 +130,22 @@ namespace HGF
/// 当前是否为分支剧情节点 /// 当前是否为分支剧情节点
/// </summary> /// </summary>
public bool IsBranch = false; public bool IsBranch = false;
public string NowJumpID;
/// <summary>
/// 当前跳转的ID
/// </summary>
public string NowJumpID;
} }
/// <summary>
/// 剧情数据的静态实例
/// </summary>
public static Struct_PlotData PlotData = new(); public static Struct_PlotData PlotData = new();
/// <summary>
/// 开始游戏,初始化剧情数据并加载剧本
/// </summary>
/// <param name="model">游戏启动模型,包含角色信息、部门信息和剧本文本</param>
public void StartGame (HGFStartModel model) public void StartGame (HGFStartModel model)
{ {
PlotData = new Struct_PlotData(); PlotData = new Struct_PlotData();
@@ -103,21 +155,21 @@ namespace HGF
StartCoroutine(LoadPlot(model.plotText)); StartCoroutine(LoadPlot(model.plotText));
return; return;
} }
/// <summary> /// <summary>
/// 解析框架文本 /// 解析框架文本,加载剧本
/// </summary> /// </summary>
/// <returns></returns> /// <param name="plotText">剧本文本内容</param>
/// <returns>协程</returns>
public IEnumerator LoadPlot (string plotText) public IEnumerator LoadPlot (string plotText)
{ {
yield return null; yield return null;
try try
{ {
GameAPI.Print($"游戏剧本:{plotText}"); GameAPI.Print($"游戏剧本:{plotText}");
PlotxDoc = XDocument.Parse(plotText); PlotxDoc = XDocument.Parse(plotText);
//-----开始读取数据 // 开始读取数据
foreach (var item in PlotxDoc.Root.Elements()) foreach (var item in PlotxDoc.Root.Elements())
{ {
switch (item.Name.ToString()) switch (item.Name.ToString())
@@ -149,7 +201,6 @@ namespace HGF
{ {
foreach (var item_name in item.Elements()) foreach (var item_name in item.Elements())
{ {
AudioSystem.AudioList.Add(new AudioSystemModel.AudioInfo AudioSystem.AudioList.Add(new AudioSystemModel.AudioInfo
{ {
name = item_name.Value, name = item_name.Value,
@@ -169,7 +220,6 @@ namespace HGF
default: default:
{ {
throw new Exception("无法识别的根标签"); throw new Exception("无法识别的根标签");
} }
} }
} }
@@ -178,35 +228,34 @@ namespace HGF
{ {
if (ex.Message != "无法识别的根标签") if (ex.Message != "无法识别的根标签")
{ {
GameAPI.Print(ex.Message, "error"); GameAPI.Print(ex.Message, "error");
} }
} }
GameAPI.Print(Newtonsoft.Json.JsonConvert.SerializeObject(PlotData)); GameAPI.Print(Newtonsoft.Json.JsonConvert.SerializeObject(PlotData));
Button_Click_NextPlot(); Button_Click_NextPlot();
} }
/// <summary> /// <summary>
/// 点击屏幕 下一句 /// 点击屏幕,进入下一句剧情
/// </summary> /// </summary>
public void Button_Click_NextPlot () public void Button_Click_NextPlot ()
{ {
if (PlotData.MainPlot.Count == 0) if (PlotData.MainPlot.Count == 0)
{ {
GameAPI.Print("游戏结束!"); GameAPI.Print("游戏结束!");
return; return;
} }
//IsCanJump这里有问题,如果一直点击会为false,而不是说true,这是因为没有点击按钮 ,没有添加按钮 // 如果正在说话或不能跳转,则返回
if (GalManager_Text.IsSpeak || !GalManager_Text.IsCanJump) { return; } if (GalManager_Text.IsSpeak || !GalManager_Text.IsCanJump) { return; }
if (!PlotData.IsBranch) if (!PlotData.IsBranch)
{ {
PlotData.MainPlot.TryDequeue(out PlotData.NowPlotDataNode);//队列出队+内联 出一个temp节点 PlotData.MainPlot.TryDequeue(out PlotData.NowPlotDataNode); // 队列出队,获取当前剧情节点
PlotData.BranchPlotInfo.Clear(); PlotData.BranchPlotInfo.Clear();
} }
else//当前为分支节点 else // 当前为分支节点
{ {
//这块得妥善处理
PlotData.NowPlotDataNode = GetBranchByID(PlotData.NowJumpID); PlotData.NowPlotDataNode = GetBranchByID(PlotData.NowJumpID);
} }
@@ -216,9 +265,11 @@ namespace HGF
GameAPI.Print("无效的剧情结点", "error"); GameAPI.Print("无效的剧情结点", "error");
return; return;
} }
// 根据当前剧情节点的类型进行处理
switch (PlotData.NowPlotDataNode.Name.ToString()) switch (PlotData.NowPlotDataNode.Name.ToString())
{ {
case "AddCharacter"://处理添加角色信息的东西 case "AddCharacter": // 处理添加角色信息
{ {
var _ = new Struct_CharacterInfo(); var _ = new Struct_CharacterInfo();
var _From = PlotData.NowPlotDataNode.Attribute("From").Value; var _From = PlotData.NowPlotDataNode.Attribute("From").Value;
@@ -229,7 +280,7 @@ namespace HGF
_.FromID = _From; _.FromID = _From;
var _CameObj = Resources.Load<GameObject>("HGF/Img-Character"); var _CameObj = Resources.Load<GameObject>("HGF/Img-Character");
//首次添加角色,默认添加Normall立绘 // 首次添加角色,默认添加Normal立绘
_CameObj.GetComponent<Image>().sprite = GetCharacterImg(_From, "Normall"); _CameObj.GetComponent<Image>().sprite = GetCharacterImg(_From, "Normall");
_.CharacterGameObject = Instantiate(_CameObj, Gal_CharacterImg.gameObject.transform); _.CharacterGameObject = Instantiate(_CameObj, Gal_CharacterImg.gameObject.transform);
@@ -244,21 +295,19 @@ namespace HGF
Button_Click_NextPlot(); Button_Click_NextPlot();
break; break;
} }
case "Speak": //处理发言 case "Speak": // 处理发言
{ {
var _nodeinfo = GetCharacterObjectByName(PlotData.NowPlotDataNode.Attribute("CharacterID").Value); var _nodeinfo = GetCharacterObjectByName(PlotData.NowPlotDataNode.Attribute("CharacterID").Value);
if (PlotData.NowPlotDataNode.Elements().Count() != 0) //有选项,因为他有子节点数目了 if (PlotData.NowPlotDataNode.Elements().Count() != 0) // 有选项,因为存在子节点
{ {
GalManager_Text.IsCanJump = false; GalManager_Text.IsCanJump = false;
foreach (var ClildItem in PlotData.NowPlotDataNode.Elements()) foreach (var ClildItem in PlotData.NowPlotDataNode.Elements())
{ {
if (ClildItem.Name.ToString() == "Choice") if (ClildItem.Name.ToString() == "Choice")
PlotData.ChoiceText.Add(new Struct_Choice { Title = ClildItem.Value, JumpID = ClildItem.Attribute("JumpID").Value }); PlotData.ChoiceText.Add(new Struct_Choice { Title = ClildItem.Value, JumpID = ClildItem.Attribute("JumpID").Value });
} }
Gal_Text.StartTextContent(PlotData.NowPlotDataNode.Attribute("Content").Value, _nodeinfo.Name, _nodeinfo.Affiliation, () => Gal_Text.StartTextContent(PlotData.NowPlotDataNode.Attribute("Content").Value, _nodeinfo.Name, _nodeinfo.Affiliation, () =>
{ {
foreach (var ClildItem in GalManager.PlotData.ChoiceText) foreach (var ClildItem in GalManager.PlotData.ChoiceText)
{ {
Gal_Choice.CreatNewChoice(ClildItem.JumpID, ClildItem.Title); Gal_Choice.CreatNewChoice(ClildItem.JumpID, ClildItem.Title);
@@ -267,103 +316,118 @@ namespace HGF
} }
else Gal_Text.StartTextContent(PlotData.NowPlotDataNode.Attribute("Content").Value, _nodeinfo.Name, _nodeinfo.Affiliation); else Gal_Text.StartTextContent(PlotData.NowPlotDataNode.Attribute("Content").Value, _nodeinfo.Name, _nodeinfo.Affiliation);
//处理消息 // 处理消息
if (PlotData.NowPlotDataNode.Attributes("SendMessage").Count() != 0) if (PlotData.NowPlotDataNode.Attributes("SendMessage").Count() != 0)
SendCharMessage(_nodeinfo.CharacterID, PlotData.NowPlotDataNode.Attribute("SendMessage").Value); SendCharMessage(_nodeinfo.CharacterID, PlotData.NowPlotDataNode.Attribute("SendMessage").Value);
if (PlotData.NowPlotDataNode.Attributes("AudioPath").Count() != 0) if (PlotData.NowPlotDataNode.Attributes("AudioPath").Count() != 0)
StartCoroutine(PlayCharacterVoice(AudioSystem.Character_Voice, _nodeinfo.FromID, PlotData.NowPlotDataNode.Attribute("AudioPath").Value)); StartCoroutine(PlayCharacterVoice(AudioSystem.Character_Voice, _nodeinfo.FromID, PlotData.NowPlotDataNode.Attribute("AudioPath").Value));
break; break;
} }
case "ChangeBackImg"://更换背景图片 case "ChangeBackImg": // 更换背景图片
{ {
var _Path = PlotData.NowPlotDataNode.Attribute("Path").Value; var _Path = PlotData.NowPlotDataNode.Attribute("Path").Value;
Gal_BackImg.SetImage(GetBackImg(_Path)); Gal_BackImg.SetImage(GetBackImg(_Path));
Button_Click_NextPlot(); Button_Click_NextPlot();
break; break;
} }
case "DeleteCharacter": case "DeleteCharacter": // 删除角色
{ {
DestroyCharacterByID(PlotData.NowPlotDataNode.Attribute("CharacterID").Value); DestroyCharacterByID(PlotData.NowPlotDataNode.Attribute("CharacterID").Value);
break; break;
} }
case "ChangeCharacterImg": case "ChangeCharacterImg": // 更换角色立绘
{ {
var _CharacterID = PlotData.NowPlotDataNode.Attribute("CharacterID").Value; var _CharacterID = PlotData.NowPlotDataNode.Attribute("CharacterID").Value;
var _obj = GetCharacterObjectByName(_CharacterID); var _obj = GetCharacterObjectByName(_CharacterID);
//Debug.Log(_obj.CharacterGameObject.GetComponent<Image>() is null);
//ResourcesPath
_obj.CharacterGameObject.GetComponent<GalManager_CharacterImg>().SetImage(GetCharacterImg(_obj.FromID, PlotData.NowPlotDataNode.Attribute("KeyName").Value)); _obj.CharacterGameObject.GetComponent<GalManager_CharacterImg>().SetImage(GetCharacterImg(_obj.FromID, PlotData.NowPlotDataNode.Attribute("KeyName").Value));
// _obj.CharacterGameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>($"Texture2D/Menhera/Plot/character/{GameManager.ServerManager.Config.CharacterInfo.GetValue(_obj.FromID, "ResourcePath")}/{GameManager.ServerManager.Config.CharacterInfo.GetValue(_obj.FromID, PlotData.NowPlotDataNode.Attribute("Img").Value)}");
// Debug.Log($"Texture2D/Menhera/Plot/character/{GameManager.ServerManager.Config.CharacterInfo.GetValue(, "ResourcePath")}/{GameManager.ServerManager.Config.CharacterInfo.GetValue(_obj.FromID, PlotData.NowPlotDataNode.Attribute("Img").Value)}");
Button_Click_NextPlot(); Button_Click_NextPlot();
break; break;
} }
case "ChangeBackAudio": case "ChangeBackAudio": // 更换背景音乐
{ {
ChangeBackAudio(AudioSystem.BackMix, AudioSystem.AudioList.Find(e => e.name == PlotData.NowPlotDataNode.Value).path); ChangeBackAudio(AudioSystem.BackMix, AudioSystem.AudioList.Find(e => e.name == PlotData.NowPlotDataNode.Value).path);
Button_Click_NextPlot(); Button_Click_NextPlot();
break; break;
} }
case "ExitGame": case "ExitGame": // 退出游戏
{ {
foreach (var item in PlotData.CharacterInfo)
{
DestroyCharacterByID(item.CharacterID);
}
PlotData.MainPlot.Clear(); PlotData.MainPlot.Clear();
PlotData.BranchPlot.Clear(); PlotData.BranchPlot.Clear();
foreach (var item in PlotData.CharacterInfo)
{
DestroyCharacterByID(item.CharacterID, false);
}
PlotData.CharacterInfo.Clear();
PlotData.IsBranch = false; PlotData.IsBranch = false;
break; break;
} }
} }
if (PlotData.BranchPlotInfo.Count == 0) if (PlotData.BranchPlotInfo.Count == 0)
{ {
PlotData.IsBranch = false; PlotData.IsBranch = false;
} }
return; return;
} }
/// <summary>
/// 进入快速模式
/// </summary>
public void Button_Click_FastMode () public void Button_Click_FastMode ()
{ {
GalManager_Text.IsFastMode = true; GalManager_Text.IsFastMode = true;
return; return;
} }
/// <summary>
/// 根据角色ID获取角色对象
/// </summary>
/// <param name="ID">角色ID</param>
/// <returns>角色信息</returns>
public Struct_CharacterInfo GetCharacterObjectByName (string ID) public Struct_CharacterInfo GetCharacterObjectByName (string ID)
{ {
return PlotData.CharacterInfo.Find(t => t.CharacterID == ID); return PlotData.CharacterInfo.Find(t => t.CharacterID == ID);
} }
/// <summary>
/// 根据分支ID获取分支剧情节点
/// </summary>
/// <param name="ID">分支ID</param>
/// <returns>分支剧情节点</returns>
public XElement GetBranchByID (string ID) public XElement GetBranchByID (string ID)
{ {
if (PlotData.BranchPlotInfo.Count == 0) if (PlotData.BranchPlotInfo.Count == 0)
foreach (var item in PlotData.BranchPlot.Find(t => t.Attribute("ID").Value == ID).Elements()) foreach (var item in PlotData.BranchPlot.Find(t => t.Attribute("ID").Value == ID).Elements())
{ {
PlotData.BranchPlotInfo.Enqueue(item); PlotData.BranchPlotInfo.Enqueue(item);
} }
PlotData.BranchPlotInfo.TryDequeue(out XElement t); PlotData.BranchPlotInfo.TryDequeue(out XElement t);
return t; return t;
} }
/// <summary> /// <summary>
/// 销毁一个角色 /// 销毁指定ID的角色
/// </summary> /// </summary>
/// <param name="ID"></param> /// <param name="ID">角色ID</param>
public void DestroyCharacterByID (string ID) public void DestroyCharacterByID (string ID, bool removeCharacterInfo = true)
{ {
var _ = PlotData.CharacterInfo.Find(t => t.CharacterID == ID); var _ = PlotData.CharacterInfo.Find(t => t.CharacterID == ID);
SendCharMessage(ID, "Quit"); SendCharMessage(ID, "Quit");
PlotData.CharacterInfo.Remove(_); if (removeCharacterInfo)
PlotData.CharacterInfo.Remove(_);
} }
/// <summary>
/// 发送角色消息
/// </summary>
/// <param name="CharacterID">角色ID</param>
/// <param name="Message">消息内容</param>
public void SendCharMessage (string CharacterID, string Message) public void SendCharMessage (string CharacterID, string Message)
{ {
var _t = GetCharacterObjectByName(CharacterID); var _t = GetCharacterObjectByName(CharacterID);
_t.CharacterGameObject.GetComponent<GalManager_CharacterMessage>().HandleMessage(Message); _t.CharacterGameObject.GetComponent<GalManager_CharacterMessage>().HandleMessage(Message);
} }
/// <summary> /// <summary>
/// 初始化音乐系统 /// 初始化音乐系统
/// </summary> /// </summary>
@@ -374,34 +438,38 @@ namespace HGF
AudioSystem.TextMix = GameObject.Find("AudioSystem/TextMix").GetComponent<AudioSource>(); AudioSystem.TextMix = GameObject.Find("AudioSystem/TextMix").GetComponent<AudioSource>();
} }
/// <summary>
/// 每帧更新角色数量
/// </summary>
private void FixedUpdate () private void FixedUpdate ()
{ {
CharacterNum = PlotData.CharacterInfo.Count; CharacterNum = PlotData.CharacterInfo.Count;
} }
private void Update () private void Update ()
{ {
} }
#region 建议自己实现的部分 #region 建议自己实现的部分
/// <summary> /// <summary>
/// 根据角色ID获取角色立绘,建议自己重新实现。 /// 根据角色ID和立绘名称获取角色立绘
/// </summary> /// </summary>
/// <returns></returns> /// <param name="id">角色ID</param>
/// <param name="imgName">立绘名称</param>
/// <returns>角色立绘</returns>
private Sprite GetCharacterImg (string id, string imgName) private Sprite GetCharacterImg (string id, string imgName)
{ {
var _path = $"HGF/img/portrait/{id}/{PlotData.ConfigCharacterInfo[id]["Portraits"][imgName]}"; var _path = $"HGF/img/portrait/{id}/{PlotData.ConfigCharacterInfo[id]["Portraits"][imgName]}";
Debug.Log(_path); Debug.Log(_path);
return Resources.Load<Sprite>(_path); return Resources.Load<Sprite>(_path);
} }
/// <summary> /// <summary>
/// 获取背景图片,建议自己重新实现。 /// 获取背景图片
/// </summary> /// </summary>
/// <param name="path"></param> /// <param name="path">背景图片路径</param>
/// <returns></returns> /// <returns>背景图片</returns>
private Sprite GetBackImg (string path) private Sprite GetBackImg (string path)
{ {
Debug.Log($"HGF/img/back/{path}"); Debug.Log($"HGF/img/back/{path}");
@@ -409,27 +477,29 @@ namespace HGF
} }
/// <summary> /// <summary>
/// 播放语音,建议自己实现指定文件夹路径 /// 播放角色语音
/// </summary> /// </summary>
/// <param name="audioSource"></param> /// <param name="audioSource">音频源</param>
/// <param name="fileName"></param> /// <param name="id">角色ID</param>
/// <returns></returns> /// <param name="fileName">音频文件名</param>
/// <returns>协程</returns>
private IEnumerator PlayCharacterVoice (AudioSource audioSource, string id, string fileName) private IEnumerator PlayCharacterVoice (AudioSource audioSource, string id, string fileName)
{ {
yield return null;//下一帧执行 yield return null; // 下一帧执行
var _clip = Resources.Load<AudioClip>($"HGF/audio/{id}/{fileName}"); var _clip = Resources.Load<AudioClip>($"HGF/audio/{id}/{fileName}");
audioSource.clip = _clip; audioSource.clip = _clip;
audioSource.Play(); audioSource.Play();
//或者
/*
* audioSource.PlayOneShot(_clip);
*
*/
} }
/// <summary>
/// 更换背景音乐
/// </summary>
/// <param name="audioSource">音频源</param>
/// <param name="path">背景音乐路径</param>
/// <returns>协程</returns>
public IEnumerator ChangeBackAudio (AudioSource audioSource, string path) public IEnumerator ChangeBackAudio (AudioSource audioSource, string path)
{ {
yield return null;//下一帧执行 yield return null; // 下一帧执行
var _clip = Resources.Load<AudioClip>($"HGF/audio/{path}"); var _clip = Resources.Load<AudioClip>($"HGF/audio/{path}");
audioSource.clip = _clip; audioSource.clip = _clip;
audioSource.Play(); audioSource.Play();
@@ -5,37 +5,63 @@ using UnityEngine.UI;
namespace HGF namespace HGF
{ {
/// <summary>
/// 角色动画管理器,用于处理角色的入场、出场和即时动画
/// </summary>
public class GalManager_CharacterAnimate : MonoBehaviour public class GalManager_CharacterAnimate : MonoBehaviour
{ {
/// <summary> /// <summary>
/// 出入场出场动画 /// 出入场动画类型
/// <para>ToShow:逐渐显示</para>
/// <para>Outside-ToLeft:从屏幕左侧滑入</para>
/// <para>Outside-ToRight:从屏幕右侧滑入</para>
/// </summary> /// </summary>
[StringInList("ToShow", "Outside-ToLeft", "Outside-ToRight")] public string Animate_StartOrOutside = "ToShow"; [StringInList("ToShow", "Outside-ToLeft", "Outside-ToRight")]
public string Animate_StartOrOutside = "ToShow";
/// <summary> /// <summary>
/// 动画 /// 即时动画类型
/// <para>Shake:颤抖</para> /// <para>Shake:颤抖</para>
/// <para>Shake-Y-Once:向下抖动一次</para> /// <para>Shake-Y-Once:向下抖动一次</para>
/// <para>ToGrey:变灰</para> /// <para>ToLeft:移动到左侧</para>
/// <para>To - :不解释了,移动到指定位置</para> /// <para>ToCenter:移动到中间</para>
/// <para>ToRight:移动到右侧</para>
/// </summary> /// </summary>
[StringInList("Shake", "Shake-Y-Once", "ToLeft", "ToCenter", "ToRight")] public string Animate_type = "Shake"; [StringInList("Shake", "Shake-Y-Once", "ToLeft", "ToCenter", "ToRight")]
public string Animate_type = "Shake";
/// <summary> /// <summary>
/// 角色立绘 /// 角色立绘
/// </summary> /// </summary>
private Image CharacterImg; private Image CharacterImg;
/// <summary>
/// 主画布,注意主画布的名称必须是MainCanvas
/// </summary>
[Title("注意,主画布的名称必须是MainCanvas")] [Title("注意,主画布的名称必须是MainCanvas")]
public Canvas MainCanvas; public Canvas MainCanvas;
/// <summary>
/// 初始化,获取角色立绘和主画布
/// </summary>
private void Awake () private void Awake ()
{ {
CharacterImg = gameObject.GetComponent<Image>(); CharacterImg = gameObject.GetComponent<Image>();
if (MainCanvas == null) MainCanvas = GameObject.Find("MainCanvas").GetComponent<Canvas>(); if (MainCanvas == null) MainCanvas = GameObject.Find("MainCanvas").GetComponent<Canvas>();
} }
/// <summary>
/// 重新执行入场动画
/// </summary>
[Button(nameof(Start), "重新执行入场动画")] [Button(nameof(Start), "重新执行入场动画")]
private void Start () private void Start ()
{ {
HandleInOrOutsideMessgae(Animate_StartOrOutside); HandleInOrOutsideMessgae(Animate_StartOrOutside);
} }
/// <summary>
/// 处理即时动画消息
/// </summary>
[Button(nameof(Start), "重新执行及时动画")] [Button(nameof(Start), "重新执行及时动画")]
public void HandleMessgae () public void HandleMessgae ()
{ {
@@ -85,34 +111,31 @@ namespace HGF
} }
} }
} }
/// <summary> /// <summary>
/// 处理出场动画消息 /// 处理出场动画消息
/// </summary> /// </summary>
/// <param name="Messgae"></param> /// <param name="Messgae">动画消息类型</param>
public void HandleInOrOutsideMessgae (string Messgae) public void HandleInOrOutsideMessgae (string Messgae)
{ {
CharacterImg.color = new Color32(255, 255, 255, 0); // 完全透明
CharacterImg.color = new Color32(255, 255, 255, 0);//完全透明
var rect = gameObject.GetComponent<RectTransform>(); var rect = gameObject.GetComponent<RectTransform>();
switch (Messgae) switch (Messgae)
{ {
// 逐渐显示
//逐渐显示
case "ToShow": case "ToShow":
{ {
PositionImageOutside(gameObject.GetComponent<RectTransform>(), 0); PositionImageOutside(gameObject.GetComponent<RectTransform>(), 0);
break; break;
} }
//从屏幕边缘滑到左侧 // 从屏幕左侧滑入
case "Outside-ToLeft": case "Outside-ToLeft":
{ {
PositionImageOutside(gameObject.GetComponent<RectTransform>(), -1); PositionImageOutside(gameObject.GetComponent<RectTransform>(), -1);
DOTween.To(() => rect.anchoredPosition, x => rect.GetComponent<RectTransform>().anchoredPosition = x, new Vector2(rect.anchoredPosition.x + CharacterImg.sprite.texture.width, rect.anchoredPosition.y), 1f); DOTween.To(() => rect.anchoredPosition, x => rect.GetComponent<RectTransform>().anchoredPosition = x, new Vector2(rect.anchoredPosition.x + CharacterImg.sprite.texture.width, rect.anchoredPosition.y), 1f);
break; break;
} }
//从屏幕边缘滑到右侧 // 从屏幕右侧滑入
case "Outside-ToRight": case "Outside-ToRight":
{ {
PositionImageOutside(gameObject.GetComponent<RectTransform>(), 1); PositionImageOutside(gameObject.GetComponent<RectTransform>(), 1);
@@ -124,21 +147,18 @@ namespace HGF
GameAPI.Print("当前剧情文本受损,请重新安装游戏尝试", "error"); GameAPI.Print("当前剧情文本受损,请重新安装游戏尝试", "error");
break; break;
} }
}
//都需要指定的
{
CharacterImg.DOFade(1, 0.7f);
} }
// 都需要指定的
CharacterImg.DOFade(1, 0.7f);
} }
/// <summary> /// <summary>
/// 设置image的位置到屏幕之外 /// 设置Image的位置到屏幕之外
/// </summary> /// </summary>
/// <param name="ImageGameObject"></param> /// <param name="ImageGameObject">Image的RectTransform</param>
/// <param name="Position">-1:左侧 0:中间 1:右侧</param> /// <param name="Position">位置类型:-1:左侧 0:中间 1:右侧</param>
private void PositionImageOutside (RectTransform ImageGameObject, int Position) private void PositionImageOutside (RectTransform ImageGameObject, int Position)
{ {
// 获取Image的Rect Transform
switch (Position) switch (Position)
{ {
case -1: case -1:
@@ -153,26 +173,23 @@ namespace HGF
default: break; default: break;
} }
} }
/// <summary> /// <summary>
/// 获取image的位置到屏幕之内的位置 /// 获取Image的位置到屏幕之内的位置
/// </summary> /// </summary>
/// <param name="ImageGameObject"></param> /// <param name="ImageGameObject">Image的RectTransform</param>
/// <param name="Position">-1:左侧 0:中间 1:右侧</param> /// <param name="Position">位置类型:-1:左侧 0:中间 1:右侧</param>
/// <returns>目标位置</returns>
private Vector2 PositionImageInside (RectTransform ImageGameObject, int Position) private Vector2 PositionImageInside (RectTransform ImageGameObject, int Position)
{ {
// 获取Image的Rect Transform
switch (Position) switch (Position)
{ {
case -1: case -1:
return new Vector2((-MainCanvas.GetComponent<RectTransform>().sizeDelta.x / 2) + (ImageGameObject.gameObject.GetComponent<Image>().sprite.texture.width / 2), ImageGameObject.anchoredPosition.y); return new Vector2((-MainCanvas.GetComponent<RectTransform>().sizeDelta.x / 2) + (ImageGameObject.gameObject.GetComponent<Image>().sprite.texture.width / 2), ImageGameObject.anchoredPosition.y);
case 1: case 1:
return new Vector2((MainCanvas.GetComponent<RectTransform>().sizeDelta.x / 2) - (ImageGameObject.gameObject.GetComponent<Image>().sprite.texture.width / 2), ImageGameObject.anchoredPosition.y); return new Vector2((MainCanvas.GetComponent<RectTransform>().sizeDelta.x / 2) - (ImageGameObject.gameObject.GetComponent<Image>().sprite.texture.width / 2), ImageGameObject.anchoredPosition.y);
case 0: case 0:
return new Vector2(0, ImageGameObject.anchoredPosition.y); return new Vector2(0, ImageGameObject.anchoredPosition.y);
default: default:
{ {
GameAPI.Print("当前剧情文本受损,请重新安装游戏尝试", "error"); GameAPI.Print("当前剧情文本受损,请重新安装游戏尝试", "error");
@@ -181,5 +198,4 @@ namespace HGF
} }
} }
} }
}
}
@@ -1,125 +1,92 @@
using System; using System;
using UnityEngine; using UnityEngine;
#if UNITY_EDITOR #if UNITY_EDITOR
using UnityEditor; using UnityEditor;
#endif #endif
namespace HGF namespace HGF
{ {
/// <summary>
/// 字符串列表属性特性,用于在Inspector中显示一个下拉列表
/// </summary>
public class StringInList : PropertyAttribute public class StringInList : PropertyAttribute
{ {
/// <summary>
/// 获取字符串列表的委托
/// </summary>
public delegate string[] GetStringList (); public delegate string[] GetStringList ();
/// <summary>
/// 使用指定的字符串列表初始化特性
/// </summary>
/// <param name="list">字符串列表</param>
public StringInList (params string[] list) public StringInList (params string[] list)
{ {
List = list; List = list;
} }
/// <summary>
/// 使用指定类型的方法来获取字符串列表初始化特性
/// </summary>
/// <param name="type">包含方法的类型</param>
/// <param name="methodName">方法名称</param>
public StringInList (Type type, string methodName) public StringInList (Type type, string methodName)
{ {
var method = type.GetMethod(methodName); var method = type.GetMethod(methodName);
if (method != null) if (method != null)
{ {
List = method.Invoke(null, null) as string[]; List = method.Invoke(null, null) as string[];
} }
else else
{ {
Debug.LogError("NO SUCH METHOD " + methodName + " FOR " + type); Debug.LogError("NO SUCH METHOD " + methodName + " FOR " + type);
} }
} }
/// <summary>
/// 获取字符串列表
/// </summary>
public string[] List public string[] List
{ {
get; get;
private set; private set;
} }
} }
#if UNITY_EDITOR #if UNITY_EDITOR
/// <summary>
/// 字符串列表属性绘制器,用于在Inspector中绘制下拉列表
/// </summary>
[CustomPropertyDrawer(typeof(StringInList))] [CustomPropertyDrawer(typeof(StringInList))]
public class StringInListDrawer : PropertyDrawer public class StringInListDrawer : PropertyDrawer
{ {
/// <summary>
// Draw the property inside the given rect /// 在Inspector中绘制属性
/// </summary>
/// <param name="position">绘制位置</param>
/// <param name="property">序列化属性</param>
/// <param name="label">属性标签</param>
public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) public override void OnGUI (Rect position, SerializedProperty property, GUIContent label)
{ {
var stringInList = attribute as StringInList; var stringInList = attribute as StringInList;
var list = stringInList.List; var list = stringInList.List;
if (property.propertyType == SerializedPropertyType.String) if (property.propertyType == SerializedPropertyType.String)
{ {
int index = Mathf.Max(0, Array.IndexOf(list, property.stringValue)); int index = Mathf.Max(0, Array.IndexOf(list, property.stringValue));
index = EditorGUI.Popup(position, property.displayName, index, list); index = EditorGUI.Popup(position, property.displayName, index, list);
property.stringValue = list[index]; property.stringValue = list[index];
} }
else if (property.propertyType == SerializedPropertyType.Integer) else if (property.propertyType == SerializedPropertyType.Integer)
{ {
property.intValue = EditorGUI.Popup(position, property.displayName, property.intValue, list); property.intValue = EditorGUI.Popup(position, property.displayName, property.intValue, list);
} }
else else
{ {
base.OnGUI(position, property, label); base.OnGUI(position, property, label);
} }
} }
} }
#endif #endif
}
}
@@ -785,7 +785,8 @@ PlayerSettings:
scriptingDefineSymbols: {} scriptingDefineSymbols: {}
additionalCompilerArguments: {} additionalCompilerArguments: {}
platformArchitecture: {} platformArchitecture: {}
scriptingBackend: {} scriptingBackend:
Standalone: 1
il2cppCompilerConfiguration: {} il2cppCompilerConfiguration: {}
managedStrippingLevel: managedStrippingLevel:
EmbeddedLinux: 1 EmbeddedLinux: 1