diff --git a/Runtime/ABase/Extension/UnityEngine.Common/UnityEngine.CommonExtensions.cs b/Runtime/ABase/Extension/UnityEngine.Common/UnityEngine.CommonExtensions.cs
index 9e841be..8ac3867 100644
--- a/Runtime/ABase/Extension/UnityEngine.Common/UnityEngine.CommonExtensions.cs
+++ b/Runtime/ABase/Extension/UnityEngine.Common/UnityEngine.CommonExtensions.cs
@@ -1,5 +1,7 @@
+using System;
using AlicizaX;
using UnityEngine.UI;
+using UnityEngine.SceneManagement;
namespace UnityEngine
{
@@ -82,6 +84,42 @@ namespace UnityEngine
}
}
+ [UnityEngine.Scripting.Preserve]
+ public static class RendererExtensions
+ {
+ public static bool IsVisibleFrom(this Renderer renderer, Camera camera)
+ {
+ Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
+ return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
+ }
+ }
+
+ [UnityEngine.Scripting.Preserve]
+ public static class CameraExtensions
+ {
+ public static Texture2D GetCaptureScreenshot(this Camera camera, float scale = 0.5f)
+ {
+ Rect rect = new Rect(0f, 0f, Screen.width * scale, Screen.height * scale);
+ string name = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
+ RenderTexture renderTexture = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 0);
+ renderTexture.name = SceneManager.GetActiveScene().name + "_" + renderTexture.width + "_" + renderTexture.height + "_" + name;
+ camera.targetTexture = renderTexture;
+ camera.Render();
+
+ RenderTexture.active = renderTexture;
+ Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false)
+ {
+ name = renderTexture.name
+ };
+ screenShot.ReadPixels(rect, 0, 0);
+ screenShot.Apply();
+ camera.targetTexture = null;
+ RenderTexture.active = null;
+ RenderTexture.ReleaseTemporary(renderTexture);
+ return screenShot;
+ }
+ }
+
[UnityEngine.Scripting.Preserve]
public static class AngleExtensions
{
diff --git a/Runtime/ABase/Extension/UnityEngine.Vector3/Vector3Extensions.cs b/Runtime/ABase/Extension/UnityEngine.Vector3/Vector3Extensions.cs
index 02cebc0..5d5d477 100644
--- a/Runtime/ABase/Extension/UnityEngine.Vector3/Vector3Extensions.cs
+++ b/Runtime/ABase/Extension/UnityEngine.Vector3/Vector3Extensions.cs
@@ -34,5 +34,35 @@
lhs.Scale(rhs);
return lhs;
}
+
+ ///
+ /// 将三维向量投影到 XZ 平面。
+ ///
+ public static Vector2 IgnoreYAxis(this Vector3 vector3)
+ {
+ return new Vector2(vector3.x, vector3.z);
+ }
+
+ ///
+ /// 保留 XZ 分量并清空 Y 轴。
+ ///
+ public static Vector3 FlattenY(this Vector3 vector3)
+ {
+ return new Vector3(vector3.x, 0f, vector3.z);
+ }
+
+ ///
+ /// 判断目标点是否位于当前方向的左侧。
+ ///
+ public static bool PointOnLeftSideOfVector(this Vector3 vector3, Vector3 originPoint, Vector3 point)
+ {
+ Vector2 origin = originPoint.IgnoreYAxis();
+ Vector2 targetDirection = (point.IgnoreYAxis() - origin).normalized;
+ Vector2 direction = vector3.IgnoreYAxis();
+ float verticalX = origin.x;
+ float verticalY = (-verticalX * direction.x) / direction.y;
+ Vector2 normalVertical = new Vector2(verticalX, verticalY).normalized;
+ return Vector2.Dot(normalVertical, targetDirection) < 0f;
+ }
}
}
diff --git a/Runtime/ABase/Helper/CompressionUtility.cs b/Runtime/ABase/Helper/CompressionUtility.cs
deleted file mode 100644
index 3547fee..0000000
--- a/Runtime/ABase/Helper/CompressionUtility.cs
+++ /dev/null
@@ -1,206 +0,0 @@
-using AlicizaX;
-using ICSharpCode.SharpZipLib.GZip;
-using System;
-using System.IO;
-
-namespace AlicizaX
-{
- ///
- /// 默认压缩解压缩辅助器。
- ///
- [UnityEngine.Scripting.Preserve]
- public class CompressionUtility
- {
- private const int CachedBytesLength = 0x1000;
- private static readonly byte[] m_CachedBytes = new byte[CachedBytesLength];
-
- ///
- /// 压缩数据。
- ///
- /// 要压缩的数据的二进制流。
- /// 要压缩的数据的二进制流的偏移。
- /// 要压缩的数据的二进制流的长度。
- /// 压缩后的数据的二进制流。
- /// 是否压缩数据成功。
- public static bool Compress(byte[] bytes, int offset, int length, Stream compressedStream)
- {
- if (bytes == null)
- {
- return false;
- }
-
- if (offset < 0 || length < 0 || offset + length > bytes.Length)
- {
- return false;
- }
-
- if (compressedStream == null)
- {
- return false;
- }
-
- try
- {
- GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream);
- gZipOutputStream.Write(bytes, offset, length);
- gZipOutputStream.Finish();
- ProcessHeader(compressedStream);
- return true;
- }
- catch
- {
- return false;
- }
- }
-
- ///
- /// 压缩数据。
- ///
- /// 要压缩的数据的二进制流。
- /// 压缩后的数据的二进制流。
- /// 是否压缩数据成功。
- public static bool Compress(Stream stream, Stream compressedStream)
- {
- if (stream == null)
- {
- return false;
- }
-
- if (compressedStream == null)
- {
- return false;
- }
-
- try
- {
- GZipOutputStream gZipOutputStream = new GZipOutputStream(compressedStream);
- int bytesRead = 0;
- while ((bytesRead = stream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
- {
- gZipOutputStream.Write(m_CachedBytes, 0, bytesRead);
- }
-
- gZipOutputStream.Finish();
- ProcessHeader(compressedStream);
- return true;
- }
- catch
- {
- return false;
- }
- finally
- {
- Array.Clear(m_CachedBytes, 0, CachedBytesLength);
- }
- }
-
- ///
- /// 解压缩数据。
- ///
- /// 要解压缩的数据的二进制流。
- /// 要解压缩的数据的二进制流的偏移。
- /// 要解压缩的数据的二进制流的长度。
- /// 解压缩后的数据的二进制流。
- /// 是否解压缩数据成功。
- public static bool Decompress(byte[] bytes, int offset, int length, Stream decompressedStream)
- {
- if (bytes == null)
- {
- return false;
- }
-
- if (offset < 0 || length < 0 || offset + length > bytes.Length)
- {
- return false;
- }
-
- if (decompressedStream == null)
- {
- return false;
- }
-
- MemoryStream memoryStream = null;
- try
- {
- memoryStream = new MemoryStream(bytes, offset, length, false);
- using (GZipInputStream gZipInputStream = new GZipInputStream(memoryStream))
- {
- int bytesRead = 0;
- while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
- {
- decompressedStream.Write(m_CachedBytes, 0, bytesRead);
- }
- }
-
- return true;
- }
- catch
- {
- return false;
- }
- finally
- {
- if (memoryStream != null)
- {
- memoryStream.Dispose();
- memoryStream = null;
- }
-
- Array.Clear(m_CachedBytes, 0, CachedBytesLength);
- }
- }
-
- ///
- /// 解压缩数据。
- ///
- /// 要解压缩的数据的二进制流。
- /// 解压缩后的数据的二进制流。
- /// 是否解压缩数据成功。
- public static bool Decompress(Stream stream, Stream decompressedStream)
- {
- if (stream == null)
- {
- return false;
- }
-
- if (decompressedStream == null)
- {
- return false;
- }
-
- try
- {
- GZipInputStream gZipInputStream = new GZipInputStream(stream);
- int bytesRead = 0;
- while ((bytesRead = gZipInputStream.Read(m_CachedBytes, 0, CachedBytesLength)) > 0)
- {
- decompressedStream.Write(m_CachedBytes, 0, bytesRead);
- }
-
- return true;
- }
- catch
- {
- return false;
- }
- finally
- {
- Array.Clear(m_CachedBytes, 0, CachedBytesLength);
- }
- }
-
- private static void ProcessHeader(Stream compressedStream)
- {
- if (compressedStream.Length >= 8L)
- {
- long current = compressedStream.Position;
- compressedStream.Position = 4L;
- compressedStream.WriteByte(25);
- compressedStream.WriteByte(134);
- compressedStream.WriteByte(2);
- compressedStream.WriteByte(32);
- compressedStream.Position = current;
- }
- }
- }
-}
diff --git a/Runtime/ABase/Helper/GameHelper.cs b/Runtime/ABase/Helper/GameHelper.cs
deleted file mode 100644
index 0787f17..0000000
--- a/Runtime/ABase/Helper/GameHelper.cs
+++ /dev/null
@@ -1,1013 +0,0 @@
-using System.Linq;
-using System.Globalization;
-using System.Collections.Generic;
-
-using System.Text.RegularExpressions;
-using AlicizaX;
-using UnityEngine;
-using UnityEngine.UI;
-
-#if UNITY_EDITOR
-using UnityEditor;
-#endif
-
-namespace UnityEngine
-{
- public static class GameHelper
- {
-
-
- ///
- /// Change color alpha (0 is transparent, 1 is opaque).
- ///
- public static Color Alpha(this Color col, float alpha)
- {
- col.a = alpha;
- return col;
- }
-
- ///
- /// Change lightness of the color.
- ///
- public static Color Lightness(this Color col, float lightness)
- {
- Color.RGBToHSV(col, out var hue, out var saturation, out var _);
- return Color.HSVToRGB(hue, saturation, lightness);
- }
-
- ///
- /// Change image color alpha (0 is transparent, 1 is opaque).
- ///
- public static void Alpha(this Image image, float alpha)
- {
- Color color = image.color;
- color.a = alpha;
- image.color = color;
- }
-
- ///
- /// Set Sound Clip to the Audio Source.
- ///
- public static void SetSoundClip(this AudioSource audioSource, SoundClip soundClip, float volumeMul = 1f, bool play = false)
- {
- if (soundClip == null || soundClip.audioClip == null || audioSource == null) return;
-
- if (audioSource.clip != soundClip.audioClip)
- audioSource.clip = soundClip.audioClip;
-
- audioSource.volume = soundClip.volume * volumeMul;
-
- if(play && !audioSource.isPlaying)
- audioSource.Play();
- }
-
- ///
- /// Play One Shot Sudio Clip in the audio source.
- ///
- public static void PlayOneShotSoundClip(this AudioSource audioSource, SoundClip soundClip, float volumeMul = 1f)
- {
- if (soundClip == null || soundClip.audioClip == null || audioSource == null)
- return;
-
- audioSource.PlayOneShot(soundClip.audioClip, soundClip.volume * volumeMul);
- }
-
- ///
- /// Create new unique Guid.
- ///
- public static string GetGuid() => System.Guid.NewGuid().ToString("N");
-
- ///
- /// Change the GameObject layer including all children.
- ///
- public static void SetLayerRecursively(this GameObject obj, int layer)
- {
- if (layer < 0 || layer > 31)
- {
- Debug.LogError("Invalid layer value. Must be between 0 and 31.");
- return;
- }
-
- obj.layer = layer;
-
- foreach (Transform child in obj.transform)
- {
- child.gameObject.SetLayerRecursively(layer);
- }
- }
-
- ///
- /// Set the rendering layer of the MeshRenderer in the GameObject.
- ///
- public static void SetRenderingLayer(this GameObject obj, uint layer, bool set = true)
- {
- if (layer < 0 || layer > 31)
- {
- Debug.LogError("Invalid layer value. Must be between 0 and 31.");
- return;
- }
-
- uint layerMask = 1u << (int)layer;
-
- foreach (MeshRenderer renderer in obj.GetComponentsInChildren())
- {
- if (set) renderer.renderingLayerMask |= layerMask;
- else renderer.renderingLayerMask &= ~layerMask;
- }
- }
-
- ///
- /// Basic raycast with interact layer checking.
- ///
- /// Status whether the object hit by the raycast has an interact layer.
- public static bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int cullLayers, Layer interactLayer)
- {
- if (Physics.Raycast(ray, out RaycastHit hit, maxDistance, cullLayers))
- {
- if (interactLayer.CompareLayer(hit.collider.gameObject))
- {
- hitInfo = hit;
- return true;
- }
- }
-
- hitInfo = default;
- return false;
- }
-
- ///
- /// Check if the value-A and value-B are close to the tolerance.
- ///
- public static bool IsApproximate(float valueA, float valueB, float tollerance)
- {
- return Mathf.Abs(valueA - valueB) < tollerance;
- }
-
- ///
- /// Correct the Angle.
- ///
- public static float FixAngle(this float angle, float min, float max)
- {
- if (angle < min)
- angle += 360F;
- if (angle > max)
- angle -= 360F;
-
- return angle;
- }
-
- ///
- /// Correct the Angle (-180, 180).
- ///
- public static float FixAngle180(this float angle)
- {
- if (angle < -180F)
- angle += 360F;
- if (angle > 180F)
- angle -= 360F;
-
- return angle;
- }
-
- ///
- /// Correct the Angle (-360, 360).
- ///
- public static float FixAngle(this float angle)
- {
- if (angle < -360F)
- angle += 360F;
- if (angle > 360F)
- angle -= 360F;
-
- return angle;
- }
-
- ///
- /// Correct the Angle (0 - 360).
- ///
- public static float FixAngle360(this float angle)
- {
- if (angle < 0)
- angle += 360F;
- if (angle > 360F)
- angle -= 360F;
-
- return angle;
- }
-
- ///
- /// Check if value is in vector range.
- ///
- public static bool InRange(this Vector2 vector, float value, bool equal = false)
- {
- return equal ? value >= vector.x && value <= vector.y :
- value > vector.x && value < vector.y;
- }
-
- ///
- /// Check if value is in vector degrees.
- ///
- public static bool InDegrees(this Vector2 vector, float value, bool equal = false)
- {
- if(vector.x > vector.y)
- {
- return equal ? value >= (vector.x - 360) && value <= vector.y :
- value > (vector.x - 360) && value < vector.y;
- }
- else
- {
- return equal ? value >= vector.x && value <= vector.y :
- value > vector.x && value < vector.y;
- }
- }
-
- ///
- /// Convert string to title case.
- ///
- public static string ToTitleCase(this string str)
- {
- return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str.ToLower());
- }
-
- ///
- /// Check if string is empty.
- ///
- public static bool IsEmpty(this string str)
- {
- return string.IsNullOrEmpty(str);
- }
-
- ///
- /// Returns a string or otherwise if the string is empty.
- ///
- public static string Or(this string str, string otherwise)
- {
- return !string.IsNullOrEmpty(str) ? str : otherwise;
- }
-
- ///
- /// Compare Layer with LayerMask.
- ///
- public static bool CompareLayer(this LayerMask layermask, int layer)
- {
- return layermask == (layermask | (1 << layer));
- }
-
- ///
- /// Function to generate a random integer number (No Duplicates).
- ///
- public static int RandomUnique(int min, int max, int last)
- {
- System.Random rnd = new System.Random();
-
- if (min + 1 < max)
- {
- return Enumerable.Range(min, max).OrderBy(x => rnd.Next()).Where(x => x != last).Take(1).Single();
- }
- else
- {
- return min;
- }
- }
-
- ///
- /// Function to generate a random integer without excluded numbers.
- ///
- public static int RandomExclude(int min, int max, int[] ex, int maxIterations = 1000)
- {
- int result;
- int iterations = 0;
-
- do
- {
- if (iterations > maxIterations)
- {
- result = -1;
- break;
- }
-
- result = UnityEngine.Random.Range(min, max);
- iterations++;
- }
- while (ex.Contains(result));
-
- return result;
- }
-
- ///
- /// Function to generate a random unique integer without excluded numbers.
- ///
- public static int RandomExcludeUnique(int min, int max, int[] ex, int[] current, int maxIterations = 1000)
- {
- return RandomExclude(min, max, ex.Concat(current).ToArray(), maxIterations);
- }
-
- ///
- /// Pick a random element from item array.
- ///
- public static T Random(this T[] items)
- {
- System.Random rnd = new System.Random();
- if(items.Length > 0) return items[rnd.Next(0, items.Length)];
- return default;
- }
-
- ///
- /// Get Random Value from Min/Max vector.
- ///
- public static float Random(this Vector2 vector)
- {
- return UnityEngine.Random.Range(vector.x, vector.y);
- }
-
- ///
- /// Get Random Value from Min/Max structure.
- ///
- public static float Random(this MinMax minMax)
- {
- return UnityEngine.Random.Range(minMax.RealMin, minMax.RealMax);
- }
-
- ///
- /// Get Random Value from Min/Max structure.
- ///
- public static int Random(this MinMaxInt minMax)
- {
- return UnityEngine.Random.Range(minMax.RealMin, minMax.RealMax);
- }
-
- ///
- /// Oscillate between the two values at speed.
- ///
- public static float PingPong(float min, float max, float speed = 1f)
- {
- return Mathf.PingPong(Time.time * speed, max - min) + min;
- }
-
- ///
- /// Wrap value between min and max values.
- ///
- public static int Wrap(int value, int min, int max)
- {
- int newValue = value % max;
- if (newValue < min) newValue = max - 1;
- return newValue;
- }
-
- ///
- /// Determines where a value lies between three points.
- ///
- public static float InverseLerp3(float min, float mid, float max, float t)
- {
- if (t <= min) return 0f;
- if (t >= max) return 0f;
-
- if (t <= mid) return Mathf.InverseLerp(min, mid, t);
- else return 1f - Mathf.InverseLerp(mid, max, t);
- }
-
- ///
- /// Get closest index from an integer array using a value.
- ///
- public static int ClosestIndex(this int[] array, int value)
- {
- int closestIndex = 0;
- int minDifference = Mathf.Abs(array[0] - value);
-
- for (int i = 1; i < array.Length; i++)
- {
- int difference = Mathf.Abs(array[i] - value);
- if (difference < minDifference)
- {
- minDifference = difference;
- closestIndex = i;
- }
- }
-
- return closestIndex;
- }
-
- ///
- /// Play OneShot Audio Clip 2D.
- ///
- public static AudioSource PlayOneShot2D(Vector3 position, AudioClip clip, float volume = 1f, string name = "OneShotAudio")
- {
- if(clip == null)
- return null;
-
- GameObject go = new GameObject(name);
- go.transform.position = position;
- AudioSource source = go.AddComponent();
- source.spatialBlend = 0f;
- source.clip = clip;
- source.volume = volume;
- source.Play();
- Object.Destroy(go, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
- return source;
- }
-
- ///
- /// Play OneShot Sound Clip 3D.
- ///
- public static AudioSource PlayOneShot2D(Vector3 position, SoundClip clip, string name = "OneShotAudio")
- {
- if (clip == null || clip.audioClip == null)
- return null;
-
- AudioClip audioClip = clip.audioClip;
- float volume = clip.volume;
- return PlayOneShot2D(position, audioClip, volume, name);
- }
-
- ///
- /// Play OneShot Audio Clip 3D.
- ///
- public static AudioSource PlayOneShot3D(Vector3 position, AudioClip clip, float volume = 1f, string name = "OneShotAudio")
- {
- if (clip == null)
- return null;
-
- GameObject go = new GameObject(name);
- go.transform.position = position;
- AudioSource source = go.AddComponent();
- source.spatialBlend = 1f;
- source.clip = clip;
- source.volume = volume;
- source.Play();
- Object.Destroy(go, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
- return source;
- }
-
- ///
- /// Play OneShot Audio Clip 3D.
- ///
- public static AudioSource PlayOneShot3D(Vector3 position, AudioClip clip, float maxDistance, float volume = 1f, string name = "OneShotAudio")
- {
- if (clip == null)
- return null;
-
- GameObject go = new GameObject(name);
- go.transform.position = position;
- AudioSource source = go.AddComponent();
- source.spatialBlend = 1f;
- source.clip = clip;
- source.volume = volume;
- source.maxDistance = maxDistance;
- source.Play();
- Object.Destroy(go, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
- return source;
- }
-
- ///
- /// Play OneShot Sound Clip 3D.
- ///
- public static AudioSource PlayOneShot3D(Vector3 position, SoundClip clip, string name = "OneShotAudio")
- {
- if (clip == null || clip.audioClip == null)
- return null;
-
- AudioClip audioClip = clip.audioClip;
- float volume = clip.volume;
- return PlayOneShot3D(position, audioClip, volume, name);
- }
-
- ///
- /// Remap range A to range B.
- ///
- public static float Remap(float minA, float maxA, float minB, float maxB, float t)
- {
- return minB + (t - minA) * (maxB - minB) / (maxA - minA);
- }
-
- ///
- /// Replace string part inside two chars
- ///
- public static string ReplacePart(this string str, char start, char end, string replace)
- {
- int chStart = str.IndexOf(start);
- int chEnd = str.IndexOf(end);
- string old = str.Substring(chStart, chEnd - chStart + 1);
- return str.Replace(old, replace);
- }
-
- ///
- /// Replace tag inside two chars (Regex).
- ///
- public static string RegexReplaceTag(this string str, char start, char end, string tag, string replace)
- {
- Regex regex = new Regex($@"\{start}({tag})\{end}");
- if(regex.Match(str).Success)
- return regex.Replace(str, replace);
-
- return str;
- }
-
- ///
- /// Get a value between two chars (Regex).
- ///
- public static bool RegexGet(this string str, char start, char end, out string result)
- {
- // escaping special characters if necessary
- string escapedStart = Regex.Escape(start.ToString());
- string escapedEnd = Regex.Escape(end.ToString());
-
- // regex pattern to match text between 'start' and 'end' characters
- string pattern = $"{escapedStart}(.*?){escapedEnd}";
-
- Match match = Regex.Match(str, pattern);
- if (match.Success)
- {
- result = match.Groups[1].Value;
- return true;
- }
-
- result = string.Empty;
- return false;
- }
-
- ///
- /// Get all values between two chars (Regex).
- ///
- public static bool RegexGetMany(this string str, char start, char end, out string[] results)
- {
- // escaping special characters if necessary
- string escapedStart = Regex.Escape(start.ToString());
- string escapedEnd = Regex.Escape(end.ToString());
-
- // regex pattern to match text between 'start' and 'end' characters
- string pattern = $"{escapedStart}(.*?){escapedEnd}";
-
- // using Regex.Matches to find all matches
- MatchCollection matches = Regex.Matches(str, pattern);
-
- // check if there are any matches
- if (matches.Count > 0)
- {
- // initialize a list to hold the results
- List matchList = new List();
-
- foreach (Match match in matches)
- {
- // add each found match to the list, excluding the 'start' and 'end' characters
- matchList.Add(match.Groups[1].Value);
- }
-
- // convert the list to an array and assign to 'results'
- results = matchList.ToArray();
- return true;
- }
-
- results = new string[0];
- return false;
- }
-
- ///
- /// Replace a word in string (Regex).
- ///
- public static string RegexReplace(this string str, string word, string replace)
- {
- string escapedWord = Regex.Escape(word);
- string pattern = $@"\b{escapedWord}\b";
-
- // replace the word with the provided replacement text
- return Regex.Replace(str, pattern, replace);
- }
-
- ///
- /// Check if any animator state is being played.
- ///
- public static bool IsAnyPlaying(this Animator animator)
- {
- AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
- return (stateInfo.length + 0.1f > stateInfo.normalizedTime || animator.IsInTransition(0)) && !stateInfo.IsName("Default");
- }
-
- ///
- /// Applies an ease-out easing function, which starts the interpolation quickly and then slows down as it approaches the end point.
- ///
- public static float EaseOut(float start, float end, float t)
- {
- t = Mathf.Clamp01(t);
- t = Mathf.Sin(t * Mathf.PI * 0.5f);
- return Mathf.Lerp(start, end, t);
- }
-
- ///
- /// Applies an ease-in easing function, which starts the interpolation slowly and then accelerates as it approaches the end point.
- ///
- public static float EaseIn(float start, float end, float t)
- {
- t = Mathf.Clamp01(t);
- t = 1f - Mathf.Cos(t * Mathf.PI * 0.5f);
- return Mathf.Lerp(start, end, t);
- }
-
- ///
- /// Implements a smooth step interpolation, offering a more gradual and smoother transition.
- ///
- ///
- /// Use this when you want an even gentler and smoother transition, especially for animations.
- ///
- public static float SmootherStep(float start, float end, float t)
- {
- t = Mathf.Clamp01(t);
- t = t * t * t * (t * (6f * t - 15f) + 10f);
- return Mathf.Lerp(start, end, t);
- }
- }
-
- public static class GizmosE
- {
- ///
- /// Draw arrow using gizmos.
- ///
- public static void DrawGizmosArrow(Vector3 pos, Vector3 direction, float arrowHeadLength = 0.25f, float arrowHeadAngle = 20.0f)
- {
- Gizmos.DrawRay(pos, direction);
-
- Vector3 right = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 + arrowHeadAngle, 0) * new Vector3(0, 0, 1);
- Vector3 left = Quaternion.LookRotation(direction) * Quaternion.Euler(0, 180 - arrowHeadAngle, 0) * new Vector3(0, 0, 1);
- Gizmos.DrawRay(pos + direction, right * arrowHeadLength);
- Gizmos.DrawRay(pos + direction, left * arrowHeadLength);
- }
-
- ///
- /// Draw wire capsule.
- ///
- public static void DrawWireCapsule(Vector3 p1, Vector3 p2, float radius)
- {
-#if UNITY_EDITOR
- // Special case when both points are in the same position
- if (p1 == p2)
- {
- // DrawWireSphere works only in gizmo methods
- Gizmos.DrawWireSphere(p1, radius);
- return;
- }
- using (new Handles.DrawingScope(Gizmos.color, Gizmos.matrix))
- {
- Quaternion p1Rotation = Quaternion.LookRotation(p1 - p2);
- Quaternion p2Rotation = Quaternion.LookRotation(p2 - p1);
-
- // Check if capsule direction is collinear to Vector.up
- float c = Vector3.Dot((p1 - p2).normalized, Vector3.up);
- if (c == 1f || c == -1f)
- {
- // Fix rotation
- p2Rotation = Quaternion.Euler(p2Rotation.eulerAngles.x, p2Rotation.eulerAngles.y + 180f, p2Rotation.eulerAngles.z);
- }
-
- // First side
- Handles.DrawWireArc(p1, p1Rotation * Vector3.left, p1Rotation * Vector3.down, 180f, radius);
- Handles.DrawWireArc(p1, p1Rotation * Vector3.up, p1Rotation * Vector3.left, 180f, radius);
- Handles.DrawWireDisc(p1, (p2 - p1).normalized, radius);
- // Second side
- Handles.DrawWireArc(p2, p2Rotation * Vector3.left, p2Rotation * Vector3.down, 180f, radius);
- Handles.DrawWireArc(p2, p2Rotation * Vector3.up, p2Rotation * Vector3.left, 180f, radius);
- Handles.DrawWireDisc(p2, (p1 - p2).normalized, radius);
- // Lines
- Handles.DrawLine(p1 + p1Rotation * Vector3.down * radius, p2 + p2Rotation * Vector3.down * radius);
- Handles.DrawLine(p1 + p1Rotation * Vector3.left * radius, p2 + p2Rotation * Vector3.right * radius);
- Handles.DrawLine(p1 + p1Rotation * Vector3.up * radius, p2 + p2Rotation * Vector3.up * radius);
- Handles.DrawLine(p1 + p1Rotation * Vector3.right * radius, p2 + p2Rotation * Vector3.left * radius);
- }
-#endif
- }
-
- ///
- /// Draw wire capsule.
- ///
- public static void DrawWireCapsule(Vector3 position, Quaternion rotation, float radius, float height)
- {
-#if UNITY_EDITOR
- Matrix4x4 angleMatrix = Matrix4x4.TRS(position, rotation, Handles.matrix.lossyScale);
- using (new Handles.DrawingScope(angleMatrix))
- {
- var pointOffset = (height - (radius * 2)) / 2;
-
- //draw sideways
- Handles.DrawWireArc(Vector3.up * pointOffset, Vector3.left, Vector3.back, -180, radius);
- Handles.DrawLine(new Vector3(0, pointOffset, -radius), new Vector3(0, -pointOffset, -radius));
- Handles.DrawLine(new Vector3(0, pointOffset, radius), new Vector3(0, -pointOffset, radius));
- Handles.DrawWireArc(Vector3.down * pointOffset, Vector3.left, Vector3.back, 180, radius);
- //draw frontways
- Handles.DrawWireArc(Vector3.up * pointOffset, Vector3.back, Vector3.left, 180, radius);
- Handles.DrawLine(new Vector3(-radius, pointOffset, 0), new Vector3(-radius, -pointOffset, 0));
- Handles.DrawLine(new Vector3(radius, pointOffset, 0), new Vector3(radius, -pointOffset, 0));
- Handles.DrawWireArc(Vector3.down * pointOffset, Vector3.back, Vector3.left, -180, radius);
- //draw center
- Handles.DrawWireDisc(Vector3.up * pointOffset, Vector3.up, radius);
- Handles.DrawWireDisc(Vector3.down * pointOffset, Vector3.up, radius);
-
- }
-#endif
- }
-
- ///
- /// Draw the label aligned to the center of the position.
- ///
- public static void DrawCenteredLabel(Vector3 position, string labelText, GUIStyle style = null)
- {
-#if UNITY_EDITOR
- if (style == null) style = new GUIStyle(GUI.skin.label);
-
- GUIContent content = new GUIContent(labelText);
- Vector2 labelSize = style.CalcSize(content);
-
- // Calculate the offset to center the label
- Vector3 screenPosition = HandleUtility.WorldToGUIPoint(position);
- screenPosition.x -= labelSize.x / 2;
- screenPosition.y -= labelSize.y / 2;
- Vector3 worldPosition = HandleUtility.GUIPointToWorldRay(screenPosition).origin;
-
- Handles.Label(worldPosition, labelText, style);
-#endif
- }
-
- ///
- /// Draw disc at the position.
- ///
- public static void DrawDisc(Vector3 position, float radius, Color outerColor, Color innerColor)
- {
-#if UNITY_EDITOR
- Handles.color = innerColor;
- Handles.DrawSolidDisc(position, Vector3.up, radius);
- Handles.color = outerColor;
- Handles.DrawWireDisc(position, Vector3.up, radius);
-#endif
- }
- }
-
- public static class VectorE
- {
- ///
- /// Determines where a value lies between two vectors.
- ///
- public static float InverseLerp(Vector3 a, Vector3 b, Vector3 value)
- {
- if (a != b)
- {
- Vector3 AB = b - a;
- Vector3 AV = value - a;
- float t = Vector3.Dot(AV, AB) / Vector3.Dot(AB, AB);
- return Mathf.Clamp01(t);
- }
-
- return 0f;
- }
-
- ///
- /// Get position in Quadratic Bezier Curve.
- ///
- /// Starting point
- /// Ending point
- /// Control point
- public static Vector3 QuadraticBezier(Vector3 p1, Vector3 p2, Vector3 cp, float t)
- {
- t = Mathf.Clamp01(t);
- Vector3 m1 = Vector3.LerpUnclamped(p1, cp, t);
- Vector3 m2 = Vector3.LerpUnclamped(cp, p2, t);
- return Vector3.LerpUnclamped(m1, m2, t);
- }
-
- ///
- /// Bezier Curve between multiple points.
- ///
- public static Vector3 BezierCurve(float t, params Vector3[] points)
- {
- if (points.Length < 1) return Vector3.zero;
- else if (points.Length == 1) return points[0];
-
- t = Mathf.Clamp01(t);
- Vector3[] cp = points;
- int n = points.Length - 1;
-
- while (n > 1)
- {
- Vector3[] rp = new Vector3[n];
- for (int i = 0; i < rp.Length; i++)
- {
- rp[i] = Vector3.LerpUnclamped(cp[i], cp[i + 1], t);
- }
-
- cp = rp;
- n--;
- }
-
- return Vector3.LerpUnclamped(cp[0], cp[1], t);
- }
-
- ///
- /// Linearly interpolates between three points.
- ///
- public static Vector3 Lerp3(Vector3 a, Vector3 b, Vector3 c, float t)
- {
- t = Mathf.Clamp01(t);
- if (t <= 0.5f) return Vector3.LerpUnclamped(a, b, t * 2f);
- return Vector3.LerpUnclamped(b, c, (t * 2f) - 1f);
- }
-
- ///
- /// Linearly interpolates between multiple points.
- ///
- public static Vector3 RangeLerp(float t, params Vector3[] points)
- {
- if (points.Length < 1) return Vector3.zero;
- else if (points.Length == 1) return points[0];
-
- t = Mathf.Clamp01(t);
- int pointsCount = points.Length - 1;
- float scale = 1f / pointsCount;
- float remap = GameHelper.Remap(0, 1, 0, pointsCount, t);
- int index = Mathf.Clamp(Mathf.FloorToInt(remap), 0, pointsCount - 1);
- float indexT = Mathf.InverseLerp(index * scale, (index + 1) * scale, t);
- return Vector3.LerpUnclamped(points[index], points[index + 1], indexT);
- }
-
- ///
- /// Linearly interpolates between two, three or multiple points.
- ///
The function selects the best method for linear interpolation.
- ///
- public static Vector3 Lerp(float t, Vector3[] points)
- {
- if (points.Length > 3)
- {
- return RangeLerp(t, points);
- }
- else if (points.Length == 3)
- {
- return Lerp3(points[0], points[1], points[2], t);
- }
- else if (points.Length == 2)
- {
- return Vector3.Lerp(points[0], points[1], t);
- }
- else if (points.Length == 1)
- {
- return points[0];
- }
-
- return Vector3.zero;
- }
-
- ///
- /// Scale a vector by another vector and return the scaled vector.
- ///
- public static Vector3 Multiply(this Vector3 lhs, Vector3 rhs)
- {
- lhs.Scale(rhs);
- return lhs;
- }
-
- ///
- /// Checks if a collection contains all values from another collection.
- ///
- public static bool ContainsAll(this IEnumerable source, IEnumerable values)
- {
- return !source.Except(values).Any();
- }
- }
-
- public static class AxisE
- {
- ///
- /// Convert Axis to Vector3 Direction.
- ///
- public static Vector3 Convert(this Axis axis) => axis switch
- {
- Axis.X => Vector3.right,
- Axis.X_Negative => Vector3.left,
- Axis.Y => Vector3.up,
- Axis.Y_Negative => Vector3.down,
- Axis.Z => Vector3.forward,
- Axis.Z_Negative => Vector3.back,
- _ => Vector3.up,
- };
-
- ///
- /// Convert Axis to Transform Direction.
- ///
- public static Vector3 Direction(this Transform transform, Axis axis)
- {
- return axis switch
- {
- Axis.X => transform.right,
- Axis.X_Negative => -transform.right,
- Axis.Y => transform.up,
- Axis.Y_Negative => -transform.up,
- Axis.Z => transform.forward,
- Axis.Z_Negative => -transform.forward,
- _ => transform.up,
- };
- }
-
- ///
- /// Get Vector Axis Component.
- ///
- public static float Component(this Vector3 vector, Axis axis)
- {
- return axis switch
- {
- Axis.X or Axis.X_Negative => vector.x,
- Axis.Y or Axis.Y_Negative => vector.y,
- Axis.Z or Axis.Z_Negative => vector.z,
- _ => vector.y,
- };
- }
-
- ///
- /// Set Vector Axis Component Value.
- ///
- public static Vector3 SetComponent(this Vector3 vector, Axis axis, float value)
- {
- switch (axis)
- {
- case Axis.X:
- case Axis.X_Negative:
- vector.x = value; break;
- case Axis.Y:
- case Axis.Y_Negative:
- vector.y = value; break;
- case Axis.Z:
- case Axis.Z_Negative:
- vector.z = value; break;
- }
- return vector;
- }
-
- ///
- /// Clamp Vector Axis to Range.
- ///
- public static Vector3 Clamp(this Vector3 vector, Axis axis, MinMax limits)
- {
- switch (axis)
- {
- case Axis.X:
- case Axis.X_Negative:
- vector.x = Mathf.Clamp(vector.x, limits.RealMin, limits.RealMax); break;
- case Axis.Y:
- case Axis.Y_Negative:
- vector.y = Mathf.Clamp(vector.y, limits.RealMin, limits.RealMax); break;
- case Axis.Z:
- case Axis.Z_Negative:
- vector.z = Mathf.Clamp(vector.z, limits.RealMin, limits.RealMax); break;
- }
- return vector;
- }
- }
-
- public static class RectTransformE
- {
- public static void SetWidth(this RectTransform rectTransform, float width)
- {
- Vector2 size = rectTransform.sizeDelta;
- size.x = width;
- rectTransform.sizeDelta = size;
- }
-
- public static void SetHeight(this RectTransform rectTransform, float height)
- {
- Vector2 size = rectTransform.sizeDelta;
- size.y = height;
- rectTransform.sizeDelta = size;
- }
-
- public static void SetAnchoredX(this RectTransform rectTransform, float x)
- {
- Vector2 position = rectTransform.anchoredPosition;
- position.x = x;
- rectTransform.anchoredPosition = position;
- }
-
- public static void SetAnchoredY(this RectTransform rectTransform, float y)
- {
- Vector2 position = rectTransform.anchoredPosition;
- position.y = y;
- rectTransform.anchoredPosition = position;
- }
-
- public static IEnumerable GetChildTransforms(this RectTransform rectTransform)
- {
- foreach (var item in rectTransform)
- {
- yield return item as RectTransform;
- }
- }
- }
-
- public struct Pair
- {
- public T1 Key { get; set; }
- public T2 Value { get; set; }
- public bool IsAssigned
- {
- get => Key != null && Value != null;
- }
-
- public Pair(T1 key, T2 value)
- {
- Key = key;
- Value = value;
- }
- }
-}
diff --git a/Runtime/ABase/Helper/GameHelper.cs.meta b/Runtime/ABase/Helper/GameHelper.cs.meta
deleted file mode 100644
index 6bea2c8..0000000
--- a/Runtime/ABase/Helper/GameHelper.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: ef59646f457548b0962c49a3434cf7e3
-timeCreated: 1758265544
\ No newline at end of file
diff --git a/Runtime/ABase/Helper/PositionHelper.cs b/Runtime/ABase/Helper/PositionHelper.cs
deleted file mode 100644
index 7153975..0000000
--- a/Runtime/ABase/Helper/PositionHelper.cs
+++ /dev/null
@@ -1,150 +0,0 @@
-using UnityEngine;
-
-namespace AlicizaX
-{
- ///
- /// 坐标帮助类
- ///
- public static class PositionHelper
- {
- public static Vector3 RayCastV2ToV3(Vector2 pos)
- {
- return new Vector3(pos.x, 0, pos.y);
- }
-
- public static Vector3 RayCastXYToV3(float x, float y)
- {
- return new Vector3(x, 0, y);
- }
-
- public static Vector3 RayCastV3ToV3(Vector3 pos)
- {
- return new Vector3(pos.x, 0, pos.z);
- }
-
- public static Quaternion AngleToQuaternion(int angle)
- {
- return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90, Vector3.up);
- }
-
- public static Quaternion GetVector3ToQuaternion(Vector3 source, Vector3 dire)
- {
- Vector3 nowPos = source;
- if (nowPos == dire)
- {
- return new Quaternion();
- }
-
- Vector3 direction = (dire - nowPos).normalized;
- return Quaternion.LookRotation(direction, Vector3.up);
- }
-
-
- public static float Distance2D(Vector3 v1, Vector3 v2)
- {
- Vector2 d1 = new Vector2(v1.x, v1.z);
- Vector2 d2 = new Vector2(v2.x, v2.z);
- return Vector2.Distance(d1, d2);
- }
-
- public static Quaternion GetAngleToQuaternion(float angle)
- {
- return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90, Vector3.up);
- }
-
- public static float Vector3ToAngle360(Vector3 from, Vector3 to)
- {
- float angle = Vector3.Angle(from, to);
- Vector3 cross = Vector3.Cross(from, to);
- return cross.y > 0 ? angle : 360 - angle;
- }
-
- ///
- /// 求点到直线的距离,采用数学公式Ax+By+C = 0; d = A*p.x + B * p.y + C / sqrt(A^2 + B ^ 2)
- ///
- /// 线的起点
- /// 线的终点
- /// 点
- ///
- public static float DistanceOfPointToVector(Vector3 startPoint, Vector3 endPoint, Vector3 point)
- {
- Vector2 startVe2 = startPoint.IgnoreYAxis();
- Vector2 endVe2 = endPoint.IgnoreYAxis();
- float A = endVe2.y - startVe2.y;
- float B = startVe2.x - endVe2.x;
- float C = endVe2.x * startVe2.y - startVe2.x * endVe2.y;
- float denominator = Mathf.Sqrt(A * A + B * B);
- Vector2 pointVe2 = point.IgnoreYAxis();
- return Mathf.Abs((A * pointVe2.x + B * pointVe2.y + C) / denominator);
- ;
- }
-
- ///
- /// 判断射线是否碰撞到球体,如果碰撞到,返回射线起点到碰撞点之间的距离
- ///
- /// 射线
- /// 中心点
- /// 半径
- /// 距离
- ///
- public static bool RayCastSphere(Ray ray, Vector3 center, float redis, out float dist)
- {
- dist = 0;
- Vector3 ma = center - ray.origin;
- float distance = Vector3.Cross(ma, ray.direction).magnitude / ray.direction.magnitude;
- if (distance < redis)
- {
- float op = PythagoreanTheorem(Vector3.Distance(center, ray.origin), distance);
- float rp = PythagoreanTheorem(redis, distance);
- dist = op - rp;
- return true;
- }
-
- return false;
- }
-
- ///
- /// 勾股定理
- ///
- ///
- ///
- ///
- public static float PythagoreanTheorem(float x, float y)
- {
- return Mathf.Sqrt(x * x + y * y);
- }
-
- ///
- /// 去掉三维向量的Y轴,把向量投射到xz平面。
- ///
- ///
- ///
- public static Vector2 IgnoreYAxis(this Vector3 vector3)
- {
- return new Vector2(vector3.x, vector3.z);
- }
-
- ///
- /// 判断目标点是否位于向量的左边
- ///
- /// True is on left, false is on right
- public static bool PointOnLeftSideOfVector(this Vector3 vector3, Vector3 originPoint, Vector3 point)
- {
- Vector2 originVec2 = originPoint.IgnoreYAxis();
-
- Vector2 pointVec2 = (point.IgnoreYAxis() - originVec2).normalized;
-
- Vector2 vector2 = vector3.IgnoreYAxis();
-
- float verticalX = originVec2.x;
-
- float verticalY = (-verticalX * vector2.x) / vector2.y;
-
- Vector2 norVertical = (new Vector2(verticalX, verticalY)).normalized;
-
- float dotValue = Vector2.Dot(norVertical, pointVec2);
-
- return dotValue < 0f;
- }
- }
-}
diff --git a/Runtime/ABase/Helper/PositionHelper.cs.meta b/Runtime/ABase/Helper/PositionHelper.cs.meta
deleted file mode 100644
index a0eb9de..0000000
--- a/Runtime/ABase/Helper/PositionHelper.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: fb356e4ecfd547b280b88ca74a847918
-timeCreated: 1666447289
\ No newline at end of file
diff --git a/Runtime/ABase/Helper/TimerHelper.cs b/Runtime/ABase/Helper/TimerHelper.cs
deleted file mode 100644
index 42b4a98..0000000
--- a/Runtime/ABase/Helper/TimerHelper.cs
+++ /dev/null
@@ -1,266 +0,0 @@
-using System;
-
-namespace AlicizaX
-{
- ///
- /// 游戏时间帮助类
- ///
- public static class TimerHelper
- {
- private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- private static readonly long Epoch = EpochTime.Ticks;
-
- ///
- /// 时间差
- ///
- private static long _differenceTime;
-
- private static bool _isSecLevel = true;
-
- ///
- /// 微秒
- ///
- public const long TicksPerMicrosecond = 1; //100微秒
-
- ///
- /// 10微秒
- ///
- public const long TicksPer = 10 * TicksPerMicrosecond;
-
- ///
- /// 1毫秒
- ///
- public const long TicksMillisecondUnit = TicksPer * 1000; //毫秒
-
- ///
- /// 1秒
- ///
- public const long TicksSecondUnit = TicksMillisecondUnit * 1000; // 秒 //10000000
-
- ///
- /// 设置时间差
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static void SetDifferenceTime(long timeSpan)
- {
- if (timeSpan > 1000000000000)
- {
- _isSecLevel = false;
- }
- else
- {
- _isSecLevel = true;
- }
-
- if (_isSecLevel)
- {
- _differenceTime = timeSpan - ClientNow();
- }
- else
- {
- _differenceTime = timeSpan - ClientNowMillisecond();
- }
- }
-
- ///
- /// 毫秒级
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long ClientNowMillisecond()
- {
- return (DateTime.UtcNow.Ticks - Epoch) / TicksMillisecondUnit;
- }
-
- [UnityEngine.Scripting.Preserve]
- public static long ServerToday()
- {
- if (_isSecLevel)
- {
- return _differenceTime + ClientToday();
- }
-
- return (_differenceTime + ClientTodayMillisecond()) / 1000;
- }
-
- [UnityEngine.Scripting.Preserve]
- public static long ClientTodayMillisecond()
- {
- return (DateTime.Now.Date.ToUniversalTime().Ticks - Epoch) / 10000;
- }
-
- ///
- /// 服务器当前时间
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long ServerNow() //秒级
- {
- if (_isSecLevel)
- {
- return _differenceTime + ClientNow();
- }
-
- return (_differenceTime + ClientNowMillisecond()) / 1000;
- }
-
- ///
- /// 将秒数转换成TimeSpan
- ///
- /// 秒
- ///
- [UnityEngine.Scripting.Preserve]
- public static TimeSpan FromSeconds(int seconds)
- {
- return TimeSpan.FromSeconds(seconds);
- }
-
- ///
- /// 今天的客户端时间
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long ClientToday()
- {
- return (DateTime.Now.Date.ToUniversalTime().Ticks - Epoch) / TicksSecondUnit;
- }
-
- ///
- /// 客户端时间,毫秒
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long ClientNow()
- {
- return (DateTime.UtcNow.Ticks - Epoch) / 10000;
- }
-
- ///
- /// 客户端时间。秒
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long ClientNowSeconds()
- {
- return (DateTime.UtcNow.Ticks - Epoch) / 10000000;
- }
-
- ///
- /// 客户端时间
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long Now()
- {
- return ClientNow();
- }
-
- ///
- /// UTC时间 秒
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long UnixTimeSeconds()
- {
- return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
- }
-
- ///
- /// UTC时间 毫秒
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static long UnixTimeMilliseconds()
- {
- return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
- }
-
-
- ///
- /// 按照UTC时间判断两个时间戳是否是同一天
- ///
- /// 时间戳1
- /// 时间戳2
- /// 是否是同一天
- [UnityEngine.Scripting.Preserve]
- public static bool IsUnixSameDay(long timestamp1, long timestamp2)
- {
- var time1 = UtcToUtcDateTime(timestamp1);
- var time2 = UtcToUtcDateTime(timestamp2);
- return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
- }
-
- ///
- /// 按照本地时间判断两个时间戳是否是同一天
- ///
- /// 时间戳1
- /// 时间戳2
- /// 是否是同一天
- [UnityEngine.Scripting.Preserve]
- public static bool IsLocalSameDay(long timestamp1, long timestamp2)
- {
- var time1 = UtcToLocalDateTime(timestamp1);
- var time2 = UtcToLocalDateTime(timestamp2);
- return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
- }
-
- ///
- /// UTC 时间戳 转换成UTC时间
- ///
- /// UTC时间戳,单位秒
- ///
- [UnityEngine.Scripting.Preserve]
- public static DateTime UtcToUtcDateTime(long utcTimestamp)
- {
- return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).UtcDateTime;
- }
-
- ///
- /// UTC 时间戳 转换成本地时间
- ///
- /// UTC时间戳,单位秒
- ///
- [UnityEngine.Scripting.Preserve]
- public static DateTime UtcToLocalDateTime(long utcTimestamp)
- {
- return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).LocalDateTime;
- }
-
- ///
- /// 判断两个时间是否是同一天
- ///
- /// 时间1
- /// 时间2
- /// 是否是同一天
- [UnityEngine.Scripting.Preserve]
- public static bool IsSameDay(DateTime time1, DateTime time2)
- {
- return time1.Date.Year == time2.Date.Year && time1.Date.Month == time2.Date.Month && time1.Date.Day == time2.Date.Day;
- }
-
- ///
- /// 指定时间转换成Unix时间戳的时间差,单位秒
- ///
- /// 指定时间
- ///
- [UnityEngine.Scripting.Preserve]
- public static long LocalTimeToUnixTimeSeconds(DateTime time)
- {
- var utcDateTime = time.ToUniversalTime();
- return (long)(utcDateTime - EpochTime).TotalSeconds;
- }
-
- ///
- /// 指定时间转换成Unix时间戳的时间差,单位毫秒
- ///
- /// 指定时间
- ///
- [UnityEngine.Scripting.Preserve]
- public static long LocalTimeToUnixTimeMilliseconds(DateTime time)
- {
- var utcDateTime = time.ToUniversalTime();
- return (long)(utcDateTime - EpochTime).TotalMilliseconds;
- }
- }
-}
diff --git a/Runtime/ABase/Helper/TimerHelper.cs.meta b/Runtime/ABase/Helper/TimerHelper.cs.meta
deleted file mode 100644
index 4ccf0fb..0000000
--- a/Runtime/ABase/Helper/TimerHelper.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: 0d61562907c14a5295de01e78a41cd22
-timeCreated: 1666538474
\ No newline at end of file
diff --git a/Runtime/ABase/Helper/UnityRendererHelper.cs b/Runtime/ABase/Helper/UnityRendererHelper.cs
deleted file mode 100644
index 194ff2e..0000000
--- a/Runtime/ABase/Helper/UnityRendererHelper.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using UnityEngine;
-using UnityEngine.SceneManagement;
-
-namespace AlicizaX
-{
- ///
- /// Unity 渲染帮助类
- ///
- public static class UnityRendererHelper
- {
- ///
- /// 判断渲染组件是否在相机范围内
- ///
- /// 渲染组件
- /// 相机对象
- ///
- public static bool IsVisibleFrom(Renderer renderer, Camera camera)
- {
- Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
- return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
- }
-
- ///
- /// 判断渲染组件是否在相机范围内
- ///
- /// 渲染对象
- /// 相机对象
- ///
- public static bool IsVisibleFrom(MeshRenderer renderer, Camera camera)
- {
- Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
- return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
- }
-
- ///
- /// 获取相机快照
- ///
- /// 相机
- /// 缩放比
- public static Texture2D GetCaptureScreenshot(Camera main, float scale = 0.5f)
- {
- Rect rect = new Rect(0, 0, Screen.width * scale, Screen.height * scale);
- string name = DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss");
- RenderTexture renderTexture = RenderTexture.GetTemporary((int)rect.width, (int)rect.height, 0);
- renderTexture.name = SceneManager.GetActiveScene().name + "_" + renderTexture.width + "_" + renderTexture.height + "_" + name;
- main.targetTexture = renderTexture;
- main.Render();
-
- RenderTexture.active = renderTexture;
- Texture2D screenShot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false)
- {
- name = renderTexture.name
- };
- screenShot.ReadPixels(rect, 0, 0);
- screenShot.Apply();
- main.targetTexture = null;
- RenderTexture.active = null;
- RenderTexture.ReleaseTemporary(renderTexture);
- return screenShot;
- }
- }
-}
diff --git a/Runtime/ABase/Helper/UnityRendererHelper.cs.meta b/Runtime/ABase/Helper/UnityRendererHelper.cs.meta
deleted file mode 100644
index 6343692..0000000
--- a/Runtime/ABase/Helper/UnityRendererHelper.cs.meta
+++ /dev/null
@@ -1,3 +0,0 @@
-fileFormatVersion: 2
-guid: f8cc8709b4b6495eab2f7dcba3529dcf
-timeCreated: 1654011360
\ No newline at end of file
diff --git a/Runtime/ABase/Helper/ZipHelper.cs b/Runtime/ABase/Helper/ZipHelper.cs
deleted file mode 100644
index 339acc2..0000000
--- a/Runtime/ABase/Helper/ZipHelper.cs
+++ /dev/null
@@ -1,327 +0,0 @@
-using System;
-using System.IO;
-using ICSharpCode.SharpZipLib.Checksums;
-using ICSharpCode.SharpZipLib.Zip;
-using ICSharpCode.SharpZipLib.Zip.Compression;
-using UnityEngine;
-
-namespace AlicizaX
-{
- ///
- /// 压缩帮助类
- ///
- [UnityEngine.Scripting.Preserve]
- public static class ZipHelper
- {
- private static readonly Crc32 CRC = new Crc32();
-
- ///
- /// 压缩文件夹
- ///
- /// 要压缩的文件夹路径
- /// 压缩前的Stream,方法执行后变为压缩完成后的文件
- /// 密码
- /// 是否成功
- [UnityEngine.Scripting.Preserve]
- public static bool CompressDirectoryToStream(string folderToZip, Stream stream, string password = null)
- {
- return CompressDirectoryToZipStream(folderToZip, stream, password) != null;
- }
-
-
- ///
- /// 压缩文件夹
- ///
- /// 要压缩的文件夹路径
- /// 压缩前的Stream,方法执行后变为压缩完成后的文件
- /// 密码
- /// 是否压缩成功返回ZipOutputStream,否则返回null
- [UnityEngine.Scripting.Preserve]
- public static ZipOutputStream CompressDirectoryToZipStream(string folderToZip, Stream stream, string password = null)
- {
- if (!Directory.Exists(folderToZip))
- {
- return null;
- }
-
- ZipOutputStream zipStream = new ZipOutputStream(stream);
- zipStream.SetLevel(6);
- if (!string.IsNullOrEmpty(password))
- {
- zipStream.Password = password;
- }
-
- if (CompressDirectory(folderToZip, zipStream, ""))
- {
- zipStream.Finish();
- return zipStream;
- }
-
- GC.Collect(1);
- return null;
- }
-
- ///
- /// 递归压缩文件夹的内部方法
- ///
- /// 要压缩的文件夹路径
- /// 压缩输出流
- /// 此文件夹的上级文件夹
- /// 是否成功
- [UnityEngine.Scripting.Preserve]
- private static bool CompressDirectory(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
- {
- //这段是创建空文件夹,注释掉可以去掉空文件夹(因为在写入文件的时候也会创建文件夹)
- if (parentFolderName.IsNotNullOrWhiteSpace())
- {
- var ent = new ZipEntry(parentFolderName + "/");
- zipStream.PutNextEntry(ent);
- zipStream.Flush();
- }
-
- var files = Directory.GetFiles(folderToZip);
- foreach (string file in files)
- {
- byte[] buffer = File.ReadAllBytes(file);
- var path = Path.GetFileName(file);
- if (parentFolderName.IsNotNullOrWhiteSpace())
- {
- path = parentFolderName + Path.DirectorySeparatorChar + Path.GetFileName(file);
- }
-
- var ent = new ZipEntry(path)
- {
- //ent.DateTime = File.GetLastWriteTime(file);//设置文件最后修改时间
- DateTime = DateTime.Now,
- Size = buffer.Length,
- };
-
- CRC.Reset();
- CRC.Update(buffer);
-
- ent.Crc = CRC.Value;
- zipStream.PutNextEntry(ent);
- zipStream.Write(buffer, 0, buffer.Length);
- }
-
- var folders = Directory.GetDirectories(folderToZip);
- foreach (var folder in folders)
- {
- var folderName = folder.Substring(folder.LastIndexOf('\\') + 1);
-
- if (parentFolderName.IsNotNullOrWhiteSpace())
- {
- folderName = parentFolderName + "\\" + folder.Substring(folder.LastIndexOf('\\') + 1);
- }
-
- if (!CompressDirectory(folder, zipStream, folderName))
- {
- return false;
- }
- }
-
- return true;
- }
-
- ///
- /// 压缩文件夹
- ///
- /// 要压缩的文件夹路径
- /// 压缩文件完整路径
- /// 密码
- /// 是否成功
- [UnityEngine.Scripting.Preserve]
- public static bool CompressDirectory(string folderToZip, string zipFile, string password = null)
- {
- if (folderToZip.EndsWithFast(Path.DirectorySeparatorChar.ToString()) || folderToZip.EndsWithFast("/"))
- {
- folderToZip = folderToZip.Substring(0, folderToZip.Length - 1);
- }
-
- var zipStream = CompressDirectoryToZipStream(folderToZip, new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.Write), password);
- if (zipStream == null)
- {
- return false;
- }
-
- zipStream.Close();
- return true;
- }
-
- ///
- /// 压缩文件
- ///
- /// 要压缩的文件全名
- /// 压缩后的文件名
- /// 密码
- /// 是否成功
- [UnityEngine.Scripting.Preserve]
- public static bool CompressFile(string fileToZip, string zipFile, string password = null)
- {
- if (!File.Exists(fileToZip))
- {
- return false;
- }
-
- using (var readStream = File.OpenRead(fileToZip))
- {
- byte[] buffer = new byte[readStream.Length];
- var read = readStream.Read(buffer, 0, buffer.Length);
- using (var writeStream = File.Create(zipFile))
- {
- var entry = new ZipEntry(Path.GetFileName(fileToZip))
- {
- DateTime = DateTime.Now,
- Size = readStream.Length
- };
- CRC.Reset();
- CRC.Update(buffer);
- entry.Crc = CRC.Value;
- using (var zipStream = new ZipOutputStream(writeStream))
- {
- if (!string.IsNullOrEmpty(password))
- {
- zipStream.Password = password;
- }
-
- zipStream.PutNextEntry(entry);
- zipStream.SetLevel(Deflater.BEST_COMPRESSION);
- zipStream.Write(buffer, 0, buffer.Length);
- }
- }
- }
-
- GC.Collect(1);
-
- return true;
- }
-
- ///
- /// 解压功能(解压压缩文件到指定目录)
- ///
- /// 待解压的文件
- /// 指定解压目标目录
- /// 密码
- /// 是否成功
- [UnityEngine.Scripting.Preserve]
- public static bool DecompressFile(string fileToUnZip, string zipFolder, string password = null)
- {
- if (!System.IO.File.Exists(fileToUnZip))
- {
- return false;
- }
-
- if (!Directory.Exists(zipFolder))
- {
- Directory.CreateDirectory(zipFolder);
- }
-
- if (!zipFolder.EndsWith("\\"))
- {
- zipFolder += "\\";
- }
-
- using (var zipStream = new ZipInputStream(System.IO.File.OpenRead(fileToUnZip)))
- {
- if (!string.IsNullOrEmpty(password))
- {
- zipStream.Password = password;
- }
-
- ZipEntry zipEntry = null;
- while ((zipEntry = zipStream.GetNextEntry()) != null)
- {
- if (zipEntry.IsDirectory)
- {
- continue;
- }
-
- if (string.IsNullOrEmpty(zipEntry.Name))
- {
- continue;
- }
-
- string fileName = zipFolder + zipEntry.Name.Replace('/', '\\');
- var index = zipEntry.Name.LastIndexOf('/');
- if (index != -1)
- {
- string path = zipFolder + zipEntry.Name.Substring(0, index).Replace('/', '\\');
- System.IO.Directory.CreateDirectory(path);
- }
-
- var bytes = new byte[zipEntry.Size];
- var read = zipStream.Read(bytes, 0, bytes.Length);
- System.IO.File.WriteAllBytes(fileName, bytes);
- }
- }
-
- GC.Collect(1);
- return true;
- }
-
- ///
- /// 压缩
- ///
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static byte[] Compress(byte[] content)
- {
- //return content;
- Deflater compressor = new Deflater();
- compressor.SetLevel(Deflater.BEST_COMPRESSION);
-
- compressor.SetInput(content);
- compressor.Finish();
-
- using (MemoryStream bos = new MemoryStream(content.Length))
- {
- var buf = new byte[4096];
- while (!compressor.IsFinished)
- {
- int n = compressor.Deflate(buf);
- bos.Write(buf, 0, n);
- }
-
- return bos.ToArray();
- }
- }
-
- ///
- /// 解压缩
- ///
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static byte[] Decompress(byte[] content)
- {
- return Decompress(content, 0, content.Length);
- }
-
- ///
- /// 解压缩
- ///
- ///
- ///
- ///
- ///
- [UnityEngine.Scripting.Preserve]
- public static byte[] Decompress(byte[] content, int offset, int count)
- {
- //return content;
- Inflater decompressor = new Inflater();
- decompressor.SetInput(content, offset, count);
- using (MemoryStream bos = new MemoryStream(content.Length))
- {
- var buf = new byte[4096];
- while (!decompressor.IsFinished)
- {
- int n = decompressor.Inflate(buf);
- bos.Write(buf, 0, n);
- }
-
- return bos.ToArray();
- }
- }
- }
-}
diff --git a/Runtime/ABase/Utility/Utility.Compression.Zip.cs b/Runtime/ABase/Utility/Utility.Compression.Zip.cs
new file mode 100644
index 0000000..af1fbf7
--- /dev/null
+++ b/Runtime/ABase/Utility/Utility.Compression.Zip.cs
@@ -0,0 +1,240 @@
+using System;
+using System.IO;
+using ICSharpCode.SharpZipLib.Checksums;
+using ICSharpCode.SharpZipLib.Zip;
+using ICSharpCode.SharpZipLib.Zip.Compression;
+
+namespace AlicizaX
+{
+ public static partial class Utility
+ {
+ ///
+ /// Zip 压缩相关的实用函数。
+ ///
+ public static class Zip
+ {
+ private static readonly Crc32 s_Crc32 = new Crc32();
+
+ public static bool CompressDirectoryToStream(string folderToZip, Stream stream, string password = null)
+ {
+ return CompressDirectoryToZipStream(folderToZip, stream, password) != null;
+ }
+
+ public static ZipOutputStream CompressDirectoryToZipStream(string folderToZip, Stream stream, string password = null)
+ {
+ if (!Directory.Exists(folderToZip) || stream == null)
+ {
+ return null;
+ }
+
+ ZipOutputStream zipStream = new ZipOutputStream(stream);
+ zipStream.SetLevel(6);
+ if (!string.IsNullOrEmpty(password))
+ {
+ zipStream.Password = password;
+ }
+
+ if (!CompressDirectoryInternal(folderToZip, zipStream, string.Empty))
+ {
+ zipStream.Dispose();
+ return null;
+ }
+
+ zipStream.Finish();
+ return zipStream;
+ }
+
+ public static bool CompressDirectory(string folderToZip, string zipFile, string password = null)
+ {
+ if (string.IsNullOrEmpty(folderToZip) || string.IsNullOrEmpty(zipFile))
+ {
+ return false;
+ }
+
+ folderToZip = folderToZip.TrimEnd(System.IO.Path.DirectorySeparatorChar, '/');
+ using (FileStream writeStream = new FileStream(zipFile, FileMode.Create, FileAccess.Write, FileShare.Write))
+ {
+ return CompressDirectoryToZipStream(folderToZip, writeStream, password) != null;
+ }
+ }
+
+ public static bool CompressFile(string fileToZip, string zipFile, string password = null)
+ {
+ if (!System.IO.File.Exists(fileToZip) || string.IsNullOrEmpty(zipFile))
+ {
+ return false;
+ }
+
+ byte[] buffer = System.IO.File.ReadAllBytes(fileToZip);
+ using (FileStream writeStream = System.IO.File.Create(zipFile))
+ using (ZipOutputStream zipStream = new ZipOutputStream(writeStream))
+ {
+ if (!string.IsNullOrEmpty(password))
+ {
+ zipStream.Password = password;
+ }
+
+ ZipEntry entry = new ZipEntry(System.IO.Path.GetFileName(fileToZip))
+ {
+ DateTime = DateTime.Now,
+ Size = buffer.Length
+ };
+
+ s_Crc32.Reset();
+ s_Crc32.Update(buffer);
+ entry.Crc = s_Crc32.Value;
+
+ zipStream.PutNextEntry(entry);
+ zipStream.SetLevel(Deflater.BEST_COMPRESSION);
+ zipStream.Write(buffer, 0, buffer.Length);
+ }
+
+ return true;
+ }
+
+ public static bool DecompressFile(string fileToUnzip, string zipFolder, string password = null)
+ {
+ if (!System.IO.File.Exists(fileToUnzip) || string.IsNullOrEmpty(zipFolder))
+ {
+ return false;
+ }
+
+ Directory.CreateDirectory(zipFolder);
+
+ using (ZipInputStream zipStream = new ZipInputStream(System.IO.File.OpenRead(fileToUnzip)))
+ {
+ if (!string.IsNullOrEmpty(password))
+ {
+ zipStream.Password = password;
+ }
+
+ ZipEntry zipEntry;
+ while ((zipEntry = zipStream.GetNextEntry()) != null)
+ {
+ if (zipEntry.IsDirectory || string.IsNullOrEmpty(zipEntry.Name))
+ {
+ continue;
+ }
+
+ string relativePath = zipEntry.Name.Replace('/', System.IO.Path.DirectorySeparatorChar);
+ string outputPath = System.IO.Path.Combine(zipFolder, relativePath);
+ string directory = System.IO.Path.GetDirectoryName(outputPath);
+ if (!string.IsNullOrEmpty(directory))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ using (FileStream fileStream = System.IO.File.Create(outputPath))
+ {
+ zipStream.CopyTo(fileStream);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public static byte[] Compress(byte[] content)
+ {
+ if (content == null)
+ {
+ return null;
+ }
+
+ Deflater compressor = new Deflater();
+ compressor.SetLevel(Deflater.BEST_COMPRESSION);
+ compressor.SetInput(content);
+ compressor.Finish();
+
+ using (MemoryStream output = new MemoryStream(content.Length))
+ {
+ byte[] buffer = new byte[4096];
+ while (!compressor.IsFinished)
+ {
+ int read = compressor.Deflate(buffer);
+ output.Write(buffer, 0, read);
+ }
+
+ return output.ToArray();
+ }
+ }
+
+ public static byte[] Decompress(byte[] content)
+ {
+ return content == null ? null : Decompress(content, 0, content.Length);
+ }
+
+ public static byte[] Decompress(byte[] content, int offset, int count)
+ {
+ if (content == null)
+ {
+ return null;
+ }
+
+ Inflater decompressor = new Inflater();
+ decompressor.SetInput(content, offset, count);
+ using (MemoryStream output = new MemoryStream(content.Length))
+ {
+ byte[] buffer = new byte[4096];
+ while (!decompressor.IsFinished)
+ {
+ int read = decompressor.Inflate(buffer);
+ output.Write(buffer, 0, read);
+ }
+
+ return output.ToArray();
+ }
+ }
+
+ private static bool CompressDirectoryInternal(string folderToZip, ZipOutputStream zipStream, string parentFolderName)
+ {
+ if (!string.IsNullOrWhiteSpace(parentFolderName))
+ {
+ ZipEntry entry = new ZipEntry(parentFolderName + "/");
+ zipStream.PutNextEntry(entry);
+ zipStream.Flush();
+ }
+
+ string[] files = Directory.GetFiles(folderToZip);
+ foreach (string file in files)
+ {
+ byte[] buffer = System.IO.File.ReadAllBytes(file);
+ string path = System.IO.Path.GetFileName(file);
+ if (!string.IsNullOrWhiteSpace(parentFolderName))
+ {
+ path = parentFolderName + System.IO.Path.DirectorySeparatorChar + System.IO.Path.GetFileName(file);
+ }
+
+ ZipEntry entry = new ZipEntry(path)
+ {
+ DateTime = DateTime.Now,
+ Size = buffer.Length
+ };
+
+ s_Crc32.Reset();
+ s_Crc32.Update(buffer);
+ entry.Crc = s_Crc32.Value;
+ zipStream.PutNextEntry(entry);
+ zipStream.Write(buffer, 0, buffer.Length);
+ }
+
+ string[] folders = Directory.GetDirectories(folderToZip);
+ foreach (string folder in folders)
+ {
+ string folderName = System.IO.Path.GetFileName(folder);
+ if (!string.IsNullOrWhiteSpace(parentFolderName))
+ {
+ folderName = parentFolderName + System.IO.Path.DirectorySeparatorChar + folderName;
+ }
+
+ if (!CompressDirectoryInternal(folder, zipStream, folderName))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+ }
+}
diff --git a/Runtime/ABase/Helper/CompressionUtility.cs.meta b/Runtime/ABase/Utility/Utility.Compression.Zip.cs.meta
similarity index 83%
rename from Runtime/ABase/Helper/CompressionUtility.cs.meta
rename to Runtime/ABase/Utility/Utility.Compression.Zip.cs.meta
index 193ed8a..65f50e7 100644
--- a/Runtime/ABase/Helper/CompressionUtility.cs.meta
+++ b/Runtime/ABase/Utility/Utility.Compression.Zip.cs.meta
@@ -1,5 +1,5 @@
fileFormatVersion: 2
-guid: 1d572c5f6d619fd4cab0970b865300f7
+guid: 4d6547a46fce4ed7b0d0dce5f6f1a211
MonoImporter:
externalObjects: {}
serializedVersion: 2
diff --git a/Runtime/ABase/Utility/Utility.Compression.cs b/Runtime/ABase/Utility/Utility.Compression.cs
index 50b3019..1ea25a3 100644
--- a/Runtime/ABase/Utility/Utility.Compression.cs
+++ b/Runtime/ABase/Utility/Utility.Compression.cs
@@ -1,6 +1,8 @@
using System;
using System.IO;
+using ICSharpCode.SharpZipLib.GZip;
+
namespace AlicizaX
{
public static partial class Utility
@@ -10,6 +12,8 @@ namespace AlicizaX
///
public static partial class Compression
{
+ private const int CachedBytesLength = 0x1000;
+
///
/// 压缩数据。
///
@@ -90,7 +94,14 @@ namespace AlicizaX
try
{
- return CompressionUtility.Compress(bytes, offset, length, compressedStream);
+ using (GZipOutputStream gzipOutputStream = new GZipOutputStream(compressedStream))
+ {
+ gzipOutputStream.Write(bytes, offset, length);
+ gzipOutputStream.Finish();
+ }
+
+ ProcessHeader(compressedStream);
+ return true;
}
catch (Exception exception)
{
@@ -143,7 +154,20 @@ namespace AlicizaX
try
{
- return CompressionUtility.Compress(stream, compressedStream);
+ byte[] cachedBytes = new byte[CachedBytesLength];
+ using (GZipOutputStream gzipOutputStream = new GZipOutputStream(compressedStream))
+ {
+ int bytesRead;
+ while ((bytesRead = stream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
+ {
+ gzipOutputStream.Write(cachedBytes, 0, bytesRead);
+ }
+
+ gzipOutputStream.Finish();
+ }
+
+ ProcessHeader(compressedStream);
+ return true;
}
catch (Exception exception)
{
@@ -236,7 +260,18 @@ namespace AlicizaX
try
{
- return CompressionUtility.Decompress(bytes, offset, length, decompressedStream);
+ byte[] cachedBytes = new byte[CachedBytesLength];
+ using (MemoryStream memoryStream = new MemoryStream(bytes, offset, length, false))
+ using (GZipInputStream gzipInputStream = new GZipInputStream(memoryStream))
+ {
+ int bytesRead;
+ while ((bytesRead = gzipInputStream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
+ {
+ decompressedStream.Write(cachedBytes, 0, bytesRead);
+ }
+ }
+
+ return true;
}
catch (Exception exception)
{
@@ -289,7 +324,17 @@ namespace AlicizaX
try
{
- return CompressionUtility.Decompress(stream, decompressedStream);
+ byte[] cachedBytes = new byte[CachedBytesLength];
+ using (GZipInputStream gzipInputStream = new GZipInputStream(stream))
+ {
+ int bytesRead;
+ while ((bytesRead = gzipInputStream.Read(cachedBytes, 0, CachedBytesLength)) > 0)
+ {
+ decompressedStream.Write(cachedBytes, 0, bytesRead);
+ }
+ }
+
+ return true;
}
catch (Exception exception)
{
@@ -301,6 +346,22 @@ namespace AlicizaX
throw new GameFrameworkException(Text.Format("Can not decompress with exception '{0}'.", exception), exception);
}
}
+
+ private static void ProcessHeader(Stream compressedStream)
+ {
+ if (compressedStream.Length < 8L)
+ {
+ return;
+ }
+
+ long current = compressedStream.Position;
+ compressedStream.Position = 4L;
+ compressedStream.WriteByte(25);
+ compressedStream.WriteByte(134);
+ compressedStream.WriteByte(2);
+ compressedStream.WriteByte(32);
+ compressedStream.Position = current;
+ }
}
}
}
diff --git a/Runtime/ABase/Utility/Utility.Math.cs b/Runtime/ABase/Utility/Utility.Math.cs
index 3952c0d..b104307 100644
--- a/Runtime/ABase/Utility/Utility.Math.cs
+++ b/Runtime/ABase/Utility/Utility.Math.cs
@@ -16,7 +16,7 @@ namespace AlicizaX
public static float PingPong(float min, float max, float speed = 1f)
{
- return Mathf.PingPong(Time.time * speed, max - min) + min;
+ return Mathf.PingPong(UnityEngine.Time.time * speed, max - min) + min;
}
public static int Wrap(int value, int min, int max)
diff --git a/Runtime/ABase/Utility/Utility.Position.cs b/Runtime/ABase/Utility/Utility.Position.cs
new file mode 100644
index 0000000..af0a638
--- /dev/null
+++ b/Runtime/ABase/Utility/Utility.Position.cs
@@ -0,0 +1,93 @@
+using UnityEngine;
+
+namespace AlicizaX
+{
+ public static partial class Utility
+ {
+ ///
+ /// 位置与几何相关的实用函数。
+ ///
+ public static class Position
+ {
+ public static Vector3 RayCastV2ToV3(Vector2 position)
+ {
+ return position.ToVector3();
+ }
+
+ public static Vector3 RayCastXYToV3(float x, float y)
+ {
+ return new Vector3(x, 0f, y);
+ }
+
+ public static Vector3 RayCastV3ToV3(Vector3 position)
+ {
+ return position.FlattenY();
+ }
+
+ public static Quaternion AngleToQuaternion(int angle)
+ {
+ return GetAngleToQuaternion(angle);
+ }
+
+ public static Quaternion GetAngleToQuaternion(float angle)
+ {
+ return Quaternion.AngleAxis(-angle, Vector3.up) * Quaternion.AngleAxis(90f, Vector3.up);
+ }
+
+ public static Quaternion GetVector3ToQuaternion(Vector3 source, Vector3 direction)
+ {
+ if (source == direction)
+ {
+ return Quaternion.identity;
+ }
+
+ return Quaternion.LookRotation((direction - source).normalized, Vector3.up);
+ }
+
+ public static float Distance2D(Vector3 a, Vector3 b)
+ {
+ return Vector2.Distance(a.IgnoreYAxis(), b.IgnoreYAxis());
+ }
+
+ public static float Vector3ToAngle360(Vector3 from, Vector3 to)
+ {
+ float angle = Vector3.Angle(from, to);
+ Vector3 cross = Vector3.Cross(from, to);
+ return cross.y > 0f ? angle : 360f - angle;
+ }
+
+ public static float DistanceOfPointToVector(Vector3 startPoint, Vector3 endPoint, Vector3 point)
+ {
+ Vector2 start = startPoint.IgnoreYAxis();
+ Vector2 end = endPoint.IgnoreYAxis();
+ float a = end.y - start.y;
+ float b = start.x - end.x;
+ float c = end.x * start.y - start.x * end.y;
+ float denominator = Mathf.Sqrt(a * a + b * b);
+ Vector2 point2 = point.IgnoreYAxis();
+ return Mathf.Abs((a * point2.x + b * point2.y + c) / denominator);
+ }
+
+ public static bool RayCastSphere(Ray ray, Vector3 center, float radius, out float distance)
+ {
+ distance = 0f;
+ Vector3 originToCenter = center - ray.origin;
+ float perpendicularDistance = Vector3.Cross(originToCenter, ray.direction).magnitude / ray.direction.magnitude;
+ if (perpendicularDistance >= radius)
+ {
+ return false;
+ }
+
+ float centerDistance = PythagoreanTheorem(Vector3.Distance(center, ray.origin), perpendicularDistance);
+ float radiusDistance = PythagoreanTheorem(radius, perpendicularDistance);
+ distance = centerDistance - radiusDistance;
+ return true;
+ }
+
+ public static float PythagoreanTheorem(float x, float y)
+ {
+ return Mathf.Sqrt(x * x + y * y);
+ }
+ }
+ }
+}
diff --git a/Runtime/ABase/Helper/ZipHelper.cs.meta b/Runtime/ABase/Utility/Utility.Position.cs.meta
similarity index 69%
rename from Runtime/ABase/Helper/ZipHelper.cs.meta
rename to Runtime/ABase/Utility/Utility.Position.cs.meta
index f1761c8..c4459d4 100644
--- a/Runtime/ABase/Helper/ZipHelper.cs.meta
+++ b/Runtime/ABase/Utility/Utility.Position.cs.meta
@@ -1,8 +1,7 @@
fileFormatVersion: 2
-guid: 75d07d90984a5dc4698c98d2fe3809bf
-timeCreated: 1474948216
-licenseType: Pro
+guid: c82a27c2ab4545f687eac25a4d731f16
MonoImporter:
+ externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
diff --git a/Runtime/ABase/Utility/Utility.Time.cs b/Runtime/ABase/Utility/Utility.Time.cs
new file mode 100644
index 0000000..4bcfa95
--- /dev/null
+++ b/Runtime/ABase/Utility/Utility.Time.cs
@@ -0,0 +1,118 @@
+using System;
+
+namespace AlicizaX
+{
+ public static partial class Utility
+ {
+ ///
+ /// 时间相关的实用函数。
+ ///
+ public static class Time
+ {
+ private static readonly DateTime EpochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ private static long s_DifferenceTime;
+ private static bool s_IsSecondLevel = true;
+
+ public const long TicksPerMicrosecond = 1;
+ public const long TicksPer = 10 * TicksPerMicrosecond;
+ public const long TicksMillisecondUnit = TicksPer * 1000;
+ public const long TicksSecondUnit = TicksMillisecondUnit * 1000;
+
+ public static void SetDifferenceTime(long timeSpan)
+ {
+ s_IsSecondLevel = timeSpan <= 1000000000000;
+ s_DifferenceTime = s_IsSecondLevel ? timeSpan - ClientNowSeconds() : timeSpan - ClientNowMillisecond();
+ }
+
+ public static long ClientNowMillisecond()
+ {
+ return (DateTime.UtcNow.Ticks - EpochTime.Ticks) / TicksMillisecondUnit;
+ }
+
+ public static long ServerToday()
+ {
+ return s_IsSecondLevel ? s_DifferenceTime + ClientToday() : (s_DifferenceTime + ClientTodayMillisecond()) / 1000;
+ }
+
+ public static long ClientTodayMillisecond()
+ {
+ return (DateTime.Now.Date.ToUniversalTime().Ticks - EpochTime.Ticks) / TicksMillisecondUnit;
+ }
+
+ public static long ServerNow()
+ {
+ return s_IsSecondLevel ? s_DifferenceTime + ClientNowSeconds() : (s_DifferenceTime + ClientNowMillisecond()) / 1000;
+ }
+
+ public static TimeSpan FromSeconds(int seconds)
+ {
+ return TimeSpan.FromSeconds(seconds);
+ }
+
+ public static long ClientToday()
+ {
+ return (DateTime.Now.Date.ToUniversalTime().Ticks - EpochTime.Ticks) / TicksSecondUnit;
+ }
+
+ public static long ClientNow()
+ {
+ return ClientNowMillisecond();
+ }
+
+ public static long ClientNowSeconds()
+ {
+ return (DateTime.UtcNow.Ticks - EpochTime.Ticks) / TicksSecondUnit;
+ }
+
+ public static long Now()
+ {
+ return ClientNow();
+ }
+
+ public static long UnixTimeSeconds()
+ {
+ return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+ }
+
+ public static long UnixTimeMilliseconds()
+ {
+ return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ }
+
+ public static bool IsUnixSameDay(long timestamp1, long timestamp2)
+ {
+ return IsSameDay(UtcToUtcDateTime(timestamp1), UtcToUtcDateTime(timestamp2));
+ }
+
+ public static bool IsLocalSameDay(long timestamp1, long timestamp2)
+ {
+ return IsSameDay(UtcToLocalDateTime(timestamp1), UtcToLocalDateTime(timestamp2));
+ }
+
+ public static DateTime UtcToUtcDateTime(long utcTimestamp)
+ {
+ return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).UtcDateTime;
+ }
+
+ public static DateTime UtcToLocalDateTime(long utcTimestamp)
+ {
+ return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).LocalDateTime;
+ }
+
+ public static bool IsSameDay(DateTime time1, DateTime time2)
+ {
+ return time1.Date == time2.Date;
+ }
+
+ public static long LocalTimeToUnixTimeSeconds(DateTime time)
+ {
+ return new DateTimeOffset(time.ToUniversalTime()).ToUnixTimeSeconds();
+ }
+
+ public static long LocalTimeToUnixTimeMilliseconds(DateTime time)
+ {
+ return new DateTimeOffset(time.ToUniversalTime()).ToUnixTimeMilliseconds();
+ }
+ }
+ }
+}
diff --git a/Runtime/ABase/Utility/Utility.Time.cs.meta b/Runtime/ABase/Utility/Utility.Time.cs.meta
new file mode 100644
index 0000000..23537cd
--- /dev/null
+++ b/Runtime/ABase/Utility/Utility.Time.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 4c88fefb639f4d1dac58f77d9cbba2af
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/ABase/Utility/Utility.Unity.Gameplay.cs b/Runtime/ABase/Utility/Utility.Unity.Gameplay.cs
index be64cef..d7ae7a3 100644
--- a/Runtime/ABase/Utility/Utility.Unity.Gameplay.cs
+++ b/Runtime/ABase/Utility/Utility.Unity.Gameplay.cs
@@ -44,7 +44,7 @@ namespace AlicizaX
source.clip = clip;
source.volume = volume;
source.Play();
- Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
+ Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
return source;
}
@@ -72,7 +72,7 @@ namespace AlicizaX
source.clip = clip;
source.volume = volume;
source.Play();
- Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
+ Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
return source;
}
@@ -91,7 +91,7 @@ namespace AlicizaX
source.volume = volume;
source.maxDistance = maxDistance;
source.Play();
- Object.Destroy(gameObject, clip.length * ((Time.timeScale < 0.01f) ? 0.01f : Time.timeScale));
+ Object.Destroy(gameObject, clip.length * ((UnityEngine.Time.timeScale < 0.01f) ? 0.01f : UnityEngine.Time.timeScale));
return source;
}