This commit is contained in:
zhangzheng
2026-03-13 17:39:35 +08:00
20 changed files with 346 additions and 142 deletions

View File

@@ -0,0 +1,12 @@
# Changelog
此包的所有更新日志会被记录在此文件中
## [1.1.3] - 2026-01-12
### Added
- 添加背景音乐缓出接口
### Fixed
- 修复背景音乐播放时不循环的问题
## [1.1.2] - 2026-01-09
### Fixed
- 修复背景音乐无法播放的问题

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a22131ad87896114c900d929c8588c8b
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -22,8 +22,8 @@ namespace Stary.Evo.AudioCore
poolObject = new GameObject(GetType().Name); poolObject = new GameObject(GetType().Name);
} }
audioSource1 = CreatAudioSource("audioSource1", out AudioSource source1); CreatAudioSource("audioSource1", out audioSource1);
audioSource2 = CreatAudioSource("audioSource2", out AudioSource source2); CreatAudioSource("audioSource2", out audioSource2);
} }
/// <summary> /// <summary>
@@ -41,7 +41,7 @@ namespace Stary.Evo.AudioCore
audioData = Initialize(audioData); audioData = Initialize(audioData);
if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.packageName)) if (!string.IsNullOrEmpty(audioData.packageName) && !string.IsNullOrEmpty(audioData.assetName))
{ {
var clip = await Resources.LoadAssetAsync<AudioClip>(audioData.packageName, audioData.assetName); var clip = await Resources.LoadAssetAsync<AudioClip>(audioData.packageName, audioData.assetName);
if (clip == null) if (clip == null)
@@ -60,10 +60,11 @@ namespace Stary.Evo.AudioCore
return; return;
} }
if (audioSource1 == null) if (audioSource1 != null && audioSource1.isPlaying == false)
{ {
audioSource1.clip = audioData.clip; audioSource1.clip = audioData.clip;
audioSource1.volume = audioData.volume; audioSource1.volume = audioData.volume;
audioSource1.loop = true;
// 设置2D与3D音频 // 设置2D与3D音频
if (audioData.is3DAudio) if (audioData.is3DAudio)
@@ -93,45 +94,43 @@ namespace Stary.Evo.AudioCore
currentAudioSource.Play(); currentAudioSource.Play();
FadeMusic(audioSource1, audioData.fadeDuration, audioSource2); FadeMusic(audioSource1, audioData.fadeDuration, audioSource2);
} }
else else if (audioSource2 != null && audioSource2.isPlaying == false)
{ {
if (audioSource2 == null) audioSource2.clip = audioData.clip;
{ audioSource2.volume = audioData.volume;
audioSource2.clip = audioData.clip; audioSource2.loop = true;
audioSource2.volume = audioData.volume;
// 设置2D与3D音频 // 设置2D与3D音频
if (audioData.is3DAudio) if (audioData.is3DAudio)
{
audioSource2.transform.position = audioData.audio3DPosition;
audioSource2.spatialBlend = 1;
audioSource2.minDistance = 1f;
if (audioData.audio3DMaxDistance != 0)
{ {
audioSource2.transform.position = audioData.audio3DPosition; audioSource2.maxDistance = audioData.audio3DMaxDistance;
audioSource2.spatialBlend = 1;
audioSource2.minDistance = 1f;
if (audioData.audio3DMaxDistance != 0)
{
audioSource2.maxDistance = audioData.audio3DMaxDistance;
}
else
{
// 默认3D最大距离为3米
audioSource2.maxDistance = 3f;
}
} }
else else
{ {
audioSource2.transform.position = Vector3.zero; // 默认3D最大距离为3米
audioSource2.spatialBlend = 0; audioSource2.maxDistance = 3f;
audioSource2.minDistance = 1f;
audioSource2.maxDistance = 500f;
} }
currentAudioSource = audioSource2;
currentAudioSource.Play();
FadeMusic(audioSource2, audioData.fadeDuration, audioSource1);
} }
else else
{ {
Debug.LogWarning("UnityEvo:已同时存在两个背景乐在切换"); audioSource2.transform.position = Vector3.zero;
audioSource2.spatialBlend = 0;
audioSource2.minDistance = 1f;
audioSource2.maxDistance = 500f;
} }
currentAudioSource = audioSource2;
currentAudioSource.Play();
FadeMusic(audioSource2, audioData.fadeDuration, audioSource1);
}
else
{
Debug.LogWarning("UnityEvo:已同时存在两个背景乐在切换");
} }
} }
@@ -142,7 +141,7 @@ namespace Stary.Evo.AudioCore
public override void StopAll() public override void StopAll()
{ {
FadeAllMusic(); FadeAllMusic(0);
} }
public override AudioSource GetAudioSource() public override AudioSource GetAudioSource()
@@ -156,7 +155,7 @@ namespace Stary.Evo.AudioCore
/// <param name="audioData">{[fadeDuration:自然过渡时间]}</param> /// <param name="audioData">{[fadeDuration:自然过渡时间]}</param>
public override void Stop() public override void Stop()
{ {
FadeAllMusic(); FadeAllMusic(0f);
} }
@@ -202,31 +201,28 @@ namespace Stary.Evo.AudioCore
FadeOutMusic(source2, fadeDuration); FadeOutMusic(source2, fadeDuration);
} }
public void FadeAllMusic(float fadeDuration)
private void FadeAllMusic()
{ {
currentAudioSource = null; currentAudioSource = null;
FadeOutMusic(audioSource1, fadeDuration);
audioSource1.Stop(); FadeOutMusic(audioSource2, fadeDuration);
audioSource2.Stop();
} }
/// <summary> /// <summary>
/// 创建一个新的AudioSource对象 /// 创建一个新的AudioSource对象
/// </summary> /// </summary>
/// <param name="obj"></param> /// <param name="obj"></param>
private AudioSource CreatAudioSource(string name, out AudioSource source) private void CreatAudioSource(string name, out AudioSource source)
{ {
source = new GameObject(name).AddComponent<AudioSource>(); source = new GameObject(name).AddComponent<AudioSource>();
source.gameObject.transform.SetParent(poolObject.transform); source.gameObject.transform.SetParent(poolObject.transform);
source.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象 source.transform.SetParent(poolObject.transform); // 将新对象作为当前对象的子对象
source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放 source.playOnAwake = false; // 添加 AudioSource 组件并禁用自动播放
return source;
} }
public void Dispose() public void Dispose()
{ {
FadeAllMusic(); FadeAllMusic(0f);
Object.Destroy(audioSource1.gameObject); Object.Destroy(audioSource1.gameObject);
Object.Destroy(audioSource2.gameObject); Object.Destroy(audioSource2.gameObject);
audioSource1 = null; audioSource1 = null;

View File

@@ -168,8 +168,7 @@ namespace Stary.Evo.AudioCore
/// <summary> /// <summary>
/// 停止播放背景音乐 /// 停止播放背景音乐
/// </summary> /// </summary>
/// <param name="fadeDuration">自然过渡时间</param> public static void StopMusic()
public static void StopMusic(float fadeDuration = 1f)
{ {
if (Music == null) if (Music == null)
{ {
@@ -180,6 +179,21 @@ namespace Stary.Evo.AudioCore
Music.Stop(); Music.Stop();
} }
/// <summary>
/// 停止播放背景音乐
/// </summary>
/// <param name="fadeDuration">自然过渡时间</param>
public static void FadeAllMusic(float fadeDuration = 1)
{
if (Music == null)
{
Debug.LogError("AudioCoreManager: Music is null, please initialize it first.");
return;
}
Music.FadeAllMusic(fadeDuration);
}
#endregion #endregion
/// <summary> /// <summary>

View File

@@ -1,6 +1,6 @@
{ {
"name": "com.staryevo.audiocore", "name": "com.staryevo.audiocore",
"version": "1.1.1", "version": "1.1.3",
"displayName": "04.AudioCore", "displayName": "04.AudioCore",
"description": "音频播放工具", "description": "音频播放工具",
"unity": "2021.3", "unity": "2021.3",

View File

@@ -1,6 +1,22 @@
# Changelog # Changelog
此包的所有更新日志会被记录在此文件中 此包的所有更新日志会被记录在此文件中
## [1.1.0] - 2026-01-08
### Added
- 新增剧本设置窗口,在窗口中打开和导出剧本
### Fixed
- 修改Graph创建时的默认位置防止热更分包导致脚本丢失报错
- 修改Graph导出时对加载器的加载逻辑解决跨包无法加载的问题
## [1.0.7] - 2026-01-08
### Fixed
- 处理IResource多程序集共存产生的无法选择加载器问题
## [1.0.6] - 2026-01-08
### Fixed
- 处理Sample无法下载的问题
- 处理Graph选择加载器时指定程序集后不产生选项的问题
## [1.0.5] - 2026-01-06 ## [1.0.5] - 2026-01-06
### Changed ### Changed
- 添加更新日志 - 添加更新日志

View File

@@ -28,7 +28,12 @@ namespace Stary.Evo.StoryEditor.Editor
private void OnEnable() private void OnEnable()
{ {
minSize = maxSize = new Vector2(300, 200); minSize = maxSize = new Vector2(300, 200);
_options = GetPackages();
// 记录Package地址并返回选项
var packages = GraphEditorTools.GetPackages();
_paths.Clear();
packages.ForEach(path => _paths.Add(Path.GetFileName(path), path));
_options = _paths.Keys.ToArray();
} }
private void OnGUI() private void OnGUI()
@@ -39,9 +44,7 @@ namespace Stary.Evo.StoryEditor.Editor
EditorGUILayout.BeginVertical(); EditorGUILayout.BeginVertical();
// Package选项 // Package选项
EditorGUILayout.LabelField( "请选择剧本所在的Package" , EditorStyles.boldLabel ) ; _selectedIndex = GraphEditorTools.Popup("请选择剧本所在的Package", _selectedIndex, _options);
var newIndex = EditorGUILayout.Popup( _selectedIndex , _options ) ;
_selectedIndex = newIndex;
GUILayout.Space(15); GUILayout.Space(15);
@@ -69,7 +72,7 @@ namespace Stary.Evo.StoryEditor.Editor
{ {
try try
{ {
CreateScriptGraph(_options[newIndex]); CreateScriptGraph(_options[_selectedIndex]);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -82,68 +85,6 @@ namespace Stary.Evo.StoryEditor.Editor
EditorGUILayout.EndHorizontal(); EditorGUILayout.EndHorizontal();
} }
/// <summary>
/// 获取所有Module Package
/// </summary>
private string[] GetPackages()
{
// 查找Modules目录
List<string> modules = new();
GetDirectoryPaths(Application.dataPath, modules, "Modules");
if (modules.Count == 0)
{
Debug.LogError("未找到任何Modules目录");
return Array.Empty<string>();
}
// 查找package
List<string> packages = new();
GetDirectoryPaths(modules[0], packages, "com.");
if (packages.Count == 0)
{
Debug.LogError("未找到任何Package");
return Array.Empty<string>();
}
// 记录Package地址并返回选项
_paths.Clear();
packages.ForEach(path => _paths.Add(Path.GetFileName(path), path));
return _paths.Keys.ToArray();
}
/// <summary>
/// 获取符合条件的目录
/// </summary>
/// <param name="root">查找起始目录</param>
/// <param name="result">查找结果</param>
/// <param name="title">筛选条件title</param>
/// <param name="tail">筛选条件tail</param>
private static void GetDirectoryPaths(string root, List<string> result, string title = null, string tail = null)
{
foreach (var dir in Directory.GetDirectories(root))
{
// ReSharper disable once ReplaceWithSingleAssignment.True
var check = true;
// 匹配文件头
if (!string.IsNullOrEmpty(title) && !Path.GetFileName(dir).StartsWith(title))
{
check = false;
}
// 匹配文件尾
if (!string.IsNullOrEmpty(tail) && !Path.GetFileName(dir).EndsWith(tail))
{
check = false;
}
if(check)
result.Add(dir.Replace('\\', '/'));
// 继续往下找
GetDirectoryPaths(dir, result, title);
}
}
/// <summary> /// <summary>
/// 创建剧本 /// 创建剧本
/// </summary> /// </summary>
@@ -161,14 +102,15 @@ namespace Stary.Evo.StoryEditor.Editor
if (_paths.TryGetValue(packageID, out var path)) if (_paths.TryGetValue(packageID, out var path))
{ {
// 包体目录排空 // 包体目录排空
var graphDir = Path.Combine(path, "Main","Res","Graphs"); var graphDir = Path.Combine(Application.dataPath, "StoryEditor", "Graphs",
$"{(string.IsNullOrEmpty(packageID) ? "default" : packageID)}");
if (!Directory.Exists(graphDir)) if (!Directory.Exists(graphDir))
{
Directory.CreateDirectory(graphDir); Directory.CreateDirectory(graphDir);
}
// 检查资源存在性 // 检查资源存在性
var graphPath = Path.Combine(graphDir, $"{_scriptName}.asset").Replace(Application.dataPath, "").Replace('\\', '/'); var graphFilePath = Path.Combine(graphDir.Replace(Application.dataPath,"Assets"), $"{_scriptName}.asset");
graphPath = graphPath[1..];
var graphFilePath = Path.Combine("Assets", graphPath);
var existAsset = AssetDatabase.LoadAssetAtPath<ScriptGraph>(graphFilePath); var existAsset = AssetDatabase.LoadAssetAtPath<ScriptGraph>(graphFilePath);
if (existAsset) if (existAsset)
{ {
@@ -178,6 +120,8 @@ namespace Stary.Evo.StoryEditor.Editor
} }
// 创建剧本图表 // 创建剧本图表
var graphPath = Path.Combine(path, "Main","Res","Graphs", $"{_scriptName}.sg.json").Replace(Application.dataPath, "").Replace('\\', '/');
graphPath = graphPath[1..];
var graph = CreateInstance<ScriptGraph>(); var graph = CreateInstance<ScriptGraph>();
graph.packageID = packageID; graph.packageID = packageID;
graph.graphPath = graphPath; graph.graphPath = graphPath;

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
namespace Stary.Evo.StoryEditor.Editor
{
public static class GraphEditorTools
{
public static int Popup(string content, int currentIndex, string[] options)
{
EditorGUILayout.LabelField( "请选择剧本所在的Package" , EditorStyles.boldLabel ) ;
return EditorGUILayout.Popup( currentIndex , options ) ;
}
/// <summary>
/// 获取所有Module Package
/// </summary>
public static List<string> GetPackages()
{
// 查找Modules目录
List<string> modules = new();
GetDirectoryPaths(Application.dataPath, modules, "Modules");
if (modules.Count == 0)
{
Debug.LogError("未找到任何Modules目录");
return new();
}
// 查找package
List<string> packages = new();
GetDirectoryPaths(modules[0], packages, "com.");
if (packages.Count == 0)
{
Debug.LogError("未找到任何Package");
return new();
}
return packages;
}
/// <summary>
/// 获取符合条件的目录
/// </summary>
/// <param name="root">查找起始目录</param>
/// <param name="result">查找结果</param>
/// <param name="title">筛选条件title</param>
/// <param name="tail">筛选条件tail</param>
private static void GetDirectoryPaths(string root, List<string> result, string title = null, string tail = null)
{
foreach (var dir in Directory.GetDirectories(root))
{
// ReSharper disable once ReplaceWithSingleAssignment.True
var check = true;
// 匹配文件头
if (!string.IsNullOrEmpty(title) && !Path.GetFileName(dir).StartsWith(title))
{
check = false;
}
// 匹配文件尾
if (!string.IsNullOrEmpty(tail) && !Path.GetFileName(dir).EndsWith(tail))
{
check = false;
}
if(check)
result.Add(dir.Replace('\\', '/'));
// 继续往下找
GetDirectoryPaths(dir, result, title);
}
}
public static IEnumerable<string> GetAllAssemblyNames() =>
AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).OrderBy(n => n);
/// <summary>
/// 获取继承 IResource 的所有类
/// </summary>
public static HashSet<string> IResourceTypes(string assembly)
{
if (string.IsNullOrEmpty(assembly))
return new();
var asm = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == assembly);
return asm == null ? new() : asm.GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Any(i => i.Name == nameof(IResource))).Select(t => t.Name).ToHashSet();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7264316efc98e9e47b55b6dca12b08d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using XNodeEditor;
namespace Stary.Evo.StoryEditor.Editor
{
public class GraphExportWindow : EditorWindow
{
private string[] _options = Array.Empty<string>();
private Dictionary<string, string> _paths = new();
private int _selectedIndex;
private int _selectedStoryIndex;
private ScriptGraph _selectedStory;
private int _selectedAssemblyIndex;
private int _selectedLoaderIndex;
[MenuItem("Evo/剧本编辑器/打开剧本")]
private static void Open()
{
// 打开一个浮动窗口
GetWindow<GraphExportWindow>( "剧本配置" ) ;
}
private void OnEnable()
{
minSize = maxSize = new Vector2(300, 400);
// 记录Package地址并返回选项
var packages = GraphEditorTools.GetPackages();
_paths.Clear();
packages.ForEach(path => _paths.Add(Path.GetFileName(path), path));
_options = _paths.Keys.ToArray();
}
private void OnGUI()
{
GUILayout.Space(15);
EditorGUILayout.BeginHorizontal();
GUILayout.Space(10);
EditorGUILayout.BeginVertical();
// Package选项
_selectedIndex = GraphEditorTools.Popup("请选择剧本所在的Package", _selectedIndex, _options);
GUILayout.Space(15);
// 显示已有剧本
try
{
string[] storys;
var packageID = _options[_selectedIndex];
var graphDir = Path.Combine(Application.dataPath, "StoryEditor", "Graphs",
$"{(string.IsNullOrEmpty(packageID) ? "default" : packageID)}");
if (!Directory.Exists(graphDir))
{
storys = Array.Empty<string>();
}
else
{
// 选择剧本
var guids = AssetDatabase.FindAssets($"t:{nameof(ScriptGraph)}");
var allAssets = guids.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<ScriptGraph>)
.ToArray();
storys = allAssets.Select(asset => asset.name).ToArray();
_selectedStoryIndex = GraphEditorTools.Popup("请选择剧本:", _selectedStoryIndex, storys);
_selectedStory = allAssets[_selectedStoryIndex];
GUILayout.Space(15);
// 打开剧本按钮
if (GUILayout.Button("打开剧本"))
{
var win = GetWindow<NodeEditorWindow> (false, _selectedStory.name);
win.graph = _selectedStory;
}
GUILayout.Space(15);
// 选择程序集
var assemblyNames = GraphEditorTools.GetAllAssemblyNames().ToArray();
_selectedAssemblyIndex = GraphEditorTools.Popup("请选择加载器所在的程序集:", _selectedAssemblyIndex, assemblyNames);
_selectedStory.assembly = assemblyNames.Length > 0 ? assemblyNames[_selectedAssemblyIndex] : null;
GUILayout.Space(15);
// 选择加载器
var loaders = GraphEditorTools.IResourceTypes(_selectedStory.assembly).ToArray();
_selectedLoaderIndex = GraphEditorTools.Popup("请选择加载器:", _selectedLoaderIndex, loaders);
_selectedStory.loaderType = loaders.Length > 0 ? loaders[_selectedLoaderIndex] : null;
GUILayout.Space(15);
// 导出剧本按钮
if (GUILayout.Button("导出剧本"))
{
_selectedStory.Export();
}
}
}
catch (Exception e)
{
Debug.LogException(e);
}
EditorGUILayout.EndVertical();
GUILayout.Space(10);
EditorGUILayout.EndHorizontal();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba732ba5b1117f549b7d0f8cb6f88449
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -2,11 +2,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using Sirenix.OdinInspector; using Sirenix.OdinInspector;
using Sirenix.Utilities;
using UnityEngine; using UnityEngine;
using XNode; using XNode;
@@ -126,30 +124,17 @@ namespace Stary.Evo.StoryEditor
#endregion #endregion
#region #region
#if UNITY_EDITOR
[BoxGroup("Export")]
[SerializeField, ValueDropdown(nameof(GetAllAssemblyNames))]
private string assembly;
private IEnumerable<string> GetAllAssemblyNames() =>
AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetName().Name).OrderBy(n => n);
/// <summary> [BoxGroup("Export", centerLabel:true)]
/// 获取继承 IResource 的所有类 [LabelText("程序集")]
/// </summary> public string assembly;
private HashSet<string> _iResourceTypes = AssemblyUtilities.GetTypes(AssemblyCategory.Scripts)
.Where(t => t.IsClass && typeof(IResource).IsAssignableFrom(t)).Select(t => t.ToString()).ToHashSet();
#else
private HashSet<string> _iResourceTypes = new();
#endif
/// <summary> /// <summary>
/// 资源加载方式 /// 资源加载方式
/// </summary> /// </summary>
[BoxGroup("Export", centerLabel:true)] [BoxGroup("Export")]
[LabelText("资源加载方式"), ValueDropdown(nameof(_iResourceTypes)),SerializeField] [LabelText("资源加载方式")]
private string loaderType; public string loaderType;
private IResource _loader; private IResource _loader;
/// <summary> /// <summary>
@@ -159,10 +144,14 @@ namespace Stary.Evo.StoryEditor
{ {
get get
{ {
if (_loader == null) if (_loader == null && !string.IsNullOrEmpty(loaderType))
{ {
var type = Type.GetType(loaderType); var asm = AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType(loaderType)).FirstOrDefault(t => t != null) ?? AppDomain.CurrentDomain.GetAssemblies().Select(a => a.GetType(loaderType, false, false)).FirstOrDefault(t => t != null);
_loader = type == null ? null : (IResource)Activator.CreateInstance(type);
if (asm != null)
{
_loader = (IResource)Activator.CreateInstance(asm);
}
} }
return _loader; return _loader;
@@ -263,7 +252,7 @@ namespace Stary.Evo.StoryEditor
// 将转录完成的图表数据序列化为json // 将转录完成的图表数据序列化为json
var json = JsonConvert.SerializeObject(graph, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }); var json = JsonConvert.SerializeObject(graph, new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
// 文件目录排空 // 文件目录排空
var graphFilePath = Path.Combine(Application.dataPath, graphPath.Replace(".asset", ".sg.json")); var graphFilePath = Path.Combine(Application.dataPath, graphPath);
if (!Directory.Exists(Path.GetDirectoryName(graphFilePath))) if (!Directory.Exists(Path.GetDirectoryName(graphFilePath)))
Directory.CreateDirectory(Path.GetDirectoryName(graphFilePath) ?? string.Empty); Directory.CreateDirectory(Path.GetDirectoryName(graphFilePath) ?? string.Empty);
// 写入json // 写入json

View File

@@ -1,6 +1,6 @@
{ {
"name": "com.staryevo.storyeditor", "name": "com.staryevo.storyeditor",
"version": "1.0.5", "version": "1.1.0",
"displayName": "10.StoryEditor", "displayName": "10.StoryEditor",
"description": "可视化剧本编辑器\n1.通过可视化图表编辑剧本内容\n2.将剧本导出为json\n3.解析剧本并执行", "description": "可视化剧本编辑器\n1.通过可视化图表编辑剧本内容\n2.将剧本导出为json\n3.解析剧本并执行",
"unity": "2021.3", "unity": "2021.3",