整合扩展
This commit is contained in:
parent
7ae4ddac09
commit
919678b811
@ -1,5 +1,7 @@
|
|||||||
|
using System;
|
||||||
using AlicizaX;
|
using AlicizaX;
|
||||||
using UnityEngine.UI;
|
using UnityEngine.UI;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
namespace UnityEngine
|
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]
|
[UnityEngine.Scripting.Preserve]
|
||||||
public static class AngleExtensions
|
public static class AngleExtensions
|
||||||
{
|
{
|
||||||
|
|||||||
@ -34,5 +34,35 @@
|
|||||||
lhs.Scale(rhs);
|
lhs.Scale(rhs);
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 将三维向量投影到 XZ 平面。
|
||||||
|
/// </summary>
|
||||||
|
public static Vector2 IgnoreYAxis(this Vector3 vector3)
|
||||||
|
{
|
||||||
|
return new Vector2(vector3.x, vector3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保留 XZ 分量并清空 Y 轴。
|
||||||
|
/// </summary>
|
||||||
|
public static Vector3 FlattenY(this Vector3 vector3)
|
||||||
|
{
|
||||||
|
return new Vector3(vector3.x, 0f, vector3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断目标点是否位于当前方向的左侧。
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,206 +0,0 @@
|
|||||||
using AlicizaX;
|
|
||||||
using ICSharpCode.SharpZipLib.GZip;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace AlicizaX
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 默认压缩解压缩辅助器。
|
|
||||||
/// </summary>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public class CompressionUtility
|
|
||||||
{
|
|
||||||
private const int CachedBytesLength = 0x1000;
|
|
||||||
private static readonly byte[] m_CachedBytes = new byte[CachedBytesLength];
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩数据。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bytes">要压缩的数据的二进制流。</param>
|
|
||||||
/// <param name="offset">要压缩的数据的二进制流的偏移。</param>
|
|
||||||
/// <param name="length">要压缩的数据的二进制流的长度。</param>
|
|
||||||
/// <param name="compressedStream">压缩后的数据的二进制流。</param>
|
|
||||||
/// <returns>是否压缩数据成功。</returns>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩数据。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">要压缩的数据的二进制流。</param>
|
|
||||||
/// <param name="compressedStream">压缩后的数据的二进制流。</param>
|
|
||||||
/// <returns>是否压缩数据成功。</returns>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解压缩数据。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="bytes">要解压缩的数据的二进制流。</param>
|
|
||||||
/// <param name="offset">要解压缩的数据的二进制流的偏移。</param>
|
|
||||||
/// <param name="length">要解压缩的数据的二进制流的长度。</param>
|
|
||||||
/// <param name="decompressedStream">解压缩后的数据的二进制流。</param>
|
|
||||||
/// <returns>是否解压缩数据成功。</returns>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解压缩数据。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="stream">要解压缩的数据的二进制流。</param>
|
|
||||||
/// <param name="decompressedStream">解压缩后的数据的二进制流。</param>
|
|
||||||
/// <returns>是否解压缩数据成功。</returns>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ef59646f457548b0962c49a3434cf7e3
|
|
||||||
timeCreated: 1758265544
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace AlicizaX
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 坐标帮助类
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 求点到直线的距离,采用数学公式Ax+By+C = 0; d = A*p.x + B * p.y + C / sqrt(A^2 + B ^ 2)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="startPoint">线的起点</param>
|
|
||||||
/// <param name="endPoint">线的终点</param>
|
|
||||||
/// <param name="point">点</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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);
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断射线是否碰撞到球体,如果碰撞到,返回射线起点到碰撞点之间的距离
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="ray">射线</param>
|
|
||||||
/// <param name="center">中心点</param>
|
|
||||||
/// <param name="redis">半径</param>
|
|
||||||
/// <param name="dist">距离</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 勾股定理
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="x"></param>
|
|
||||||
/// <param name="y"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static float PythagoreanTheorem(float x, float y)
|
|
||||||
{
|
|
||||||
return Mathf.Sqrt(x * x + y * y);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 去掉三维向量的Y轴,把向量投射到xz平面。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="vector3"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static Vector2 IgnoreYAxis(this Vector3 vector3)
|
|
||||||
{
|
|
||||||
return new Vector2(vector3.x, vector3.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断目标点是否位于向量的左边
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>True is on left, false is on right</returns>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fb356e4ecfd547b280b88ca74a847918
|
|
||||||
timeCreated: 1666447289
|
|
||||||
@ -1,266 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace AlicizaX
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 游戏时间帮助类
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 时间差
|
|
||||||
/// </summary>
|
|
||||||
private static long _differenceTime;
|
|
||||||
|
|
||||||
private static bool _isSecLevel = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 微秒
|
|
||||||
/// </summary>
|
|
||||||
public const long TicksPerMicrosecond = 1; //100微秒
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 10微秒
|
|
||||||
/// </summary>
|
|
||||||
public const long TicksPer = 10 * TicksPerMicrosecond;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1毫秒
|
|
||||||
/// </summary>
|
|
||||||
public const long TicksMillisecondUnit = TicksPer * 1000; //毫秒
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1秒
|
|
||||||
/// </summary>
|
|
||||||
public const long TicksSecondUnit = TicksMillisecondUnit * 1000; // 秒 //10000000
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 设置时间差
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timeSpan"></param>
|
|
||||||
[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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 毫秒级
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 服务器当前时间
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long ServerNow() //秒级
|
|
||||||
{
|
|
||||||
if (_isSecLevel)
|
|
||||||
{
|
|
||||||
return _differenceTime + ClientNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (_differenceTime + ClientNowMillisecond()) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 将秒数转换成TimeSpan
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="seconds">秒</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static TimeSpan FromSeconds(int seconds)
|
|
||||||
{
|
|
||||||
return TimeSpan.FromSeconds(seconds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 今天的客户端时间
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long ClientToday()
|
|
||||||
{
|
|
||||||
return (DateTime.Now.Date.ToUniversalTime().Ticks - Epoch) / TicksSecondUnit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 客户端时间,毫秒
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long ClientNow()
|
|
||||||
{
|
|
||||||
return (DateTime.UtcNow.Ticks - Epoch) / 10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 客户端时间。秒
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long ClientNowSeconds()
|
|
||||||
{
|
|
||||||
return (DateTime.UtcNow.Ticks - Epoch) / 10000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 客户端时间
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long Now()
|
|
||||||
{
|
|
||||||
return ClientNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UTC时间 秒
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long UnixTimeSeconds()
|
|
||||||
{
|
|
||||||
return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UTC时间 毫秒
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long UnixTimeMilliseconds()
|
|
||||||
{
|
|
||||||
return new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按照UTC时间判断两个时间戳是否是同一天
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timestamp1">时间戳1</param>
|
|
||||||
/// <param name="timestamp2">时间戳2</param>
|
|
||||||
/// <returns>是否是同一天</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按照本地时间判断两个时间戳是否是同一天
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="timestamp1">时间戳1</param>
|
|
||||||
/// <param name="timestamp2">时间戳2</param>
|
|
||||||
/// <returns>是否是同一天</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UTC 时间戳 转换成UTC时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="utcTimestamp">UTC时间戳,单位秒</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static DateTime UtcToUtcDateTime(long utcTimestamp)
|
|
||||||
{
|
|
||||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).UtcDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UTC 时间戳 转换成本地时间
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="utcTimestamp">UTC时间戳,单位秒</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static DateTime UtcToLocalDateTime(long utcTimestamp)
|
|
||||||
{
|
|
||||||
return DateTimeOffset.FromUnixTimeSeconds(utcTimestamp).LocalDateTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断两个时间是否是同一天
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time1">时间1</param>
|
|
||||||
/// <param name="time2">时间2</param>
|
|
||||||
/// <returns>是否是同一天</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 指定时间转换成Unix时间戳的时间差,单位秒
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">指定时间</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long LocalTimeToUnixTimeSeconds(DateTime time)
|
|
||||||
{
|
|
||||||
var utcDateTime = time.ToUniversalTime();
|
|
||||||
return (long)(utcDateTime - EpochTime).TotalSeconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 指定时间转换成Unix时间戳的时间差,单位毫秒
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="time">指定时间</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static long LocalTimeToUnixTimeMilliseconds(DateTime time)
|
|
||||||
{
|
|
||||||
var utcDateTime = time.ToUniversalTime();
|
|
||||||
return (long)(utcDateTime - EpochTime).TotalMilliseconds;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0d61562907c14a5295de01e78a41cd22
|
|
||||||
timeCreated: 1666538474
|
|
||||||
@ -1,63 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.SceneManagement;
|
|
||||||
|
|
||||||
namespace AlicizaX
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Unity 渲染帮助类
|
|
||||||
/// </summary>
|
|
||||||
public static class UnityRendererHelper
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 判断渲染组件是否在相机范围内
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderer">渲染组件</param>
|
|
||||||
/// <param name="camera">相机对象</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static bool IsVisibleFrom(Renderer renderer, Camera camera)
|
|
||||||
{
|
|
||||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
|
||||||
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断渲染组件是否在相机范围内
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="renderer">渲染对象</param>
|
|
||||||
/// <param name="camera">相机对象</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static bool IsVisibleFrom(MeshRenderer renderer, Camera camera)
|
|
||||||
{
|
|
||||||
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
|
|
||||||
return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取相机快照
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="main">相机</param>
|
|
||||||
/// <param name="scale">缩放比</param>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f8cc8709b4b6495eab2f7dcba3529dcf
|
|
||||||
timeCreated: 1654011360
|
|
||||||
@ -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
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩帮助类
|
|
||||||
/// </summary>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static class ZipHelper
|
|
||||||
{
|
|
||||||
private static readonly Crc32 CRC = new Crc32();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩文件夹
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
|
||||||
/// <param name="stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
|
|
||||||
/// <param name="password">密码</param>
|
|
||||||
/// <returns>是否成功</returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static bool CompressDirectoryToStream(string folderToZip, Stream stream, string password = null)
|
|
||||||
{
|
|
||||||
return CompressDirectoryToZipStream(folderToZip, stream, password) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩文件夹
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
|
||||||
/// <param name="stream">压缩前的Stream,方法执行后变为压缩完成后的文件</param>
|
|
||||||
/// <param name="password">密码</param>
|
|
||||||
/// <returns>是否压缩成功返回ZipOutputStream,否则返回null</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 递归压缩文件夹的内部方法
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
|
||||||
/// <param name="zipStream">压缩输出流</param>
|
|
||||||
/// <param name="parentFolderName">此文件夹的上级文件夹</param>
|
|
||||||
/// <returns>是否成功</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩文件夹
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="folderToZip">要压缩的文件夹路径</param>
|
|
||||||
/// <param name="zipFile">压缩文件完整路径</param>
|
|
||||||
/// <param name="password">密码</param>
|
|
||||||
/// <returns>是否成功</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩文件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fileToZip">要压缩的文件全名</param>
|
|
||||||
/// <param name="zipFile">压缩后的文件名</param>
|
|
||||||
/// <param name="password">密码</param>
|
|
||||||
/// <returns>是否成功</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解压功能(解压压缩文件到指定目录)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fileToUnZip">待解压的文件</param>
|
|
||||||
/// <param name="zipFolder">指定解压目标目录</param>
|
|
||||||
/// <param name="password">密码</param>
|
|
||||||
/// <returns>是否成功</returns>
|
|
||||||
[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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 压缩
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解压缩
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[UnityEngine.Scripting.Preserve]
|
|
||||||
public static byte[] Decompress(byte[] content)
|
|
||||||
{
|
|
||||||
return Decompress(content, 0, content.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 解压缩
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="content"></param>
|
|
||||||
/// <param name="offset"></param>
|
|
||||||
/// <param name="count"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
240
Runtime/ABase/Utility/Utility.Compression.Zip.cs
Normal file
240
Runtime/ABase/Utility/Utility.Compression.Zip.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Zip 压缩相关的实用函数。
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1d572c5f6d619fd4cab0970b865300f7
|
guid: 4d6547a46fce4ed7b0d0dce5f6f1a211
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
using ICSharpCode.SharpZipLib.GZip;
|
||||||
|
|
||||||
namespace AlicizaX
|
namespace AlicizaX
|
||||||
{
|
{
|
||||||
public static partial class Utility
|
public static partial class Utility
|
||||||
@ -10,6 +12,8 @@ namespace AlicizaX
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static partial class Compression
|
public static partial class Compression
|
||||||
{
|
{
|
||||||
|
private const int CachedBytesLength = 0x1000;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 压缩数据。
|
/// 压缩数据。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -90,7 +94,14 @@ namespace AlicizaX
|
|||||||
|
|
||||||
try
|
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)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@ -143,7 +154,20 @@ namespace AlicizaX
|
|||||||
|
|
||||||
try
|
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)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@ -236,7 +260,18 @@ namespace AlicizaX
|
|||||||
|
|
||||||
try
|
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)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@ -289,7 +324,17 @@ namespace AlicizaX
|
|||||||
|
|
||||||
try
|
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)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
@ -301,6 +346,22 @@ namespace AlicizaX
|
|||||||
throw new GameFrameworkException(Text.Format("Can not decompress with exception '{0}'.", exception), exception);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ namespace AlicizaX
|
|||||||
|
|
||||||
public static float PingPong(float min, float max, float speed = 1f)
|
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)
|
public static int Wrap(int value, int min, int max)
|
||||||
|
|||||||
93
Runtime/ABase/Utility/Utility.Position.cs
Normal file
93
Runtime/ABase/Utility/Utility.Position.cs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace AlicizaX
|
||||||
|
{
|
||||||
|
public static partial class Utility
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 位置与几何相关的实用函数。
|
||||||
|
/// </summary>
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,8 +1,7 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 75d07d90984a5dc4698c98d2fe3809bf
|
guid: c82a27c2ab4545f687eac25a4d731f16
|
||||||
timeCreated: 1474948216
|
|
||||||
licenseType: Pro
|
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
118
Runtime/ABase/Utility/Utility.Time.cs
Normal file
118
Runtime/ABase/Utility/Utility.Time.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AlicizaX
|
||||||
|
{
|
||||||
|
public static partial class Utility
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 时间相关的实用函数。
|
||||||
|
/// </summary>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Runtime/ABase/Utility/Utility.Time.cs.meta
Normal file
11
Runtime/ABase/Utility/Utility.Time.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4c88fefb639f4d1dac58f77d9cbba2af
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -44,7 +44,7 @@ namespace AlicizaX
|
|||||||
source.clip = clip;
|
source.clip = clip;
|
||||||
source.volume = volume;
|
source.volume = volume;
|
||||||
source.Play();
|
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;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ namespace AlicizaX
|
|||||||
source.clip = clip;
|
source.clip = clip;
|
||||||
source.volume = volume;
|
source.volume = volume;
|
||||||
source.Play();
|
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;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ namespace AlicizaX
|
|||||||
source.volume = volume;
|
source.volume = volume;
|
||||||
source.maxDistance = maxDistance;
|
source.maxDistance = maxDistance;
|
||||||
source.Play();
|
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;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user