安卓优化

This commit is contained in:
2025-12-22 21:10:37 +08:00
parent 0cd5c55789
commit 43cad617af
29 changed files with 11047 additions and 4877 deletions
+132
View File
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace AibisDream.SystemEditor
{
// 帧数据
[Serializable]
public class FrameData
{
public string name;
public int x;
public int y;
public int width;
public int height;
public float duration; // 毫秒
}
// 动画片段数据
[Serializable]
public class AnimationData
{
public string name;
public List<int> frameIndices;
public bool loop;
public float? frameDuration; // 可选的,覆盖全局frameDuration
public int? sampleRate; // 可选的,覆盖全局sampleRate
}
// Aseprite JSON格式的数据结构
[Serializable]
public class AsepriteFrameInfo
{
public AsepriteFrameRect frame;
public bool rotated;
public bool trimmed;
public AsepriteFrameRect spriteSourceSize;
public AsepriteSize sourceSize;
public float duration; // 毫秒
}
[Serializable]
public class AsepriteFrameRect
{
public int x;
public int y;
public int w;
public int h;
}
[Serializable]
public class AsepriteSize
{
public int w;
public int h;
}
[Serializable]
public class AsepriteFrameTag
{
public string name;
public int from;
public int to;
public string direction;
}
[Serializable]
public class AsepriteMeta
{
public string app;
public string version;
public string image;
public string format;
public AsepriteSize size;
public string scale;
public List<AsepriteFrameTag> frameTags;
public List<object> layers;
public List<object> slices;
}
// Aseprite JSON的包装类(因为Unity JsonUtility不支持Dictionary
[Serializable]
public class AsepriteFrameEntry
{
public string key;
public AsepriteFrameInfo value;
}
[Serializable]
public class AsepriteJsonData
{
public AsepriteMeta meta;
// frames将通过手动解析处理
}
// 手动JSON格式的数据结构
[Serializable]
public class ManualLayout
{
public int rows;
public int columns;
public int? frameCount; // 可选
public string direction; // "horizontal" 或 "vertical"
}
[Serializable]
public class ManualJsonData
{
public string type;
public ManualLayout layout;
public float frameDuration; // 毫秒
public int sampleRate;
public List<AnimationData> animations;
}
// 统一的内部数据格式
public class ProcessedAnimationData
{
public List<FrameData> frames;
public List<ProcessedAnimationClip> animations;
}
public class ProcessedAnimationClip
{
public string name;
public List<int> frameIndices;
public bool loop;
public float frameDuration; // 毫秒(已应用覆盖逻辑)
public int sampleRate; // 已应用覆盖逻辑
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5cd60e41866d0ec418dfc6fdce37a8ba
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,133 @@
using System.IO;
using UnityEditor;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public class AnimationClipGenerator : EditorWindow
{
private Texture2D selectedTexture;
private TextAsset selectedJson;
private DefaultAsset outputFolder;
private string outputPath = "";
// 动画类型选项
private enum AnimationTargetType
{
SpriteRenderer, // Sprite动画
Image // UIImage动画
}
private AnimationTargetType animationType = AnimationTargetType.SpriteRenderer;
[MenuItem("Tools/Animation Clip Generator")]
public static void ShowWindow()
{
GetWindow<AnimationClipGenerator>("Animation Clip Generator");
}
private void OnGUI()
{
GUILayout.Label("Animation Clip Generator", EditorStyles.boldLabel);
EditorGUILayout.Space();
// 图片文件选择
EditorGUILayout.LabelField("图片文件 (PNG/JPG)", EditorStyles.boldLabel);
selectedTexture = (Texture2D)EditorGUILayout.ObjectField(
"Texture", selectedTexture, typeof(Texture2D), false);
EditorGUILayout.Space();
// JSON文件选择
EditorGUILayout.LabelField("JSON文件", EditorStyles.boldLabel);
selectedJson = (TextAsset)EditorGUILayout.ObjectField(
"JSON", selectedJson, typeof(TextAsset), false);
EditorGUILayout.Space();
// 动画类型选择
EditorGUILayout.LabelField("动画类型", EditorStyles.boldLabel);
animationType = (AnimationTargetType)EditorGUILayout.EnumPopup(
"Animation Type", animationType);
EditorGUILayout.HelpBox(
animationType == AnimationTargetType.SpriteRenderer
? "生成用于SpriteRenderer的动画(绑定到m_Sprite属性)"
: "生成用于Unity UI Image的动画(绑定到m_Sprite属性)",
MessageType.Info);
EditorGUILayout.Space();
// 输出目录选择
EditorGUILayout.LabelField("输出目录", EditorStyles.boldLabel);
outputFolder = (DefaultAsset)EditorGUILayout.ObjectField(
"Output Folder", outputFolder, typeof(DefaultAsset), false);
// 显示输出路径
if (outputFolder != null)
{
outputPath = AssetDatabase.GetAssetPath(outputFolder);
EditorGUILayout.HelpBox($"输出路径: {outputPath}", MessageType.Info);
}
else
{
outputPath = "";
}
EditorGUILayout.Space();
// 生成按钮
GUI.enabled = selectedTexture != null && selectedJson != null && outputFolder != null;
if (GUILayout.Button("生成 AnimationClip", GUILayout.Height(30)))
{
GenerateAnimationClips();
}
GUI.enabled = true;
EditorGUILayout.Space();
// 说明信息
EditorGUILayout.HelpBox(
"使用说明:\n" +
"1. 选择PNG或JPG图片文件\n" +
"2. 选择JSON文件(Aseprite格式或手动格式)\n" +
"3. 选择输出目录\n" +
"4. 点击生成按钮\n\n" +
"注意: 如果图片的SpriteMode是Single,工具会自动根据JSON切图。",
MessageType.Info);
}
private void GenerateAnimationClips()
{
if (selectedTexture == null || selectedJson == null || outputFolder == null)
{
EditorUtility.DisplayDialog("错误", "请选择图片文件、JSON文件和输出目录", "确定");
return;
}
string texturePath = AssetDatabase.GetAssetPath(selectedTexture);
string jsonPath = AssetDatabase.GetAssetPath(selectedJson);
// 验证文件扩展名
string textureExt = Path.GetExtension(texturePath).ToLower();
if (textureExt != ".png" && textureExt != ".jpg" && textureExt != ".jpeg")
{
EditorUtility.DisplayDialog("错误", "图片文件必须是PNG或JPG格式", "确定");
return;
}
try
{
bool isImageAnimation = animationType == AnimationTargetType.Image;
AnimationClipGeneratorCore.GenerateClips(texturePath, jsonPath, outputPath, isImageAnimation);
EditorUtility.DisplayDialog("成功", $"AnimationClip已生成到: {outputPath}", "确定");
// 刷新资源数据库
AssetDatabase.Refresh();
}
catch (System.Exception e)
{
EditorUtility.DisplayDialog("错误", $"生成失败: {e.Message}", "确定");
Debug.LogError(e);
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7472aae8191639b47af5d9ba115b39b5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,603 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEditor.U2D.Sprites;
using UnityEngine;
namespace AibisDream.SystemEditor
{
public static class AnimationClipGeneratorCore
{
// 检查SpriteMode
public static SpriteImportMode CheckSpriteMode(string texturePath)
{
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
return textureImporter.spriteImportMode;
}
// 解析Aseprite JSON
public static ProcessedAnimationData ParseAsepriteJson(string jsonPath, string texturePath)
{
string jsonContent = File.ReadAllText(jsonPath);
// Unity的JsonUtility不支持Dictionary,需要手动解析frames对象
// 使用SimpleJSON或手动解析
ProcessedAnimationData result = ParseAsepriteJsonManual(jsonContent);
if (result.frames == null || result.frames.Count == 0)
{
throw new Exception("无效的Aseprite JSON格式:无法解析frames");
}
return result;
}
private static ProcessedAnimationData ParseAsepriteJsonManual(string jsonContent)
{
List<FrameData> frames = new List<FrameData>();
List<ProcessedAnimationClip> animations = new List<ProcessedAnimationClip>();
try
{
// 解析meta部分
int metaStart = jsonContent.IndexOf("\"meta\":");
if (metaStart == -1)
{
throw new Exception("找不到meta部分");
}
// 找到meta对象的结束位置
int metaBraceStart = jsonContent.IndexOf('{', metaStart);
int metaBraceEnd = FindMatchingBrace(jsonContent, metaBraceStart);
string metaJson = jsonContent.Substring(metaBraceStart, metaBraceEnd - metaBraceStart + 1);
// 移除可能的尾随逗号
metaJson = metaJson.TrimEnd(',', ' ', '\n', '\r');
AsepriteMeta meta = JsonUtility.FromJson<AsepriteMeta>(metaJson);
// 解析frameTags
if (meta.frameTags != null)
{
foreach (var tag in meta.frameTags)
{
List<int> frameIndices = new List<int>();
int start = tag.from;
int end = tag.to;
if (tag.direction == "forward" || tag.direction == "pingpong" || string.IsNullOrEmpty(tag.direction))
{
for (int i = start; i <= end; i++)
{
frameIndices.Add(i);
}
}
else if (tag.direction == "reverse")
{
for (int i = end; i >= start; i--)
{
frameIndices.Add(i);
}
}
animations.Add(new ProcessedAnimationClip
{
name = tag.name,
frameIndices = frameIndices,
loop = true,
frameDuration = 0,
sampleRate = 100
});
}
}
// 解析frames对象 - 使用正则表达式或手动解析
int framesStart = jsonContent.IndexOf("\"frames\":");
if (framesStart == -1)
{
throw new Exception("找不到frames部分");
}
// 找到frames对象的开始和结束
int framesBraceStart = jsonContent.IndexOf('{', framesStart);
int framesBraceEnd = FindMatchingBrace(jsonContent, framesBraceStart);
string framesContent = jsonContent.Substring(framesBraceStart + 1, framesBraceEnd - framesBraceStart - 1);
// 解析每个帧条目
ParseFramesContent(framesContent, frames);
// 按名称排序帧(确保顺序正确)
frames = frames.OrderBy(f => ExtractFrameNumber(f.name)).ThenBy(f => f.name).ToList();
}
catch (Exception e)
{
throw new Exception($"解析Aseprite JSON失败: {e.Message}\n{e.StackTrace}");
}
return new ProcessedAnimationData
{
frames = frames,
animations = animations
};
}
private static void ParseFramesContent(string framesContent, List<FrameData> frames)
{
int pos = 0;
while (pos < framesContent.Length)
{
// 跳过空白字符和逗号
while (pos < framesContent.Length && (char.IsWhiteSpace(framesContent[pos]) || framesContent[pos] == ','))
pos++;
if (pos >= framesContent.Length) break;
// 查找帧名称(在引号中)
if (framesContent[pos] != '"')
{
pos++;
continue;
}
int nameStart = pos + 1;
int nameEnd = framesContent.IndexOf('"', nameStart);
if (nameEnd == -1) break;
string frameName = framesContent.Substring(nameStart, nameEnd - nameStart);
pos = nameEnd + 1;
// 跳过冒号和空白
while (pos < framesContent.Length && (char.IsWhiteSpace(framesContent[pos]) || framesContent[pos] == ':'))
pos++;
if (pos >= framesContent.Length) break;
// 查找帧数据对象
if (framesContent[pos] != '{')
{
continue;
}
int dataStart = pos;
int dataEnd = FindMatchingBrace(framesContent, dataStart);
if (dataEnd == -1) break;
string frameDataJson = framesContent.Substring(dataStart, dataEnd - dataStart + 1);
pos = dataEnd + 1;
try
{
AsepriteFrameInfo frameInfo = JsonUtility.FromJson<AsepriteFrameInfo>(frameDataJson);
if (frameInfo.frame != null)
{
frames.Add(new FrameData
{
name = frameName,
x = frameInfo.frame.x,
y = frameInfo.frame.y,
width = frameInfo.frame.w,
height = frameInfo.frame.h,
duration = frameInfo.duration
});
}
}
catch (Exception e)
{
Debug.LogWarning($"解析帧数据失败: {frameName}, 错误: {e.Message}");
}
}
}
private static int ExtractFrameNumber(string frameName)
{
// 尝试从帧名称中提取数字(例如 "调酒妹侧头 0.aseprite" -> 0
int lastSpace = frameName.LastIndexOf(' ');
if (lastSpace >= 0 && lastSpace < frameName.Length - 1)
{
string numberPart = frameName.Substring(lastSpace + 1);
int dotIndex = numberPart.IndexOf('.');
if (dotIndex > 0)
{
numberPart = numberPart.Substring(0, dotIndex);
}
if (int.TryParse(numberPart, out int number))
{
return number;
}
}
return int.MaxValue; // 如果无法解析,放在最后
}
private static int FindMatchingBrace(string str, int startIndex)
{
if (startIndex < 0 || startIndex >= str.Length) return -1;
int braceCount = 0;
bool foundStart = false;
for (int i = startIndex; i < str.Length; i++)
{
if (str[i] == '{')
{
braceCount++;
foundStart = true;
}
else if (str[i] == '}')
{
braceCount--;
if (braceCount == 0 && foundStart)
{
return i;
}
}
}
return -1;
}
// 解析手动JSON
public static ProcessedAnimationData ParseManualJson(string jsonPath, string texturePath)
{
string jsonContent = File.ReadAllText(jsonPath);
ManualJsonData manualData = JsonUtility.FromJson<ManualJsonData>(jsonContent);
if (manualData.layout == null || manualData.animations == null)
{
throw new Exception("无效的手动JSON格式");
}
// 验证layout参数
if (manualData.layout.rows <= 0 || manualData.layout.columns <= 0)
{
throw new Exception("rows和columns必须大于0");
}
// 读取图片尺寸
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(texturePath);
if (texture == null)
{
throw new Exception($"无法加载纹理: {texturePath}");
}
int imageWidth = texture.width;
int imageHeight = texture.height;
// 计算sprite尺寸
int spriteWidth = imageWidth / manualData.layout.columns;
int spriteHeight = imageHeight / manualData.layout.rows;
// 验证图片尺寸能被行列数整除
if (imageWidth % manualData.layout.columns != 0 || imageHeight % manualData.layout.rows != 0)
{
throw new Exception($"图片尺寸({imageWidth}x{imageHeight})无法被行列数({manualData.layout.columns}x{manualData.layout.rows})整除");
}
// 计算总帧数
int totalFrames = manualData.layout.frameCount ?? (manualData.layout.rows * manualData.layout.columns);
if (totalFrames > manualData.layout.rows * manualData.layout.columns)
{
throw new Exception($"frameCount({totalFrames})不能超过rows*columns({manualData.layout.rows * manualData.layout.columns})");
}
// 生成帧数据
List<FrameData> frames = new List<FrameData>();
bool isHorizontal = manualData.layout.direction == "horizontal";
for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++)
{
int row, column;
if (isHorizontal)
{
// 横向排列:按行扫描,从左到右,从上到下
row = frameIndex / manualData.layout.columns;
column = frameIndex % manualData.layout.columns;
}
else
{
// 纵向排列:按列扫描,从上到下,从左到右
column = frameIndex / manualData.layout.rows;
row = frameIndex % manualData.layout.rows;
}
// Unity Y轴从下往上,需要转换
int x = column * spriteWidth;
int y = (manualData.layout.rows - 1 - row) * spriteHeight;
frames.Add(new FrameData
{
name = $"frame_{frameIndex}",
x = x,
y = y,
width = spriteWidth,
height = spriteHeight,
duration = manualData.frameDuration
});
}
// 处理动画片段
List<ProcessedAnimationClip> animations = new List<ProcessedAnimationClip>();
foreach (var anim in manualData.animations)
{
// 应用参数覆盖逻辑
float frameDuration = anim.frameDuration ?? manualData.frameDuration;
int sampleRate = anim.sampleRate ?? manualData.sampleRate;
animations.Add(new ProcessedAnimationClip
{
name = anim.name,
frameIndices = anim.frameIndices,
loop = anim.loop,
frameDuration = frameDuration,
sampleRate = sampleRate
});
}
return new ProcessedAnimationData
{
frames = frames,
animations = animations
};
}
// 根据JSON信息切图
public static void SliceSprites(string texturePath, List<FrameData> frames)
{
TextureImporter textureImporter = AssetImporter.GetAtPath(texturePath) as TextureImporter;
if (textureImporter == null)
{
throw new Exception($"无法加载纹理导入器: {texturePath}");
}
// 设置spriteMode为Multiple
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
// 使用新的Sprite Editor Data Provider API (Unity 2020.2+)
var spriteDataProviderFactories = new SpriteDataProviderFactories();
spriteDataProviderFactories.Init();
var dataProvider = spriteDataProviderFactories.GetSpriteEditorDataProviderFromObject(textureImporter);
if (dataProvider == null)
{
throw new Exception($"无法获取Sprite Editor Data Provider: {texturePath}");
}
dataProvider.InitSpriteEditorDataProvider();
// 创建SpriteRect数组
var spriteRects = new SpriteRect[frames.Count];
for (int i = 0; i < frames.Count; i++)
{
var frame = frames[i];
spriteRects[i] = new SpriteRect
{
name = frame.name,
rect = new Rect(frame.x, frame.y, frame.width, frame.height),
pivot = new Vector2(0.5f, 0.5f),
alignment = SpriteAlignment.Center
};
}
dataProvider.SetSpriteRects(spriteRects);
dataProvider.Apply();
AssetDatabase.ImportAsset(texturePath, ImportAssetOptions.ForceUpdate);
}
// 创建AnimationClip
public static AnimationClip CreateAnimationClip(
ProcessedAnimationClip animationData,
List<FrameData> frames,
Sprite[] sprites,
string outputPath,
bool isImageAnimation = false)
{
AnimationClip clip = new AnimationClip();
clip.name = animationData.name;
// 设置采样率
AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
clip.frameRate = animationData.sampleRate;
// 创建Sprite关键帧
List<ObjectReferenceKeyframe> keyframes = new List<ObjectReferenceKeyframe>();
float currentTime = 0f;
foreach (int frameIndex in animationData.frameIndices)
{
if (frameIndex < 0 || frameIndex >= sprites.Length)
{
Debug.LogWarning($"帧索引{frameIndex}超出范围,跳过");
continue;
}
Sprite sprite = sprites[frameIndex];
if (sprite == null)
{
Debug.LogWarning($"帧索引{frameIndex}的Sprite为空,跳过");
continue;
}
// 使用帧的duration(如果是Aseprite格式)或动画的frameDuration(手动格式)
float frameDuration = frames[frameIndex].duration > 0
? frames[frameIndex].duration / 1000f // 毫秒转秒
: animationData.frameDuration / 1000f;
keyframes.Add(new ObjectReferenceKeyframe
{
time = currentTime,
value = sprite
});
currentTime += frameDuration;
}
if (keyframes.Count == 0)
{
throw new Exception($"动画片段{animationData.name}没有有效的关键帧");
}
// 设置循环
if (animationData.loop && keyframes.Count > 1)
{
// 添加最后一帧的重复,确保循环
keyframes.Add(new ObjectReferenceKeyframe
{
time = currentTime,
value = keyframes[0].value
});
}
// 创建EditorCurveBinding - 根据动画类型选择不同的组件
EditorCurveBinding curveBinding = new EditorCurveBinding
{
path = "",
type = isImageAnimation ? typeof(UnityEngine.UI.Image) : typeof(SpriteRenderer),
propertyName = "m_Sprite"
};
// 设置曲线
AnimationUtility.SetObjectReferenceCurve(clip, curveBinding, keyframes.ToArray());
// 设置循环
settings.loopTime = animationData.loop;
AnimationUtility.SetAnimationClipSettings(clip, settings);
// 保存AnimationClip
string fullPath = Path.Combine(outputPath, $"{animationData.name}.anim");
string assetPath = fullPath.Replace('\\', '/');
if (!assetPath.StartsWith("Assets/"))
{
// 转换为相对路径
string projectPath = Application.dataPath.Replace("Assets", "");
if (assetPath.StartsWith(projectPath))
{
assetPath = assetPath.Substring(projectPath.Length);
}
}
AssetDatabase.CreateAsset(clip, assetPath);
AssetDatabase.SaveAssets();
return clip;
}
// 主流程:生成AnimationClip
public static void GenerateClips(string texturePath, string jsonPath, string outputPath, bool isImageAnimation = false)
{
try
{
EditorUtility.DisplayProgressBar("生成AnimationClip", "检查SpriteMode...", 0f);
// 检查SpriteMode
SpriteImportMode spriteMode = CheckSpriteMode(texturePath);
if (spriteMode == SpriteImportMode.Multiple)
{
Debug.Log("图片的SpriteMode已经是Multiple,将使用现有的Sprite切图");
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "解析JSON...", 0.2f);
// 判断JSON类型并解析
ProcessedAnimationData processedData;
string jsonContent = File.ReadAllText(jsonPath);
if (jsonContent.Contains("\"type\":\"manual\"") || jsonContent.Contains("\"type\": \"manual\""))
{
// 手动格式
processedData = ParseManualJson(jsonPath, texturePath);
}
else
{
// Aseprite格式
processedData = ParseAsepriteJson(jsonPath, texturePath);
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "切图...", 0.4f);
// 如果是Single模式,需要切图
if (spriteMode == SpriteImportMode.Single)
{
SliceSprites(texturePath, processedData.frames);
// 重新加载以确保sprites可用
AssetDatabase.Refresh();
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "加载Sprites...", 0.6f);
// 加载所有Sprites
Sprite[] allSpritesArray = AssetDatabase.LoadAllAssetsAtPath(texturePath)
.OfType<Sprite>()
.ToArray();
if (allSpritesArray.Length == 0)
{
throw new Exception("无法加载任何Sprite,请检查切图设置");
}
// 创建Sprite字典以便快速查找
Dictionary<string, Sprite> spriteDict = allSpritesArray.ToDictionary(s => s.name, s => s);
// 按照frames列表的顺序创建Sprite数组
Sprite[] allSprites = new Sprite[processedData.frames.Count];
for (int i = 0; i < processedData.frames.Count; i++)
{
string frameName = processedData.frames[i].name;
if (spriteDict.TryGetValue(frameName, out Sprite sprite))
{
allSprites[i] = sprite;
}
else
{
Debug.LogWarning($"找不到名为{frameName}的Sprite");
// 尝试使用索引查找
if (i < allSpritesArray.Length)
{
allSprites[i] = allSpritesArray[i];
}
}
}
// 确保输出目录存在
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
EditorUtility.DisplayProgressBar("生成AnimationClip", "创建AnimationClip...", 0.8f);
// 为每个动画片段创建AnimationClip
int animationCount = processedData.animations.Count;
for (int i = 0; i < animationCount; i++)
{
var anim = processedData.animations[i];
EditorUtility.DisplayProgressBar("生成AnimationClip",
$"创建动画片段: {anim.name}", 0.8f + (i / (float)animationCount) * 0.2f);
CreateAnimationClip(anim, processedData.frames, allSprites, outputPath, isImageAnimation);
}
EditorUtility.ClearProgressBar();
Debug.Log($"成功生成{animationCount}个AnimationClip到: {outputPath}");
}
catch (Exception e)
{
EditorUtility.ClearProgressBar();
Debug.LogError($"生成AnimationClip失败: {e.Message}");
throw;
}
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7abb40962ba935419bb10c937b8b2c7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -19,12 +19,12 @@ MonoBehaviour:
m_Key: line:02365db
m_Metadata:
m_Items:
- rid: 4903297761218920450
- rid: 4903297902702231610
- m_Id: 111869431808
m_Key: line:0559767
m_Metadata:
m_Items:
- rid: 4903297761218920451
- rid: 4903297902702231611
- m_Id: 111869431809
m_Key: line:0ee9c21
m_Metadata:
@@ -39,12 +39,12 @@ MonoBehaviour:
m_Key: line:0667c6a
m_Metadata:
m_Items:
- rid: 4903297761218920452
- rid: 4903297902702231612
- m_Id: 46439178508963840
m_Key: line:054b767
m_Metadata:
m_Items:
- rid: 4903297761218920453
- rid: 4903297902702231613
m_Metadata:
m_Items: []
m_KeyGenerator:
@@ -52,22 +52,22 @@ MonoBehaviour:
references:
version: 2
RefIds:
- rid: 4903297761218920450
- rid: 4903297902702231610
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 4903297761218920451
- rid: 4903297902702231611
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: Start
tags: []
- rid: 4903297761218920452
- rid: 4903297902702231612
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: "\u65B9\u5757\u62FC\u56FE\u5B8C\u6210"
tags: []
- rid: 4903297761218920453
- rid: 4903297902702231613
type: {class: LineMetadata, ns: Yarn.Unity.UnityLocalization, asm: YarnSpinner.Unity}
data:
nodeName: "\u65B9\u5757\u62FC\u56FE\u5B8C\u6210"
File diff suppressed because it is too large Load Diff
+9 -13
View File
@@ -463,19 +463,15 @@ MonoBehaviour:
m_PostInfinity: 2
m_RotationOrder: 4
_filter:
- 0.0048309183
- 0.016401261
- 0.04532712
- 0.08293076
- 0.12053438
- 0.14946026
- 0.1610306
- 0.14946026
- 0.12053438
- 0.08293076
- 0.04532712
- 0.016401261
- 0.0048309183
- 0.007228916
- 0.043749984
- 0.12409639
- 0.20444278
- 0.24096388
- 0.20444278
- 0.12409639
- 0.043749984
- 0.007228916
--- !u!114 &-6086986437317696584
MonoBehaviour:
m_ObjectHideFlags: 3
+269
View File
@@ -12191,6 +12191,43 @@ PlayableDirector:
value: {fileID: 0}
m_ExposedReferences:
m_References: []
--- !u!1 &749156594
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 749156595}
m_Layer: 5
m_Name: Loading
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!224 &749156595
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 749156594}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1186192817}
- {fileID: 1314471602}
m_Father: {fileID: 923998313}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1001 &759307075
PrefabInstance:
m_ObjectHideFlags: 0
@@ -14585,6 +14622,7 @@ RectTransform:
m_Children:
- {fileID: 961234236}
- {fileID: 398371925}
- {fileID: 749156595}
- {fileID: 1986521822}
m_Father: {fileID: 2091451641}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@@ -17487,6 +17525,103 @@ MonoBehaviour:
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 0
--- !u!1 &1186192816
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1186192817}
- component: {fileID: 1186192820}
- component: {fileID: 1186192819}
- component: {fileID: 1186192818}
m_Layer: 5
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1186192817
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1186192816}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 749156595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 68}
m_SizeDelta: {x: 182, y: 222}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!95 &1186192818
Animator:
serializedVersion: 5
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1186192816}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: 4efe920582e4eb84eabc738f16624d2b, type: 2}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!114 &1186192819
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1186192816}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &1186192820
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1186192816}
m_CullTransparentMesh: 1
--- !u!1 &1197644599
GameObject:
m_ObjectHideFlags: 0
@@ -19215,6 +19350,140 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 85815d386fde43dca8b4be1cfd26fe89, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1314471601
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1314471602}
- component: {fileID: 1314471604}
- component: {fileID: 1314471603}
m_Layer: 5
m_Name: Text (TMP)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1314471602
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1314471601}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 749156595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 3, y: -30}
m_SizeDelta: {x: 200, y: 50}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &1314471603
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1314471601}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_text: Loading
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: f242fb3dde1933640859f1c54591c9c8, type: 2}
m_sharedMaterial: {fileID: -6659093157667844055, guid: f242fb3dde1933640859f1c54591c9c8, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
topLeft: {r: 1, g: 1, b: 1, a: 1}
topRight: {r: 1, g: 1, b: 1, a: 1}
bottomLeft: {r: 1, g: 1, b: 1, a: 1}
bottomRight: {r: 1, g: 1, b: 1, a: 1}
m_fontColorGradientPreset: {fileID: 0}
m_spriteAsset: {fileID: 0}
m_tintAllSprites: 0
m_StyleSheet: {fileID: 0}
m_TextStyleHashCode: -1183493901
m_overrideHtmlColors: 0
m_faceColor:
serializedVersion: 2
rgba: 4294967295
m_fontSize: 36
m_fontSizeBase: 36
m_fontWeight: 400
m_enableAutoSizing: 0
m_fontSizeMin: 18
m_fontSizeMax: 72
m_fontStyle: 0
m_HorizontalAlignment: 2
m_VerticalAlignment: 512
m_textAlignment: 65535
m_characterSpacing: 0
m_wordSpacing: 0
m_lineSpacing: 0
m_lineSpacingMax: 0
m_paragraphSpacing: 0
m_charWidthMaxAdj: 0
m_enableWordWrapping: 1
m_wordWrappingRatios: 0.4
m_overflowMode: 0
m_linkedTextComponent: {fileID: 0}
parentLinkedComponent: {fileID: 0}
m_enableKerning: 1
m_enableExtraPadding: 0
checkPaddingRequired: 0
m_isRichText: 1
m_parseCtrlCharacters: 1
m_isOrthographic: 1
m_isCullingEnabled: 0
m_horizontalMapping: 0
m_verticalMapping: 0
m_uvLineOffset: 0
m_geometrySortingOrder: 0
m_IsTextObjectScaleStatic: 0
m_VertexBufferAutoSizeReduction: 0
m_useMaxVisibleDescender: 1
m_pageToDisplay: 1
m_margin: {x: 0, y: 0, z: 0, w: 0}
m_isUsingLegacyAnimationComponent: 0
m_isVolumetricText: 0
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!222 &1314471604
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1314471601}
m_CullTransparentMesh: 1
--- !u!1 &1317294297
GameObject:
m_ObjectHideFlags: 0
+21 -13
View File
@@ -1,9 +1,10 @@
using System;
using UnityEngine;
using AibisDream.Utility;
namespace AibisDream.Kit
{
internal class LogKit : MonoBehaviour
internal static class LogKit
{
/// <summary>
/// 文件名称格式
@@ -11,11 +12,6 @@ namespace AibisDream.Kit
/// </summary>
public static string LogFileName => "Log{0:_yyyy_MM_dd}.txt";
/// <summary>
/// 日志文件路径
/// </summary>
public static string LogPath => Application.streamingAssetsPath + "/LogFile";
/// <summary>
/// 日志保存最近几天的内容
/// </summary>
@@ -26,29 +22,41 @@ namespace AibisDream.Kit
/// </summary>
private static string LogContent => Time + ": {0}\n{1}";
private FileLogger _fileLogger;
private static FileLogger _fileLogger;
private static bool _isInitialized;
private static string Time => DateTime.Now.ToString("[HH:mm:ss.fffd]");
private void Awake()
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
#if !UNITY_EDITOR
DontDestroyOnLoad(gameObject);
_fileLogger = new FileLogger(LogFileName, LogPath, SaveDays, Application.version);
if (_isInitialized)
return;
_fileLogger = new FileLogger(LogFileName, ConstRef.LogFilePath, SaveDays);
LogMessage($"Ver.{Application.version}", "", LogType.Log);
Application.logMessageReceivedThreaded += LogMessage;
Application.quitting += Shutdown;
_isInitialized = true;
#endif
}
private void LogMessage(string condition, string stackTrace, LogType type)
private static void LogMessage(string condition, string stackTrace, LogType type)
{
_fileLogger?.Write(string.Format(LogContent, condition, stackTrace));
}
private void OnDestroy()
private static void Shutdown()
{
if (!_isInitialized)
return;
Application.logMessageReceivedThreaded -= LogMessage;
Application.quitting -= Shutdown;
_fileLogger?.OnDestroy();
_fileLogger = null;
Application.logMessageReceivedThreaded -= LogMessage;
_isInitialized = false;
}
}
}
+46 -1
View File
@@ -4,6 +4,8 @@ using AibisDream.Framework;
using AibisDream.Kit;
using AibisDream.UI;
using UnityEngine;
using System.IO;
using AibisDream.Utility;
namespace AibisDream
{
@@ -12,12 +14,15 @@ namespace AibisDream
/// </summary>
public class SettingLoader
{
private static readonly string SettingPath = Application.streamingAssetsPath + "/Config/setting.json";
private static readonly string SettingPath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "Config", "setting.json");
private static readonly string SettingDefaultPath = Path.Combine(Application.streamingAssetsPath, "Config", "setting.json");
private readonly ConfigContainer _container;
private SettingLoader()
{
// 初始化设置文件(如果不存在)
InitSettingFile();
// 读取数据
_container = new ConfigContainer(SettingPath);
LoadAllSetting();
@@ -30,6 +35,44 @@ namespace AibisDream
_container.OnWrite -= OnSettingChanged;
}
private void InitSettingFile()
{
// 如果文件存在,则直接返回
if (File.Exists(SettingPath))
{
return;
}
// 如果文件不存在,则复制默认设置并根据系统语言设置初始语言值
var defaultSetting = JsonUtil.ReadJObject(SettingDefaultPath);
// 根据当前系统语言设置初始语言值
string systemLanguage = GetLanguageBySystemLanguage();
defaultSetting["Language"] = systemLanguage;
// 保存设置文件
JsonUtil.SaveJObject(defaultSetting, SettingPath);
}
/// <summary>
/// 根据系统语言获取对应的语言代码
/// </summary>
/// <returns>语言代码:zh-Hans、en、ja-JP,默认返回 en</returns>
private string GetLanguageBySystemLanguage()
{
SystemLanguage systemLang = Application.systemLanguage;
return systemLang switch
{
SystemLanguage.Chinese => "zh-Hans",
SystemLanguage.ChineseSimplified => "zh-Hans",
SystemLanguage.ChineseTraditional => "zh-Hans",
SystemLanguage.Japanese => "ja-JP",
SystemLanguage.English => "en",
_ => "en",
};
}
private void LoadAllSetting()
{
var settingConfig = _container.ReadAll();
@@ -55,7 +98,9 @@ namespace AibisDream
break;
case "WindowMode":
// 屏幕模式
#if !UNITY_ANDROID && !UNITY_IOS
GameManager.Instance.SetScreenMode(value);
#endif
break;
case "Language":
// 确保本地化系统已初始化
+11
View File
@@ -5,6 +5,7 @@ namespace AibisDream.UI
public class InfoPanel : MonoBehaviour, IUIPanel
{
[SerializeField] private DemoTimer demoTimer;
[SerializeField] private GameObject loading;
[SerializeField] private VariableBar variableBar;
public void SetTimerActive(bool isOpen)
@@ -35,6 +36,16 @@ namespace AibisDream.UI
gameObject.SetActive(false);
}
public void ShowLoading()
{
loading.SetActive(true);
}
public void HideLoading()
{
loading.SetActive(false);
}
public bool IsOpen => gameObject.activeSelf;
public bool IsCloseable => false;
+11 -9
View File
@@ -1,3 +1,4 @@
using System.IO;
using UnityEngine;
namespace AibisDream.Utility
@@ -14,6 +15,7 @@ namespace AibisDream.Utility
public const string SurveyURL_CN = "https://jsj.top/f/HkmCnH";
public const string SurveyURL_EN = "https://jsj.top/f/y501LX";
public const string SurveyURL_JP = "https://jsj.top/f/icnVug";
public const string WishlistURL = "https://store.steampowered.com/app/3473430/_All_Our_Broken_Parts?utm_source=playtest";
@@ -22,14 +24,18 @@ namespace AibisDream.Utility
#if UnityEditor
public static readonly string SaveFilePath = Application.persistentDataPath + "/SaveFiles/";
#else
public static readonly string SaveFilePath = Application.persistentDataPath + "/AllOurBrokenParts/saves/";
public static readonly string SaveFilePath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "saves");
#endif
public static readonly string ChapterProgressPath = $"{Application.streamingAssetsPath}/Config/chapter.json";
public static readonly string ChapterProgressPath = Path.Combine(Application.persistentDataPath, "AllOurBrokenParts", "Config", "chapter.json");
public static readonly string CharacterConfigPath = Path.Combine(Application.streamingAssetsPath, "Config", "character.csv");
public static readonly string LogFilePath = Path.Combine(Application.persistentDataPath, "LogFile");
public static readonly string BlockPuzzleDataPath = Path.Combine(Application.streamingAssetsPath, "LevelData", "BlockPuzzle", "BlockPuzzleData.json");
public static readonly string BlockShapeDataPath = Path.Combine(Application.streamingAssetsPath, "LevelData", "BlockPuzzle", "BlockShapeData.json");
public static readonly string BlockShapeDataPath = $"{Application.streamingAssetsPath}/LevelData/BlockPuzzle/BlockShapeData.json";
public static readonly string BlockPuzzleDataPath = $"{Application.streamingAssetsPath}/LevelData/BlockPuzzle/BlockPuzzleData.json";
#region
@@ -63,10 +69,6 @@ namespace AibisDream.Utility
public const string RecordPrefab = "RecordItem";
public const string BlockShapePrefab = "BlockShape";
public const string ShapeCreateButtonPrefab = "ShapeCreateButton";
#endregion
#region
@@ -82,7 +84,7 @@ namespace AibisDream.Utility
public const int CharacterDelayTime = 70;
public const int LineMaxDelay = 2800;
public const int LineMinDelay = 600;
public const int AutoHideDelay = 300;
public const int AutoHideDelay = 150;
public const int FixedDelay = 200;
#endregion
+92 -12
View File
@@ -9,6 +9,8 @@ using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;
namespace AibisDream.Utility
{
@@ -20,13 +22,89 @@ namespace AibisDream.Utility
// 默认分隔符
private const char FieldSeparator = ',';
/// <summary>
/// 根据平台读取文件内容
/// </summary>
private static string ReadFileText(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
// Android 上 StreamingAssets 在 APK 中,需要构建正确的 URL
string url = filePath;
// 确保使用正确的路径分隔符
url = url.Replace("\\", "/");
// 如果路径不包含协议前缀,添加 file://
if (!url.StartsWith("file://") && !url.StartsWith("jar:file://"))
{
// 对于 Android APK 中的文件,使用 jar:file:// 协议
string relativePath = url.Replace(Application.streamingAssetsPath, "").TrimStart('/');
url = "jar:file://" + Application.dataPath + "!/assets/" + relativePath;
}
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
// 等待请求完成(同步等待)
while (!www.isDone)
{
// 在主线程中等待
}
if (www.result == UnityWebRequest.Result.Success)
{
return www.downloadHandler.text;
}
else
{
throw new IOException($"无法读取文件: {filePath}, URL: {url}, 错误: {www.error}");
}
}
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return File.ReadAllText(filePath, DefaultEncode);
}
#else
// 其他平台直接使用 File 类
return File.ReadAllText(filePath, DefaultEncode);
#endif
}
/// <summary>
/// 根据平台创建 StreamReader
/// </summary>
private static StreamReader CreateStreamReader(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
string fileText = ReadFileText(filePath);
MemoryStream stream = new MemoryStream(DefaultEncode.GetBytes(fileText));
return new StreamReader(stream, DefaultEncode);
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return new StreamReader(filePath, DefaultEncode);
}
#else
// 其他平台直接使用 File 类
return new StreamReader(filePath, DefaultEncode);
#endif
}
public static List<string[]> Read(string filePath)
{
List<string[]> dataList = new List<string[]>();
StreamReader reader;
StreamReader reader = null;
try
{
using (reader = new StreamReader(filePath, DefaultEncode))
using (reader = CreateStreamReader(filePath))
{
while (!reader.EndOfStream)
{
@@ -48,7 +126,7 @@ namespace AibisDream.Utility
GC.Collect();
Thread.Sleep(50);
Console.WriteLine(ex.StackTrace);
using (reader = new StreamReader(filePath, DefaultEncode))
using (reader = CreateStreamReader(filePath))
{
while (!reader.EndOfStream)
{
@@ -59,8 +137,10 @@ namespace AibisDream.Utility
}
}
}
reader.Close();
finally
{
reader?.Close();
}
return dataList;
}
@@ -82,7 +162,7 @@ namespace AibisDream.Utility
var props = targetType.GetProperties();
// 读取CSV
using var reader = new StreamReader(filePath, DefaultEncode);
using var reader = CreateStreamReader(filePath);
// 第一行是注释
reader.ReadLine();
@@ -90,7 +170,7 @@ namespace AibisDream.Utility
var titles = reader.ReadLine()?.Split(FieldSeparator);
if (titles == null)
{
Debug.WriteLine("csv无标题");
System.Diagnostics.Debug.WriteLine("csv无标题");
throw new Exception("csv无标题");
}
@@ -100,7 +180,7 @@ namespace AibisDream.Utility
{
string newLine = reader.ReadLine();
if (string.IsNullOrEmpty(newLine)) break;
string[] rowData = newLine.Split(FieldSeparator);
if (rowData == null || rowData.Length == 0) continue;
@@ -109,13 +189,13 @@ namespace AibisDream.Utility
foreach (var prop in props)
{
string name = prop.Name;
if (!titles.Contains(prop.Name))
if (!titles.Contains(prop.Name))
continue;
int idx = Array.IndexOf(titles, prop.Name);
prop.SetValue(obj, GetDefaultValue(prop, rowData[idx]));
}
res.Add(obj as T);
}
@@ -130,7 +210,7 @@ namespace AibisDream.Utility
{
bool blnFlag = true;
StreamReader reader = new StreamReader(strPath, DefaultEncode);
StreamReader reader = CreateStreamReader(strPath);
myCsvDt = new DataTable();
while (reader.ReadLine() is { } strLine)
{
@@ -218,7 +298,7 @@ namespace AibisDream.Utility
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.Message);
sw.Close();
}
}
+63 -6
View File
@@ -4,6 +4,8 @@ using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Networking;
namespace AibisDream.Utility
{
@@ -11,6 +13,58 @@ namespace AibisDream.Utility
{
public const string JsonSuffix = ".json";
/// <summary>
/// 根据平台读取文件内容
/// </summary>
private static string ReadFileText(string filePath)
{
#if UNITY_ANDROID && !UNITY_EDITOR
// Android 平台需要使用 UnityWebRequest 读取 StreamingAssets
if (filePath.Contains(Application.streamingAssetsPath))
{
// Android 上 StreamingAssets 在 APK 中,需要构建正确的 URL
string url = filePath;
// 确保使用正确的路径分隔符
url = url.Replace("\\", "/");
// 如果路径不包含协议前缀,添加 file://
if (!url.StartsWith("file://") && !url.StartsWith("jar:file://"))
{
// 对于 Android APK 中的文件,使用 jar:file:// 协议
string relativePath = url.Replace(Application.streamingAssetsPath, "").TrimStart('/');
url = "jar:file://" + Application.dataPath + "!/assets/" + relativePath;
}
using (UnityWebRequest www = UnityWebRequest.Get(url))
{
www.SendWebRequest();
// 等待请求完成(同步等待)
while (!www.isDone)
{
// 在主线程中等待
}
if (www.result == UnityWebRequest.Result.Success)
{
return www.downloadHandler.text;
}
else
{
throw new IOException($"无法读取文件: {filePath}, URL: {url}, 错误: {www.error}");
}
}
}
else
{
// 非 StreamingAssets 路径,使用普通文件读取
return File.ReadAllText(filePath);
}
#else
// 其他平台直接使用 File 类
return File.ReadAllText(filePath);
#endif
}
/// <summary>
/// 按路径和Key加载
/// </summary>
@@ -21,7 +75,7 @@ namespace AibisDream.Utility
/// <exception cref="Exception">错误</exception>
public static T ReadBean<T>(string path, string key)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
JObject jObject = JObject.Parse(json);
if (jObject.ContainsKey(key))
@@ -40,7 +94,7 @@ namespace AibisDream.Utility
/// <returns></returns>
public static T ReadBean<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<T>(json);
}
@@ -61,7 +115,7 @@ namespace AibisDream.Utility
/// <returns>目标Bean</returns>
public static T[] ReadBeanArray<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<T[]>(json);
}
@@ -73,7 +127,7 @@ namespace AibisDream.Utility
/// <returns>目标Bean</returns>
public static Dictionary<string, T> ReadBeanDict<T>(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
return JsonConvert.DeserializeObject<Dictionary<string, T>>(json);
}
@@ -84,7 +138,7 @@ namespace AibisDream.Utility
/// <returns>key列表</returns>
public static string[] ReadKeys(string path)
{
string json = File.ReadAllText(path);
string json = ReadFileText(path);
JObject jObject = JObject.Parse(json);
return jObject.Properties().Select(jProp => jProp.Name).ToArray();
@@ -92,7 +146,7 @@ namespace AibisDream.Utility
public static JObject ReadJObject(string path)
{
string json = File.ReadAllText(FormatAsJsonPath(path), System.Text.Encoding.UTF8);
string json = ReadFileText(FormatAsJsonPath(path));
return JObject.Parse(json);
}
@@ -105,18 +159,21 @@ namespace AibisDream.Utility
public static void SaveBean<T>(T bean, string path)
{
string json = JsonConvert.SerializeObject(bean);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, json);
}
public static void SaveJObject(JObject jObject, string path)
{
string json = jObject.ToString();
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(FormatAsJsonPath(path), json);
}
public static void SaveArray<T>(T[] array, string path)
{
string json = JsonConvert.SerializeObject(array);
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(FormatAsJsonPath(path), json);
}
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f152992d42cac4e4fb88e562812b6013
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
Binary file not shown.
@@ -0,0 +1,505 @@
fileFormatVersion: 2
guid: 4af5cf244c618df42813f45ce20338ea
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 4096
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: "LOADING \u7F50\u5934_0"
rect:
serializedVersion: 2
x: 0
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 6e493e316235fe542a153d49c625f134
internalID: 1719050414
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_1"
rect:
serializedVersion: 2
x: 182
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 52cf602c8b89e284b83d131738790d0a
internalID: -1164775371
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_2"
rect:
serializedVersion: 2
x: 364
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 774324f9c420dc049813cb468abc2594
internalID: -1244389054
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_3"
rect:
serializedVersion: 2
x: 546
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 2f8c071d9d5fc9849a68a6e64f984b57
internalID: -1957662414
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_4"
rect:
serializedVersion: 2
x: 728
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 5b29d8093de8b4c4e9c0b66b82deb1ed
internalID: -386358468
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_5"
rect:
serializedVersion: 2
x: 910
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: d3dc6fe9812df3049bad7f19730fb6ca
internalID: -1287565805
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_6"
rect:
serializedVersion: 2
x: 1092
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 4bf8ebffad0c6f44e9abb099429e3722
internalID: -2040738244
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_7"
rect:
serializedVersion: 2
x: 1274
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 3e080f56cdb5b8b48b4b1ccefabc8de9
internalID: 1625432532
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_8"
rect:
serializedVersion: 2
x: 1456
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 2360c3e26ec123b48ad8357e748b657d
internalID: 1848882051
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_9"
rect:
serializedVersion: 2
x: 1638
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 8eab2dccbc20b3f4d9a5b0d9f995fc6f
internalID: -1381685395
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_10"
rect:
serializedVersion: 2
x: 1820
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 92f5a9e142ea3ec4fae5990f3153dd34
internalID: -641158983
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_11"
rect:
serializedVersion: 2
x: 2002
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: b37db88e2759412468c4b61d6238fd01
internalID: -1931024059
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_12"
rect:
serializedVersion: 2
x: 2184
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: d485e426994f5ca4c91c6b0256e63f35
internalID: -1103357223
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_13"
rect:
serializedVersion: 2
x: 2366
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: b377314d703afef4bbb2da26559342e0
internalID: 596276626
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_14"
rect:
serializedVersion: 2
x: 2548
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 9ef6d368720f1e14796cf8f3d991c4db
internalID: 766679972
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: "LOADING \u7F50\u5934_15"
rect:
serializedVersion: 2
x: 2730
y: 0
width: 182
height: 222
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
outline: []
physicsShape: []
tessellationDetail: 0
bones: []
spriteID: 15c7470169f38ed4184bc11b865b772d
internalID: 908783198
vertices: []
indices:
edges: []
weights: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable:
"LOADING \u7F50\u5934_0": 1719050414
"LOADING \u7F50\u5934_1": -1164775371
"LOADING \u7F50\u5934_10": -641158983
"LOADING \u7F50\u5934_11": -1931024059
"LOADING \u7F50\u5934_12": -1103357223
"LOADING \u7F50\u5934_13": 596276626
"LOADING \u7F50\u5934_14": 766679972
"LOADING \u7F50\u5934_15": 908783198
"LOADING \u7F50\u5934_2": -1244389054
"LOADING \u7F50\u5934_3": -1957662414
"LOADING \u7F50\u5934_4": -386358468
"LOADING \u7F50\u5934_5": -1287565805
"LOADING \u7F50\u5934_6": -2040738244
"LOADING \u7F50\u5934_7": 1625432532
"LOADING \u7F50\u5934_8": 1848882051
"LOADING \u7F50\u5934_9": -1381685395
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,72 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-6608008813301334011
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: New State
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: da64c7b441e509c4f8a07f47647dc313, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Loading
serializedVersion: 5
m_AnimatorParameters: []
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 3638069603095265619}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1107 &3638069603095265619
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -6608008813301334011}
m_Position: {x: 390, y: 260, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 20, z: 0}
m_EntryPosition: {x: 50, y: 120, z: 0}
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -6608008813301334011}
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4efe920582e4eb84eabc738f16624d2b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 9100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,20 @@
{
"type": "manual",
"layout": {
"rows": 1,
"columns": 17,
"frameCount": 16,
"direction": "horizontal"
},
"frameDuration": 200,
"sampleRate": 60,
"animations": [
{
"name": "loading",
"frameIndices": [
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
],
"loop": true
}
]
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 16afd6b9dee930748902c25e1db009de
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+120
View File
@@ -0,0 +1,120 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: loading
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves: []
m_PositionCurves: []
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 1719050414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.1
value: {fileID: -1164775371, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.2
value: {fileID: -1244389054, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.3
value: {fileID: -1957662414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.4
value: {fileID: -386358468, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.5
value: {fileID: -1287565805, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.6
value: {fileID: -2040738244, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.7
value: {fileID: 1625432532, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.8
value: {fileID: 1848882051, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 0.9
value: {fileID: -1381685395, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1
value: {fileID: -641158983, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.1
value: {fileID: -1931024059, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.2
value: {fileID: -1103357223, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.3
value: {fileID: 596276626, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.4
value: {fileID: 766679972, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.5
value: {fileID: 908783198, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- time: 1.6
value: {fileID: 1719050414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
attribute: m_Sprite
path:
classID: 114
script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
flags: 2
m_SampleRate: 120
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 2015549526
script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
typeID: 114
customType: 0
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 1719050414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1164775371, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1244389054, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1957662414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -386358468, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1287565805, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -2040738244, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 1625432532, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 1848882051, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1381685395, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -641158983, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1931024059, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: -1103357223, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 596276626, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 766679972, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 908783198, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
- {fileID: 1719050414, guid: 4af5cf244c618df42813f45ce20338ea, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1.6083333
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves: []
m_EulerEditorCurves: []
m_HasGenericRootTransform: 0
m_HasMotionFloatCurves: 0
m_Events: []
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: da64c7b441e509c4f8a07f47647dc313
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant: