1
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b5a024b5076b4e48bf76a9036590c0b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7869f32c05eacac4a91f8018cc9cc875
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using static UnityEngine.AddressableAssets.Addressables;
|
||||
|
||||
/// <summary>
|
||||
/// AAResourceManager
|
||||
/// 通用的 Addressables (aa包) 资源管理器,用于统一管理游戏资源的加载和卸载。
|
||||
/// 通过标签 (Label) + 当前游戏类型 (GameType) 来筛选资源,
|
||||
/// 并使用映射字典 (name → id) 将资源绑定到对应的 ID,方便后续查找和使用。
|
||||
/// </summary>
|
||||
public static class AAResourceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载资源并存入目标字典
|
||||
/// </summary>
|
||||
/// <typeparam name="T">资源类型 (例如 GameObject, AudioClip, Sprite, SkeletonDataAsset)</typeparam>
|
||||
/// <param name="label">Addressables 标签,用于筛选资源</param>
|
||||
/// <param name="gameTypeLabel">玩法标签(由调用方/游戏侧传入,框架层不反向依赖游戏层)</param>
|
||||
/// <param name="mappingDic">映射字典 (资源名 → ID),用于将资源绑定到唯一 ID</param>
|
||||
/// <param name="targetDic">目标字典 (ID → 资源),存放加载后的资源</param>
|
||||
/// <param name="onLoaded">可选回调,在资源加载完成时执行 (例如绑定对象池)</param>
|
||||
/// <remarks>
|
||||
/// - 使用 Addressables.LoadAssetsAsync 按标签和玩法标签加载资源
|
||||
/// - 将资源存入 targetDic,键为映射字典中的 ID
|
||||
/// - 可选执行 onLoaded 回调,例如 Prefab 加入对象池
|
||||
/// - 最后释放 handle,避免内存泄漏
|
||||
/// </remarks>
|
||||
public static async Task LoadAssets<T>(
|
||||
string label,
|
||||
string gameTypeLabel,
|
||||
Dictionary<string, int> mappingDic,
|
||||
Dictionary<int, T> targetDic,
|
||||
Action<T, int> onLoaded = null)
|
||||
where T : UnityEngine.Object
|
||||
{
|
||||
// 构建 keys:标签 + 玩法标签
|
||||
var keys = new List<string> { label, gameTypeLabel };
|
||||
|
||||
// 异步加载资源
|
||||
var handle = Addressables.LoadAssetsAsync<T>(keys, asset =>
|
||||
{
|
||||
// 根据资源名查找对应 ID
|
||||
if (mappingDic.TryGetValue(asset.name, out int id))
|
||||
{
|
||||
targetDic[id] = asset; // 存入目标字典
|
||||
onLoaded?.Invoke(asset, id); // 执行回调
|
||||
}
|
||||
}, MergeMode.Intersection);
|
||||
|
||||
await handle.Task;
|
||||
|
||||
// 释放句柄,避免内存泄漏
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 卸载资源并从目标字典移除
|
||||
/// </summary>
|
||||
/// <typeparam name="T">资源类型 (例如 GameObject, AudioClip, Sprite, SkeletonDataAsset)</typeparam>
|
||||
/// <param name="label">Addressables 标签,用于筛选资源</param>
|
||||
/// <param name="gameTypeLabel">玩法标签(由调用方/游戏侧传入,框架层不反向依赖游戏层)</param>
|
||||
/// <param name="mappingDic">映射字典 (资源名 → ID),用于查找对应 ID</param>
|
||||
/// <param name="targetDic">目标字典 (ID → 资源),存放已加载的资源</param>
|
||||
/// <remarks>
|
||||
/// - 使用 Addressables.LoadAssetsAsync 获取当前标签下的资源列表
|
||||
/// - 遍历资源,查找对应 ID 并从 targetDic 移除
|
||||
/// - 最后释放 handle,避免内存泄漏
|
||||
/// </remarks>
|
||||
public static async Task UnloadAssets<T>(
|
||||
string label,
|
||||
string gameTypeLabel,
|
||||
Dictionary<string, int> mappingDic,
|
||||
Dictionary<int, T> targetDic)
|
||||
where T : UnityEngine.Object
|
||||
{
|
||||
// 构建 keys:标签 + 玩法标签
|
||||
var keys = new List<string> { label, gameTypeLabel };
|
||||
|
||||
// 异步加载资源列表(仅用于获取引用)
|
||||
var handle = Addressables.LoadAssetsAsync<T>(keys, null, MergeMode.Intersection);
|
||||
await handle.Task;
|
||||
|
||||
// 遍历资源并移除对应条目
|
||||
foreach (var asset in handle.Result)
|
||||
{
|
||||
if (mappingDic.TryGetValue(asset.name, out int id))
|
||||
{
|
||||
targetDic.Remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
// 释放句柄,避免内存泄漏
|
||||
Addressables.Release(handle);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18852f331ebfd804999b378e8fce13da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 148474591fcaf1849b134c7b8150d9aa
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,212 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
/// <summary>
|
||||
/// 知识点
|
||||
/// 1.AB包相关的API
|
||||
/// 2.单例模式
|
||||
/// 3.委托——>Lambda表达式
|
||||
/// 4.协程
|
||||
/// 5.字典
|
||||
/// </summary>
|
||||
public class ABMgr : AutoMonoSingleton<ABMgr>
|
||||
{
|
||||
//AB包管理器 目的是
|
||||
//让外部更方便的进行资源加载
|
||||
|
||||
//主包
|
||||
private AssetBundle mainAB = null;
|
||||
//依赖包获取用的配置文件
|
||||
private AssetBundleManifest manifest = null;
|
||||
|
||||
//AB包不能够重复加载 重复加载会报错
|
||||
//字典 用字典来存储 加载过的AB包
|
||||
private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();
|
||||
|
||||
/// <summary>
|
||||
/// 这个AB包存放路径 方便修改
|
||||
/// </summary>
|
||||
private string PathUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
return Application.streamingAssetsPath + "/";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 主包名 方便修改
|
||||
/// </summary>
|
||||
private string MainABName
|
||||
{
|
||||
get
|
||||
{
|
||||
#if UNITY_IOS
|
||||
return "IOS";
|
||||
#elif UNITY_ANDROID
|
||||
return "Android";
|
||||
#else
|
||||
return "StandaloneWindows";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载AB包
|
||||
/// </summary>
|
||||
/// <param name="abName"></param>
|
||||
public void LoadAB( string abName )
|
||||
{
|
||||
//加载AB包
|
||||
if (mainAB == null)
|
||||
{
|
||||
mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
|
||||
manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
|
||||
}
|
||||
//我们获取依赖包相关信息
|
||||
AssetBundle ab = null;
|
||||
string[] strs = manifest.GetAllDependencies(abName);
|
||||
for (int i = 0; i < strs.Length; i++)
|
||||
{
|
||||
//判断包是否加载过
|
||||
if (!abDic.ContainsKey(strs[i]))
|
||||
{
|
||||
ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
|
||||
abDic.Add(strs[i], ab);
|
||||
}
|
||||
}
|
||||
//加载资源来源包
|
||||
//如果没有加载过 再加载
|
||||
if (!abDic.ContainsKey(abName))
|
||||
{
|
||||
ab = AssetBundle.LoadFromFile(PathUrl + abName);
|
||||
abDic.Add(abName, ab);
|
||||
}
|
||||
}
|
||||
|
||||
//同步加载 不指定类型
|
||||
public Object LoadRes(string abName, string resName)
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
Object obj = abDic[abName].LoadAsset(resName);
|
||||
if (obj is GameObject)
|
||||
return Instantiate(obj);
|
||||
else
|
||||
return obj;
|
||||
}
|
||||
|
||||
//同步加载 根据type指定类型
|
||||
public Object LoadRes(string abName, string resName, System.Type type)
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
Object obj = abDic[abName].LoadAsset(resName, type);
|
||||
if (obj is GameObject)
|
||||
return Instantiate(obj);
|
||||
else
|
||||
return obj;
|
||||
}
|
||||
|
||||
//同步加载 根据泛型指定类型
|
||||
public T LoadRes<T>(string abName, string resName) where T:Object
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
T obj = abDic[abName].LoadAsset<T>(resName);
|
||||
if (obj is GameObject)
|
||||
return Instantiate(obj);
|
||||
else
|
||||
return obj;
|
||||
}
|
||||
|
||||
//异步加载的方法
|
||||
//这里的异步加载 AB包并没有使用异步加载
|
||||
//知识从AB包中 加载资源时 使用异步
|
||||
//根据名字异步加载资源
|
||||
public void LoadResAsync(string abName, string resName, UnityAction<Object> callBack)
|
||||
{
|
||||
StartCoroutine(ReallyLoadResAsync(abName, resName, callBack));
|
||||
}
|
||||
private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callBack)
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
|
||||
yield return abr;
|
||||
//异步加载结束后 通过委托 传递给外部 外部来使用
|
||||
if (abr.asset is GameObject)
|
||||
callBack(Instantiate(abr.asset));
|
||||
else
|
||||
callBack(abr.asset);
|
||||
}
|
||||
|
||||
//根据Type异步加载资源
|
||||
public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
|
||||
{
|
||||
StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));
|
||||
}
|
||||
private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
|
||||
yield return abr;
|
||||
//异步加载结束后 通过委托 传递给外部 外部来使用
|
||||
if (abr.asset is GameObject)
|
||||
callBack(Instantiate(abr.asset));
|
||||
else
|
||||
callBack(abr.asset);
|
||||
}
|
||||
|
||||
|
||||
//根据泛型 异步加载资源
|
||||
public void LoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T:Object
|
||||
{
|
||||
StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callBack));
|
||||
}
|
||||
private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
|
||||
{
|
||||
//加载AB包
|
||||
LoadAB(abName);
|
||||
//为了外面方便 在加载资源时 判断一下 资源是不是GameObject
|
||||
//如果是 直接实例化了 再返回给外部
|
||||
AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);
|
||||
yield return abr;
|
||||
//异步加载结束后 通过委托 传递给外部 外部来使用
|
||||
if (abr.asset is GameObject)
|
||||
callBack(Instantiate(abr.asset) as T);
|
||||
else
|
||||
callBack(abr.asset as T);
|
||||
}
|
||||
|
||||
//单个包卸载
|
||||
public void UnLoad(string abName)
|
||||
{
|
||||
if( abDic.ContainsKey(abName) )
|
||||
{
|
||||
abDic[abName].Unload(false);
|
||||
abDic.Remove(abName);
|
||||
}
|
||||
}
|
||||
|
||||
//所有包的卸载
|
||||
public void ClearAB()
|
||||
{
|
||||
AssetBundle.UnloadAllAssetBundles(false);
|
||||
abDic.Clear();
|
||||
mainAB = null;
|
||||
manifest = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11e3c2c0028c7c44d8523bc91ef4fb1b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60b851e1a0e38524296024ab447bc15d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class AutoMonoSingleton<T>: MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T _instance;
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_instance==null)
|
||||
{
|
||||
GameObject obj = new GameObject();
|
||||
obj.name = typeof(T).ToString();
|
||||
DontDestroyOnLoad(obj);
|
||||
_instance = obj.AddComponent<T>();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83e2c93ea050f244487572f6c78a1dbb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T _instance;
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance==null)
|
||||
{
|
||||
_instance = FindObjectOfType<T>();
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = new GameObject().AddComponent<T>();
|
||||
}
|
||||
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_instance = this as T;
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bcd03eada2a3a604984f7f1708bf6d00
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,17 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Singleton<T> where T:new()
|
||||
{
|
||||
private static T _instance;
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
_instance = new T();
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3b4544c50b6e8b4b9122f3dc35f907b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d74fb167e3f2c9f4892e944235780644
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,144 @@
|
||||
#region zijixie
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Device;
|
||||
using Screen = UnityEngine.Screen;
|
||||
|
||||
public static class CoordinateTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// 世界坐标转换成总父 Canvas 下的 anchoredPosition
|
||||
/// </summary>
|
||||
public static Vector2 WorldPos_ToCanvas(Vector3 worldPos, Canvas canvas)
|
||||
{
|
||||
var screenPos = Camera.main.WorldToScreenPoint(worldPos);
|
||||
RectTransform canvasRT = canvas.GetComponent<RectTransform>();
|
||||
|
||||
// 2. 屏幕 → Canvas 局部坐标(Overlay 模式 cam 必须为 null)
|
||||
Vector2 canvasLocalPos;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvasRT,
|
||||
screenPos,
|
||||
canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
|
||||
out canvasLocalPos
|
||||
);
|
||||
|
||||
return canvasLocalPos;
|
||||
}
|
||||
/// <summary>
|
||||
/// 屏幕坐标 → Canvas 坐标(RectTransform 的 anchoredPosition)
|
||||
/// </summary>
|
||||
public static Vector2 ScreenPoint_ToCanvas(Vector2 screenPos, Canvas canvas)
|
||||
{
|
||||
RectTransform canvasRect = canvas.GetComponent<RectTransform>();
|
||||
|
||||
Vector2 localPoint;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvasRect,
|
||||
screenPos,
|
||||
canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
|
||||
out localPoint);
|
||||
|
||||
return localPoint;
|
||||
}
|
||||
public static Vector3 UIToWorld(RectTransform targetUI, RectTransform targetCanvas)
|
||||
{
|
||||
|
||||
|
||||
|
||||
return CanvasToWorld(GetLocalPositionRelativeToCanvas(targetUI, targetCanvas), targetCanvas, Camera.main);
|
||||
}
|
||||
/// <summary>
|
||||
/// 计算某个 UI 元素相对于指定 Canvas 的局部坐标(基于 Canvas 轴心)
|
||||
/// </summary>
|
||||
/// <param name="targetUI">要计算的 UI 元素的 RectTransform</param>
|
||||
/// <param name="targetCanvas">目标 Canvas 的 RectTransform</param>
|
||||
/// <returns>相对于 Canvas 轴心的局部坐标(Vector3)</returns>
|
||||
public static Vector3 GetLocalPositionRelativeToCanvas(RectTransform targetUI, RectTransform targetCanvas)
|
||||
{
|
||||
Vector3 worldPos = targetUI.position; // 轴心世界坐标
|
||||
return targetCanvas.InverseTransformPoint(worldPos);
|
||||
}
|
||||
public static Vector3 CanvasToWorld(Vector2 canvasPos, RectTransform canvas, Camera cam)
|
||||
{
|
||||
// 1. 获取 Canvas 实际像素尺寸(自动适配所有设备)
|
||||
float canvasWidth = canvas.rect.width;
|
||||
float canvasHeight = canvas.rect.height;
|
||||
|
||||
// 2. 正交相机的世界高度
|
||||
float worldHeight = cam.orthographicSize * 2f;
|
||||
|
||||
// 3. 世界宽度 = 世界高度 * 屏幕宽高比
|
||||
float worldWidth = worldHeight * cam.aspect;
|
||||
|
||||
// 4. 画布单位 → 世界单位比例(横竖一致)
|
||||
float scaleX = worldWidth / canvasWidth;
|
||||
float scaleY = worldHeight / canvasHeight;
|
||||
|
||||
// 5. 你的 canvasPos 是以中心为原点的坐标
|
||||
float worldX = canvasPos.x * scaleX;
|
||||
float worldY = canvasPos.y * scaleY;
|
||||
|
||||
// 6. 映射到世界 z = 0 平面
|
||||
return new Vector3(worldX, worldY, 0f);
|
||||
}
|
||||
/// <summary>
|
||||
/// 从子坐标转换成总父canvas坐标
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="canvas"></param>
|
||||
/// <returns></returns>
|
||||
public static Vector2 AnchoredPos_ToCanvas(RectTransform target, Canvas canvas)
|
||||
{
|
||||
// 1. 先把 anchoredPosition(父坐标)转换成世界坐标
|
||||
Vector3 worldPos = target.TransformPoint(target.anchoredPosition);
|
||||
|
||||
// 2. 再把世界坐标转换成 Canvas 的局部坐标(等价于 Canvas 下的 anchoredPosition)
|
||||
RectTransform canvasRT = canvas.GetComponent<RectTransform>();
|
||||
|
||||
Vector2 canvasLocalPos;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
canvasRT,
|
||||
RectTransformUtility.WorldToScreenPoint(canvas.worldCamera, worldPos),
|
||||
canvas.renderMode == RenderMode.ScreenSpaceOverlay ? null : canvas.worldCamera,
|
||||
out canvasLocalPos
|
||||
);
|
||||
|
||||
return canvasLocalPos;
|
||||
}
|
||||
public static Vector3 ScreenToWord(Vector3 screenVector3)
|
||||
{
|
||||
return Camera.main.ScreenToWorldPoint(screenVector3);
|
||||
}
|
||||
public static Vector3 ScreenToCamera(Vector3 screenPos,Camera cam=null)
|
||||
{
|
||||
float targetZ = 0;
|
||||
if (cam==null)
|
||||
{
|
||||
cam=Camera.main;
|
||||
}
|
||||
// 1. 屏幕左下角原点 → 屏幕中心原点
|
||||
float cx = screenPos.x - Screen.width * 0.5f;
|
||||
float cy = screenPos.y - Screen.height * 0.5f;
|
||||
|
||||
// 2. 屏幕中心原点 → Unity 标准屏幕坐标(左下角原点)
|
||||
float ux = cx + Screen.width * 0.5f;
|
||||
float uy = cy + Screen.height * 0.5f;
|
||||
|
||||
// 3. 屏幕 → 世界
|
||||
float distance = Mathf.Abs(cam.transform.position.z - targetZ);
|
||||
Vector3 worldPos = cam.ScreenToWorldPoint(new Vector3(ux, uy, distance));
|
||||
worldPos.z = targetZ;
|
||||
|
||||
// 4. 世界 → 相机坐标(相机中心为原点)
|
||||
float worldHeight = cam.orthographicSize;
|
||||
|
||||
return cam.transform.InverseTransformPoint(worldPos);
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf0db1470318abc41bf6af07f8f9918b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f7ac6af63e83c94fbc2268aaafb8658
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,198 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
#if !DOTWEEN_NOAUDIO // MODULE_MARKER
|
||||
using System;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio; // Required for AudioMixer
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModuleAudio
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region Audio
|
||||
|
||||
/// <summary>Tweens an AudioSource's volume to the given value.
|
||||
/// Also stores the AudioSource as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach (0 to 1)</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOFade(this AudioSource target, float endValue, float duration)
|
||||
{
|
||||
if (endValue < 0) endValue = 0;
|
||||
else if (endValue > 1) endValue = 1;
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.volume, x => target.volume = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an AudioSource's pitch to the given value.
|
||||
/// Also stores the AudioSource as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOPitch(this AudioSource target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.pitch, x => target.pitch = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region AudioMixer
|
||||
|
||||
/// <summary>Tweens an AudioMixer's exposed float to the given value.
|
||||
/// Also stores the AudioMixer as the tween's target so it can be used for filtered operations.
|
||||
/// Note that you need to manually expose a float in an AudioMixerGroup in order to be able to tween it from an AudioMixer.</summary>
|
||||
/// <param name="floatName">Name given to the exposed float to set</param>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOSetFloat(this AudioMixer target, string floatName, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(()=> {
|
||||
float currVal;
|
||||
target.GetFloat(floatName, out currVal);
|
||||
return currVal;
|
||||
}, x=> target.SetFloat(floatName, x), endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#region Operation Shortcuts
|
||||
|
||||
/// <summary>
|
||||
/// Completes all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens completed
|
||||
/// (meaning the tweens that don't have infinite loops and were not already complete)
|
||||
/// </summary>
|
||||
/// <param name="withCallbacks">For Sequences only: if TRUE also internal Sequence callbacks will be fired,
|
||||
/// otherwise they will be ignored</param>
|
||||
public static int DOComplete(this AudioMixer target, bool withCallbacks = false)
|
||||
{
|
||||
return DOTween.Complete(target, withCallbacks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Kills all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens killed.
|
||||
/// </summary>
|
||||
/// <param name="complete">If TRUE completes the tween before killing it</param>
|
||||
public static int DOKill(this AudioMixer target, bool complete = false)
|
||||
{
|
||||
return DOTween.Kill(target, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flips the direction (backwards if it was going forward or viceversa) of all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens flipped.
|
||||
/// </summary>
|
||||
public static int DOFlip(this AudioMixer target)
|
||||
{
|
||||
return DOTween.Flip(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends to the given position all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens involved.
|
||||
/// </summary>
|
||||
/// <param name="to">Time position to reach
|
||||
/// (if higher than the whole tween duration the tween will simply reach its end)</param>
|
||||
/// <param name="andPlay">If TRUE will play the tween after reaching the given position, otherwise it will pause it</param>
|
||||
public static int DOGoto(this AudioMixer target, float to, bool andPlay = false)
|
||||
{
|
||||
return DOTween.Goto(target, to, andPlay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pauses all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens paused.
|
||||
/// </summary>
|
||||
public static int DOPause(this AudioMixer target)
|
||||
{
|
||||
return DOTween.Pause(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens played.
|
||||
/// </summary>
|
||||
public static int DOPlay(this AudioMixer target)
|
||||
{
|
||||
return DOTween.Play(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays backwards all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens played.
|
||||
/// </summary>
|
||||
public static int DOPlayBackwards(this AudioMixer target)
|
||||
{
|
||||
return DOTween.PlayBackwards(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays forward all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens played.
|
||||
/// </summary>
|
||||
public static int DOPlayForward(this AudioMixer target)
|
||||
{
|
||||
return DOTween.PlayForward(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restarts all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens restarted.
|
||||
/// </summary>
|
||||
public static int DORestart(this AudioMixer target)
|
||||
{
|
||||
return DOTween.Restart(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rewinds all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens rewinded.
|
||||
/// </summary>
|
||||
public static int DORewind(this AudioMixer target)
|
||||
{
|
||||
return DOTween.Rewind(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Smoothly rewinds all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens rewinded.
|
||||
/// </summary>
|
||||
public static int DOSmoothRewind(this AudioMixer target)
|
||||
{
|
||||
return DOTween.SmoothRewind(target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles the paused state (plays if it was paused, pauses if it was playing) of all tweens that have this target as a reference
|
||||
/// (meaning tweens that were started from this target, or that had this target added as an Id)
|
||||
/// and returns the total number of tweens involved.
|
||||
/// </summary>
|
||||
public static int DOTogglePause(this AudioMixer target)
|
||||
{
|
||||
return DOTween.TogglePause(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b766d08851589514b97afb23c6f30a70
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,146 @@
|
||||
using UnityEngine;
|
||||
|
||||
#if DOTWEEN_EPO || EPO_DOTWEEN // MODULE_MARKER
|
||||
|
||||
using EPOOutline;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
using DG.Tweening;
|
||||
using DG.Tweening.Core;
|
||||
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModuleEPOOutline
|
||||
{
|
||||
public static int DOKill(this SerializedPass target, bool complete)
|
||||
{
|
||||
return DOTween.Kill(target, complete);
|
||||
}
|
||||
|
||||
public static TweenerCore<float, float, FloatOptions> DOFloat(this SerializedPass target, string propertyName, float endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetFloat(propertyName), x => target.SetFloat(propertyName, x), endValue, duration);
|
||||
tweener.SetOptions(true).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this SerializedPass target, string propertyName, float endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.ToAlpha(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration);
|
||||
tweener.SetOptions(true).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this SerializedPass target, string propertyName, Color endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetColor(propertyName), x => target.SetColor(propertyName, x), endValue, duration);
|
||||
tweener.SetOptions(false).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Vector4, Vector4, VectorOptions> DOVector(this SerializedPass target, string propertyName, Vector4 endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetVector(propertyName), x => target.SetVector(propertyName, x), endValue, duration);
|
||||
tweener.SetOptions(false).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<float, float, FloatOptions> DOFloat(this SerializedPass target, int propertyId, float endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetFloat(propertyId), x => target.SetFloat(propertyId, x), endValue, duration);
|
||||
tweener.SetOptions(true).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this SerializedPass target, int propertyId, float endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.ToAlpha(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration);
|
||||
tweener.SetOptions(true).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this SerializedPass target, int propertyId, Color endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetColor(propertyId), x => target.SetColor(propertyId, x), endValue, duration);
|
||||
tweener.SetOptions(false).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static TweenerCore<Vector4, Vector4, VectorOptions> DOVector(this SerializedPass target, int propertyId, Vector4 endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.GetVector(propertyId), x => target.SetVector(propertyId, x), endValue, duration);
|
||||
tweener.SetOptions(false).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
public static int DOKill(this Outlinable.OutlineProperties target, bool complete = false)
|
||||
{
|
||||
return DOTween.Kill(target, complete);
|
||||
}
|
||||
|
||||
public static int DOKill(this Outliner target, bool complete = false)
|
||||
{
|
||||
return DOTween.Kill(target, complete);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the alpha (transparency) of the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Outlinable.OutlineProperties target, float endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.ToAlpha(() => target.Color, x => target.Color = x, endValue, duration);
|
||||
tweener.SetOptions(true).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the color of the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Outlinable.OutlineProperties target, Color endValue, float duration)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.Color, x => target.Color = x, endValue, duration);
|
||||
tweener.SetOptions(false).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the amount of blur applied to the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<float, float, FloatOptions> DOBlurShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration);
|
||||
tweener.SetOptions(snapping).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the amount of blur applied to the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<float, float, FloatOptions> DOBlurShift(this Outliner target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.BlurShift, x => target.BlurShift = x, endValue, duration);
|
||||
tweener.SetOptions(snapping).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the amount of dilation applied to the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<float, float, FloatOptions> DODilateShift(this Outlinable.OutlineProperties target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration);
|
||||
tweener.SetOptions(snapping).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controls the amount of dilation applied to the outline
|
||||
/// </summary>
|
||||
public static TweenerCore<float, float, FloatOptions> DODilateShift(this Outliner target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
var tweener = DOTween.To(() => target.DilateShift, x => target.DilateShift = x, endValue, duration);
|
||||
tweener.SetOptions(snapping).SetTarget(target);
|
||||
return tweener;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e944529dcaee98f4e9498d80e541d93e
|
||||
timeCreated: 1602593330
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,216 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
#if !DOTWEEN_NOPHYSICS // MODULE_MARKER
|
||||
using System;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Core.Enums;
|
||||
using DG.Tweening.Plugins;
|
||||
using DG.Tweening.Plugins.Core.PathCore;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModulePhysics
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region Rigidbody
|
||||
|
||||
/// <summary>Tweens a Rigidbody's position to the given value.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMove(this Rigidbody target, Vector3 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's X position to the given value.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveX(this Rigidbody target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue, 0, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's Y position to the given value.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveY(this Rigidbody target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's Z position to the given value.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveZ(this Rigidbody target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's rotation to the given value.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="mode">Rotation mode</param>
|
||||
public static TweenerCore<Quaternion, Vector3, QuaternionOptions> DORotate(this Rigidbody target, Vector3 endValue, float duration, RotateMode mode = RotateMode.Fast)
|
||||
{
|
||||
TweenerCore<Quaternion, Vector3, QuaternionOptions> t = DOTween.To(() => target.rotation, target.MoveRotation, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
t.plugOptions.rotateMode = mode;
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's rotation so that it will look towards the given position.
|
||||
/// Also stores the rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="towards">The position to look at</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="axisConstraint">Eventual axis constraint for the rotation</param>
|
||||
/// <param name="up">The vector that defines in which direction up is (default: Vector3.up)</param>
|
||||
public static TweenerCore<Quaternion, Vector3, QuaternionOptions> DOLookAt(this Rigidbody target, Vector3 towards, float duration, AxisConstraint axisConstraint = AxisConstraint.None, Vector3? up = null)
|
||||
{
|
||||
TweenerCore<Quaternion, Vector3, QuaternionOptions> t = DOTween.To(() => target.rotation, target.MoveRotation, towards, duration)
|
||||
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetLookAt);
|
||||
t.plugOptions.axisConstraint = axisConstraint;
|
||||
t.plugOptions.up = (up == null) ? Vector3.up : (Vector3)up;
|
||||
return t;
|
||||
}
|
||||
|
||||
#region Special
|
||||
|
||||
/// <summary>Tweens a Rigidbody's position to the given value, while also applying a jump effect along the Y axis.
|
||||
/// Returns a Sequence instead of a Tweener.
|
||||
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="jumpPower">Power of the jump (the max height of the jump is represented by this plus the final Y offset)</param>
|
||||
/// <param name="numJumps">Total number of jumps</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Sequence DOJump(this Rigidbody target, Vector3 endValue, float jumpPower, int numJumps, float duration, bool snapping = false)
|
||||
{
|
||||
if (numJumps < 1) numJumps = 1;
|
||||
float startPosY = 0;
|
||||
float offsetY = -1;
|
||||
bool offsetYSet = false;
|
||||
Sequence s = DOTween.Sequence();
|
||||
Tween yTween = DOTween.To(() => target.position, target.MovePosition, new Vector3(0, jumpPower, 0), duration / (numJumps * 2))
|
||||
.SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative()
|
||||
.SetLoops(numJumps * 2, LoopType.Yoyo)
|
||||
.OnStart(() => startPosY = target.position.y);
|
||||
s.Append(DOTween.To(() => target.position, target.MovePosition, new Vector3(endValue.x, 0, 0), duration)
|
||||
.SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear)
|
||||
).Join(DOTween.To(() => target.position, target.MovePosition, new Vector3(0, 0, endValue.z), duration)
|
||||
.SetOptions(AxisConstraint.Z, snapping).SetEase(Ease.Linear)
|
||||
).Join(yTween)
|
||||
.SetTarget(target).SetEase(DOTween.defaultEaseType);
|
||||
yTween.OnUpdate(() => {
|
||||
if (!offsetYSet) {
|
||||
offsetYSet = true;
|
||||
offsetY = s.isRelative ? endValue.y : endValue.y - startPosY;
|
||||
}
|
||||
Vector3 pos = target.position;
|
||||
pos.y += DOVirtual.EasedValue(0, offsetY, yTween.ElapsedPercentage(), Ease.OutQuad);
|
||||
target.MovePosition(pos);
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody's position through the given path waypoints, using the chosen path algorithm.
|
||||
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations.
|
||||
/// <para>NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened.</para>
|
||||
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
|
||||
/// If you plan to publish there you should use a regular transform.DOPath.</para></summary>
|
||||
/// <param name="path">The waypoints to go through</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
|
||||
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
|
||||
/// <param name="resolution">The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive.
|
||||
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
|
||||
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
|
||||
public static TweenerCore<Vector3, Path, PathOptions> DOPath(
|
||||
this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear,
|
||||
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
|
||||
)
|
||||
{
|
||||
if (resolution < 1) resolution = 1;
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, new Path(pathType, path, resolution, gizmoColor), duration)
|
||||
.SetTarget(target).SetUpdate(UpdateType.Fixed);
|
||||
|
||||
t.plugOptions.isRigidbody = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a Rigidbody's localPosition through the given path waypoints, using the chosen path algorithm.
|
||||
/// Also stores the Rigidbody as the tween's target so it can be used for filtered operations
|
||||
/// <para>NOTE: to tween a rigidbody correctly it should be set to kinematic at least while being tweened.</para>
|
||||
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
|
||||
/// If you plan to publish there you should use a regular transform.DOLocalPath.</para></summary>
|
||||
/// <param name="path">The waypoint to go through</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
|
||||
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
|
||||
/// <param name="resolution">The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive.
|
||||
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
|
||||
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
|
||||
public static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
|
||||
this Rigidbody target, Vector3[] path, float duration, PathType pathType = PathType.Linear,
|
||||
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
|
||||
)
|
||||
{
|
||||
if (resolution < 1) resolution = 1;
|
||||
Transform trans = target.transform;
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), new Path(pathType, path, resolution, gizmoColor), duration)
|
||||
.SetTarget(target).SetUpdate(UpdateType.Fixed);
|
||||
|
||||
t.plugOptions.isRigidbody = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
t.plugOptions.useLocalPosition = true;
|
||||
return t;
|
||||
}
|
||||
// Used by path editor when creating the actual tween, so it can pass a pre-compiled path
|
||||
internal static TweenerCore<Vector3, Path, PathOptions> DOPath(
|
||||
this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D
|
||||
)
|
||||
{
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, target.MovePosition, path, duration)
|
||||
.SetTarget(target);
|
||||
|
||||
t.plugOptions.isRigidbody = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
return t;
|
||||
}
|
||||
internal static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
|
||||
this Rigidbody target, Path path, float duration, PathMode pathMode = PathMode.Full3D
|
||||
)
|
||||
{
|
||||
Transform trans = target.transform;
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), path, duration)
|
||||
.SetTarget(target);
|
||||
|
||||
t.plugOptions.isRigidbody = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
t.plugOptions.useLocalPosition = true;
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dae9aa560b4242648a3affa2bfabc365
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,193 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
#if !DOTWEEN_NOPHYSICS2D // MODULE_MARKER
|
||||
using System;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Plugins;
|
||||
using DG.Tweening.Plugins.Core.PathCore;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
using UnityEngine;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModulePhysics2D
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region Rigidbody2D Shortcuts
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's position to the given value.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOMove(this Rigidbody2D target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's X position to the given value.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOMoveX(this Rigidbody2D target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector2(endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's Y position to the given value.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOMoveY(this Rigidbody2D target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.position, target.MovePosition, new Vector2(0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's rotation to the given value.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DORotate(this Rigidbody2D target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.rotation, target.MoveRotation, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#region Special
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's position to the given value, while also applying a jump effect along the Y axis.
|
||||
/// Returns a Sequence instead of a Tweener.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations.
|
||||
/// <para>IMPORTANT: a rigidbody2D can't be animated in a jump arc using MovePosition, so the tween will directly set the position</para></summary>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="jumpPower">Power of the jump (the max height of the jump is represented by this plus the final Y offset)</param>
|
||||
/// <param name="numJumps">Total number of jumps</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Sequence DOJump(this Rigidbody2D target, Vector2 endValue, float jumpPower, int numJumps, float duration, bool snapping = false)
|
||||
{
|
||||
if (numJumps < 1) numJumps = 1;
|
||||
float startPosY = 0;
|
||||
float offsetY = -1;
|
||||
bool offsetYSet = false;
|
||||
Sequence s = DOTween.Sequence();
|
||||
Tween yTween = DOTween.To(() => target.position, x => target.position = x, new Vector2(0, jumpPower), duration / (numJumps * 2))
|
||||
.SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative()
|
||||
.SetLoops(numJumps * 2, LoopType.Yoyo)
|
||||
.OnStart(() => startPosY = target.position.y);
|
||||
s.Append(DOTween.To(() => target.position, x => target.position = x, new Vector2(endValue.x, 0), duration)
|
||||
.SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear)
|
||||
).Join(yTween)
|
||||
.SetTarget(target).SetEase(DOTween.defaultEaseType);
|
||||
yTween.OnUpdate(() => {
|
||||
if (!offsetYSet) {
|
||||
offsetYSet = true;
|
||||
offsetY = s.isRelative ? endValue.y : endValue.y - startPosY;
|
||||
}
|
||||
Vector3 pos = target.position;
|
||||
pos.y += DOVirtual.EasedValue(0, offsetY, yTween.ElapsedPercentage(), Ease.OutQuad);
|
||||
target.MovePosition(pos);
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Rigidbody2D's position through the given path waypoints, using the chosen path algorithm.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations.
|
||||
/// <para>NOTE: to tween a Rigidbody2D correctly it should be set to kinematic at least while being tweened.</para>
|
||||
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
|
||||
/// If you plan to publish there you should use a regular transform.DOPath.</para></summary>
|
||||
/// <param name="path">The waypoints to go through</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
|
||||
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
|
||||
/// <param name="resolution">The resolution of the path (useless in case of Linear paths): higher resolutions make for more detailed curved paths but are more expensive.
|
||||
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
|
||||
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
|
||||
public static TweenerCore<Vector3, Path, PathOptions> DOPath(
|
||||
this Rigidbody2D target, Vector2[] path, float duration, PathType pathType = PathType.Linear,
|
||||
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
|
||||
)
|
||||
{
|
||||
if (resolution < 1) resolution = 1;
|
||||
int len = path.Length;
|
||||
Vector3[] path3D = new Vector3[len];
|
||||
for (int i = 0; i < len; ++i) path3D[i] = path[i];
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, x => target.MovePosition(x), new Path(pathType, path3D, resolution, gizmoColor), duration)
|
||||
.SetTarget(target).SetUpdate(UpdateType.Fixed);
|
||||
|
||||
t.plugOptions.isRigidbody2D = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a Rigidbody2D's localPosition through the given path waypoints, using the chosen path algorithm.
|
||||
/// Also stores the Rigidbody2D as the tween's target so it can be used for filtered operations
|
||||
/// <para>NOTE: to tween a Rigidbody2D correctly it should be set to kinematic at least while being tweened.</para>
|
||||
/// <para>BEWARE: doesn't work on Windows Phone store (waiting for Unity to fix their own bug).
|
||||
/// If you plan to publish there you should use a regular transform.DOLocalPath.</para></summary>
|
||||
/// <param name="path">The waypoint to go through</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="pathType">The type of path: Linear (straight path), CatmullRom (curved CatmullRom path) or CubicBezier (curved with control points)</param>
|
||||
/// <param name="pathMode">The path mode: 3D, side-scroller 2D, top-down 2D</param>
|
||||
/// <param name="resolution">The resolution of the path: higher resolutions make for more detailed curved paths but are more expensive.
|
||||
/// Defaults to 10, but a value of 5 is usually enough if you don't have dramatic long curves between waypoints</param>
|
||||
/// <param name="gizmoColor">The color of the path (shown when gizmos are active in the Play panel and the tween is running)</param>
|
||||
public static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
|
||||
this Rigidbody2D target, Vector2[] path, float duration, PathType pathType = PathType.Linear,
|
||||
PathMode pathMode = PathMode.Full3D, int resolution = 10, Color? gizmoColor = null
|
||||
)
|
||||
{
|
||||
if (resolution < 1) resolution = 1;
|
||||
int len = path.Length;
|
||||
Vector3[] path3D = new Vector3[len];
|
||||
for (int i = 0; i < len; ++i) path3D[i] = path[i];
|
||||
Transform trans = target.transform;
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), new Path(pathType, path3D, resolution, gizmoColor), duration)
|
||||
.SetTarget(target).SetUpdate(UpdateType.Fixed);
|
||||
|
||||
t.plugOptions.isRigidbody2D = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
t.plugOptions.useLocalPosition = true;
|
||||
return t;
|
||||
}
|
||||
// Used by path editor when creating the actual tween, so it can pass a pre-compiled path
|
||||
internal static TweenerCore<Vector3, Path, PathOptions> DOPath(
|
||||
this Rigidbody2D target, Path path, float duration, PathMode pathMode = PathMode.Full3D
|
||||
)
|
||||
{
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => target.position, x => target.MovePosition(x), path, duration)
|
||||
.SetTarget(target);
|
||||
|
||||
t.plugOptions.isRigidbody2D = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
return t;
|
||||
}
|
||||
internal static TweenerCore<Vector3, Path, PathOptions> DOLocalPath(
|
||||
this Rigidbody2D target, Path path, float duration, PathMode pathMode = PathMode.Full3D
|
||||
)
|
||||
{
|
||||
Transform trans = target.transform;
|
||||
TweenerCore<Vector3, Path, PathOptions> t = DOTween.To(PathPlugin.Get(), () => trans.localPosition, x => target.MovePosition(trans.parent == null ? x : trans.parent.TransformPoint(x)), path, duration)
|
||||
.SetTarget(target);
|
||||
|
||||
t.plugOptions.isRigidbody2D = true;
|
||||
t.plugOptions.mode = pathMode;
|
||||
t.plugOptions.useLocalPosition = true;
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 230fe34542e175245ba74b4659dae700
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,93 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
#if !DOTWEEN_NOSPRITES // MODULE_MARKER
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModuleSprite
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region SpriteRenderer
|
||||
|
||||
/// <summary>Tweens a SpriteRenderer's color to the given value.
|
||||
/// Also stores the spriteRenderer as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this SpriteRenderer target, Color endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.To(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Material's alpha color to the given value.
|
||||
/// Also stores the spriteRenderer as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this SpriteRenderer target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a SpriteRenderer's color using the given gradient
|
||||
/// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener).
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="gradient">The gradient to use</param><param name="duration">The duration of the tween</param>
|
||||
public static Sequence DOGradientColor(this SpriteRenderer target, Gradient gradient, float duration)
|
||||
{
|
||||
Sequence s = DOTween.Sequence();
|
||||
GradientColorKey[] colors = gradient.colorKeys;
|
||||
int len = colors.Length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
GradientColorKey c = colors[i];
|
||||
if (i == 0 && c.time <= 0) {
|
||||
target.color = c.color;
|
||||
continue;
|
||||
}
|
||||
float colorDuration = i == len - 1
|
||||
? duration - s.Duration(false) // Verifies that total duration is correct
|
||||
: duration * (i == 0 ? c.time : c.time - colors[i - 1].time);
|
||||
s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear));
|
||||
}
|
||||
s.SetTarget(target);
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Blendables
|
||||
|
||||
#region SpriteRenderer
|
||||
|
||||
/// <summary>Tweens a SpriteRenderer's color to the given value,
|
||||
/// in a way that allows other DOBlendableColor tweens to work together on the same target,
|
||||
/// instead than fight each other as multiple DOColor would do.
|
||||
/// Also stores the SpriteRenderer as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The value to tween to</param><param name="duration">The duration of the tween</param>
|
||||
public static Tweener DOBlendableColor(this SpriteRenderer target, Color endValue, float duration)
|
||||
{
|
||||
endValue = endValue - target.color;
|
||||
Color to = new Color(0, 0, 0, 0);
|
||||
return DOTween.To(() => to, x => {
|
||||
Color diff = x - to;
|
||||
to = x;
|
||||
target.color += diff;
|
||||
}, endValue, duration)
|
||||
.Blendable().SetTarget(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 188918ab119d93148aa0de59ccf5286b
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,662 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
#if !DOTWEEN_NOUI // MODULE_MARKER
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Core.Enums;
|
||||
using DG.Tweening.Plugins;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
using Outline = UnityEngine.UI.Outline;
|
||||
using Text = UnityEngine.UI.Text;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModuleUI
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region CanvasGroup
|
||||
|
||||
/// <summary>Tweens a CanvasGroup's alpha color to the given value.
|
||||
/// Also stores the canvasGroup as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOFade(this CanvasGroup target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.alpha, x => target.alpha = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Graphic
|
||||
|
||||
/// <summary>Tweens an Graphic's color to the given value.
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Graphic target, Color endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.To(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an Graphic's alpha color to the given value.
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Graphic target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image
|
||||
|
||||
/// <summary>Tweens an Image's color to the given value.
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Image target, Color endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.To(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an Image's alpha color to the given value.
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Image target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an Image's fillAmount to the given value.
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach (0 to 1)</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOFillAmount(this Image target, float endValue, float duration)
|
||||
{
|
||||
if (endValue > 1) endValue = 1;
|
||||
else if (endValue < 0) endValue = 0;
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.fillAmount, x => target.fillAmount = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an Image's colors using the given gradient
|
||||
/// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener).
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="gradient">The gradient to use</param><param name="duration">The duration of the tween</param>
|
||||
public static Sequence DOGradientColor(this Image target, Gradient gradient, float duration)
|
||||
{
|
||||
Sequence s = DOTween.Sequence();
|
||||
GradientColorKey[] colors = gradient.colorKeys;
|
||||
int len = colors.Length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
GradientColorKey c = colors[i];
|
||||
if (i == 0 && c.time <= 0) {
|
||||
target.color = c.color;
|
||||
continue;
|
||||
}
|
||||
float colorDuration = i == len - 1
|
||||
? duration - s.Duration(false) // Verifies that total duration is correct
|
||||
: duration * (i == 0 ? c.time : c.time - colors[i - 1].time);
|
||||
s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear));
|
||||
}
|
||||
s.SetTarget(target);
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LayoutElement
|
||||
|
||||
/// <summary>Tweens an LayoutElement's flexibleWidth/Height to the given value.
|
||||
/// Also stores the LayoutElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOFlexibleSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => new Vector2(target.flexibleWidth, target.flexibleHeight), x => {
|
||||
target.flexibleWidth = x.x;
|
||||
target.flexibleHeight = x.y;
|
||||
}, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an LayoutElement's minWidth/Height to the given value.
|
||||
/// Also stores the LayoutElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOMinSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => new Vector2(target.minWidth, target.minHeight), x => {
|
||||
target.minWidth = x.x;
|
||||
target.minHeight = x.y;
|
||||
}, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens an LayoutElement's preferredWidth/Height to the given value.
|
||||
/// Also stores the LayoutElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOPreferredSize(this LayoutElement target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => new Vector2(target.preferredWidth, target.preferredHeight), x => {
|
||||
target.preferredWidth = x.x;
|
||||
target.preferredHeight = x.y;
|
||||
}, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Outline
|
||||
|
||||
/// <summary>Tweens a Outline's effectColor to the given value.
|
||||
/// Also stores the Outline as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Outline target, Color endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.To(() => target.effectColor, x => target.effectColor = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Outline's effectColor alpha to the given value.
|
||||
/// Also stores the Outline as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Outline target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.ToAlpha(() => target.effectColor, x => target.effectColor = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Outline's effectDistance to the given value.
|
||||
/// Also stores the Outline as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOScale(this Outline target, Vector2 endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.effectDistance, x => target.effectDistance = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RectTransform
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOAnchorPos(this RectTransform target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition X to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOAnchorPosX(this RectTransform target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition Y to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOAnchorPosY(this RectTransform target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition3D to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOAnchorPos3D(this RectTransform target, Vector3 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition3D X to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOAnchorPos3DX(this RectTransform target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(endValue, 0, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition3D Y to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOAnchorPos3DY(this RectTransform target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(0, endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition3D Z to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOAnchorPos3DZ(this RectTransform target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t = DOTween.To(() => target.anchoredPosition3D, x => target.anchoredPosition3D = x, new Vector3(0, 0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchorMax to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOAnchorMax(this RectTransform target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.anchorMax, x => target.anchorMax = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchorMin to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOAnchorMin(this RectTransform target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.anchorMin, x => target.anchorMin = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a RectTransform's pivot to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOPivot(this RectTransform target, Vector2 endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.pivot, x => target.pivot = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's pivot X to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOPivotX(this RectTransform target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.pivot, x => target.pivot = x, new Vector2(endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a RectTransform's pivot Y to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOPivotY(this RectTransform target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.pivot, x => target.pivot = x, new Vector2(0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Y).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a RectTransform's sizeDelta to the given value.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOSizeDelta(this RectTransform target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.sizeDelta, x => target.sizeDelta = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Punches a RectTransform's anchoredPosition towards the given direction and then back to the starting one
|
||||
/// as if it was connected to the starting position via an elastic.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="punch">The direction and strength of the punch (added to the RectTransform's current position)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="vibrato">Indicates how much will the punch vibrate</param>
|
||||
/// <param name="elasticity">Represents how much (0 to 1) the vector will go beyond the starting position when bouncing backwards.
|
||||
/// 1 creates a full oscillation between the punch direction and the opposite direction,
|
||||
/// while 0 oscillates only between the punch and the start position</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Tweener DOPunchAnchorPos(this RectTransform target, Vector2 punch, float duration, int vibrato = 10, float elasticity = 1, bool snapping = false)
|
||||
{
|
||||
return DOTween.Punch(() => target.anchoredPosition, x => target.anchoredPosition = x, punch, duration, vibrato, elasticity)
|
||||
.SetTarget(target).SetOptions(snapping);
|
||||
}
|
||||
|
||||
/// <summary>Shakes a RectTransform's anchoredPosition with the given values.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="strength">The shake strength</param>
|
||||
/// <param name="vibrato">Indicates how much will the shake vibrate</param>
|
||||
/// <param name="randomness">Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware).
|
||||
/// Setting it to 0 will shake along a single direction.</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
/// <param name="fadeOut">If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not</param>
|
||||
/// <param name="randomnessMode">Randomness mode</param>
|
||||
public static Tweener DOShakeAnchorPos(this RectTransform target, float duration, float strength = 100, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true, ShakeRandomnessMode randomnessMode = ShakeRandomnessMode.Full)
|
||||
{
|
||||
return DOTween.Shake(() => target.anchoredPosition, x => target.anchoredPosition = x, duration, strength, vibrato, randomness, true, fadeOut, randomnessMode)
|
||||
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping);
|
||||
}
|
||||
/// <summary>Shakes a RectTransform's anchoredPosition with the given values.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="strength">The shake strength on each axis</param>
|
||||
/// <param name="vibrato">Indicates how much will the shake vibrate</param>
|
||||
/// <param name="randomness">Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware).
|
||||
/// Setting it to 0 will shake along a single direction.</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
/// <param name="fadeOut">If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not</param>
|
||||
/// <param name="randomnessMode">Randomness mode</param>
|
||||
public static Tweener DOShakeAnchorPos(this RectTransform target, float duration, Vector2 strength, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true, ShakeRandomnessMode randomnessMode = ShakeRandomnessMode.Full)
|
||||
{
|
||||
return DOTween.Shake(() => target.anchoredPosition, x => target.anchoredPosition = x, duration, strength, vibrato, randomness, fadeOut, randomnessMode)
|
||||
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping);
|
||||
}
|
||||
|
||||
#region Special
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition to the given value, while also applying a jump effect along the Y axis.
|
||||
/// Returns a Sequence instead of a Tweener.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="jumpPower">Power of the jump (the max height of the jump is represented by this plus the final Y offset)</param>
|
||||
/// <param name="numJumps">Total number of jumps</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Sequence DOJumpAnchorPos(this RectTransform target, Vector2 endValue, float jumpPower, int numJumps, float duration, bool snapping = false)
|
||||
{
|
||||
if (numJumps < 1) numJumps = 1;
|
||||
float startPosY = 0;
|
||||
float offsetY = -1;
|
||||
bool offsetYSet = false;
|
||||
|
||||
// Separate Y Tween so we can elaborate elapsedPercentage on that insted of on the Sequence
|
||||
// (in case users add a delay or other elements to the Sequence)
|
||||
Sequence s = DOTween.Sequence();
|
||||
Tween yTween = DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(0, jumpPower), duration / (numJumps * 2))
|
||||
.SetOptions(AxisConstraint.Y, snapping).SetEase(Ease.OutQuad).SetRelative()
|
||||
.SetLoops(numJumps * 2, LoopType.Yoyo)
|
||||
.OnStart(()=> startPosY = target.anchoredPosition.y);
|
||||
s.Append(DOTween.To(() => target.anchoredPosition, x => target.anchoredPosition = x, new Vector2(endValue.x, 0), duration)
|
||||
.SetOptions(AxisConstraint.X, snapping).SetEase(Ease.Linear)
|
||||
).Join(yTween)
|
||||
.SetTarget(target).SetEase(DOTween.defaultEaseType);
|
||||
s.OnUpdate(() => {
|
||||
if (!offsetYSet) {
|
||||
offsetYSet = true;
|
||||
offsetY = s.isRelative ? endValue.y : endValue.y - startPosY;
|
||||
}
|
||||
Vector2 pos = target.anchoredPosition;
|
||||
pos.y += DOVirtual.EasedValue(0, offsetY, s.ElapsedDirectionalPercentage(), Ease.OutQuad);
|
||||
target.anchoredPosition = pos;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region ScrollRect
|
||||
|
||||
/// <summary>Tweens a ScrollRect's horizontal/verticalNormalizedPosition to the given value.
|
||||
/// Also stores the ScrollRect as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Tweener DONormalizedPos(this ScrollRect target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
return DOTween.To(() => new Vector2(target.horizontalNormalizedPosition, target.verticalNormalizedPosition),
|
||||
x => {
|
||||
target.horizontalNormalizedPosition = x.x;
|
||||
target.verticalNormalizedPosition = x.y;
|
||||
}, endValue, duration)
|
||||
.SetOptions(snapping).SetTarget(target);
|
||||
}
|
||||
/// <summary>Tweens a ScrollRect's horizontalNormalizedPosition to the given value.
|
||||
/// Also stores the ScrollRect as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Tweener DOHorizontalNormalizedPos(this ScrollRect target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
return DOTween.To(() => target.horizontalNormalizedPosition, x => target.horizontalNormalizedPosition = x, endValue, duration)
|
||||
.SetOptions(snapping).SetTarget(target);
|
||||
}
|
||||
/// <summary>Tweens a ScrollRect's verticalNormalizedPosition to the given value.
|
||||
/// Also stores the ScrollRect as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Tweener DOVerticalNormalizedPos(this ScrollRect target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
return DOTween.To(() => target.verticalNormalizedPosition, x => target.verticalNormalizedPosition = x, endValue, duration)
|
||||
.SetOptions(snapping).SetTarget(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Slider
|
||||
|
||||
/// <summary>Tweens a Slider's value to the given value.
|
||||
/// Also stores the Slider as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DOValue(this Slider target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t = DOTween.To(() => target.value, x => target.value = x, endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Text
|
||||
|
||||
/// <summary>Tweens a Text's color to the given value.
|
||||
/// Also stores the Text as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOColor(this Text target, Color endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.To(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tweens a Text's text from one integer to another, with options for thousands separators
|
||||
/// </summary>
|
||||
/// <param name="fromValue">The value to start from</param>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="addThousandsSeparator">If TRUE (default) also adds thousands separators</param>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> to use (InvariantCulture if NULL)</param>
|
||||
public static TweenerCore<int, int, NoOptions> DOCounter(
|
||||
this Text target, int fromValue, int endValue, float duration, bool addThousandsSeparator = true, CultureInfo culture = null
|
||||
){
|
||||
int v = fromValue;
|
||||
CultureInfo cInfo = !addThousandsSeparator ? null : culture ?? CultureInfo.InvariantCulture;
|
||||
TweenerCore<int, int, NoOptions> t = DOTween.To(() => v, x => {
|
||||
v = x;
|
||||
target.text = addThousandsSeparator
|
||||
? v.ToString("N0", cInfo)
|
||||
: v.ToString();
|
||||
}, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Text's alpha color to the given value.
|
||||
/// Also stores the Text as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Color, Color, ColorOptions> DOFade(this Text target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Color, Color, ColorOptions> t = DOTween.ToAlpha(() => target.color, x => target.color = x, endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Text's text to the given value.
|
||||
/// Also stores the Text as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end string to tween to</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="richTextEnabled">If TRUE (default), rich text will be interpreted correctly while animated,
|
||||
/// otherwise all tags will be considered as normal text</param>
|
||||
/// <param name="scrambleMode">The type of scramble mode to use, if any</param>
|
||||
/// <param name="scrambleChars">A string containing the characters to use for scrambling.
|
||||
/// Use as many characters as possible (minimum 10) because DOTween uses a fast scramble mode which gives better results with more characters.
|
||||
/// Leave it to NULL (default) to use default ones</param>
|
||||
public static TweenerCore<string, string, StringOptions> DOText(this Text target, string endValue, float duration, bool richTextEnabled = true, ScrambleMode scrambleMode = ScrambleMode.None, string scrambleChars = null)
|
||||
{
|
||||
if (endValue == null) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogWarning("You can't pass a NULL string to DOText: an empty string will be used instead to avoid errors");
|
||||
endValue = "";
|
||||
}
|
||||
TweenerCore<string, string, StringOptions> t = DOTween.To(() => target.text, x => target.text = x, endValue, duration);
|
||||
t.SetOptions(richTextEnabled, scrambleMode, scrambleChars)
|
||||
.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Blendables
|
||||
|
||||
#region Graphic
|
||||
|
||||
/// <summary>Tweens a Graphic's color to the given value,
|
||||
/// in a way that allows other DOBlendableColor tweens to work together on the same target,
|
||||
/// instead than fight each other as multiple DOColor would do.
|
||||
/// Also stores the Graphic as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The value to tween to</param><param name="duration">The duration of the tween</param>
|
||||
public static Tweener DOBlendableColor(this Graphic target, Color endValue, float duration)
|
||||
{
|
||||
endValue = endValue - target.color;
|
||||
Color to = new Color(0, 0, 0, 0);
|
||||
return DOTween.To(() => to, x => {
|
||||
Color diff = x - to;
|
||||
to = x;
|
||||
target.color += diff;
|
||||
}, endValue, duration)
|
||||
.Blendable().SetTarget(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image
|
||||
|
||||
/// <summary>Tweens a Image's color to the given value,
|
||||
/// in a way that allows other DOBlendableColor tweens to work together on the same target,
|
||||
/// instead than fight each other as multiple DOColor would do.
|
||||
/// Also stores the Image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The value to tween to</param><param name="duration">The duration of the tween</param>
|
||||
public static Tweener DOBlendableColor(this Image target, Color endValue, float duration)
|
||||
{
|
||||
endValue = endValue - target.color;
|
||||
Color to = new Color(0, 0, 0, 0);
|
||||
return DOTween.To(() => to, x => {
|
||||
Color diff = x - to;
|
||||
to = x;
|
||||
target.color += diff;
|
||||
}, endValue, duration)
|
||||
.Blendable().SetTarget(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Text
|
||||
|
||||
/// <summary>Tweens a Text's color BY the given value,
|
||||
/// in a way that allows other DOBlendableColor tweens to work together on the same target,
|
||||
/// instead than fight each other as multiple DOColor would do.
|
||||
/// Also stores the Text as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The value to tween to</param><param name="duration">The duration of the tween</param>
|
||||
public static Tweener DOBlendableColor(this Text target, Color endValue, float duration)
|
||||
{
|
||||
endValue = endValue - target.color;
|
||||
Color to = new Color(0, 0, 0, 0);
|
||||
return DOTween.To(() => to, x => {
|
||||
Color diff = x - to;
|
||||
to = x;
|
||||
target.color += diff;
|
||||
}, endValue, duration)
|
||||
.Blendable().SetTarget(target);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Shapes
|
||||
|
||||
/// <summary>Tweens a RectTransform's anchoredPosition so that it draws a circle around the given center.
|
||||
/// Also stores the RectTransform as the tween's target so it can be used for filtered operations.<para/>
|
||||
/// IMPORTANT: SetFrom(value) requires a <see cref="Vector2"/> instead of a float, where the X property represents the "from degrees value"</summary>
|
||||
/// <param name="center">Circle-center/pivot around which to rotate (in UI anchoredPosition coordinates)</param>
|
||||
/// <param name="endValueDegrees">The end value degrees to reach (to rotate counter-clockwise pass a negative value)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="relativeCenter">If TRUE the <see cref="center"/> coordinates will be considered as relative to the target's current anchoredPosition</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, CircleOptions> DOShapeCircle(
|
||||
this RectTransform target, Vector2 center, float endValueDegrees, float duration, bool relativeCenter = false, bool snapping = false
|
||||
)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, CircleOptions> t = DOTween.To(
|
||||
CirclePlugin.Get(), () => target.anchoredPosition, x => target.anchoredPosition = x, center, duration
|
||||
);
|
||||
t.SetOptions(endValueDegrees, relativeCenter, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
|
||||
public static class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the anchoredPosition of the first RectTransform to the second RectTransform,
|
||||
/// taking into consideration offset, anchors and pivot, and returns the new anchoredPosition
|
||||
/// </summary>
|
||||
public static Vector2 SwitchToRectTransform(RectTransform from, RectTransform to)
|
||||
{
|
||||
Vector2 localPoint;
|
||||
Vector2 fromPivotDerivedOffset = new Vector2(from.rect.width * 0.5f + from.rect.xMin, from.rect.height * 0.5f + from.rect.yMin);
|
||||
Vector2 screenP = RectTransformUtility.WorldToScreenPoint(null, from.position);
|
||||
screenP += fromPivotDerivedOffset;
|
||||
RectTransformUtility.ScreenPointToLocalPointInRectangle(to, screenP, null, out localPoint);
|
||||
Vector2 pivotDerivedOffset = new Vector2(to.rect.width * 0.5f + to.rect.xMin, to.rect.height * 0.5f + to.rect.yMin);
|
||||
return to.anchoredPosition + localPoint - pivotDerivedOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a060394c03331a64392db53a10e7f2d1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,161 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2026/01/08
|
||||
|
||||
#if DOTWEEN_UITOOLKIT && UNITY_2021_3_OR_NEWER // MODULE_MARKER
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Core.Enums;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
public static class DOTweenModuleUIToolkit
|
||||
{
|
||||
#region Shortcuts
|
||||
|
||||
#region VisualElement
|
||||
|
||||
/// <summary>Tweens a VisualElement's position (via style.translate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMove(this VisualElement target, Vector3 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t
|
||||
= DOTween.To(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a VisualElement's position (via style.translate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOMove(this VisualElement target, Vector2 endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t
|
||||
= DOTween.To(() => (Vector2)target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, 0), endValue, duration);
|
||||
t.SetOptions(snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a VisualElement's X position (via style.translate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveX(this VisualElement target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t
|
||||
= DOTween.To(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), new Vector3(endValue, 0, 0), duration);
|
||||
t.SetOptions(AxisConstraint.X, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a VisualElement's Y position (via style.translate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveY(this VisualElement target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t
|
||||
= DOTween.To(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), new Vector3(0, endValue, 0), duration);
|
||||
t.SetOptions(AxisConstraint.Y, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a VisualElement's Z position (via style.translate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static TweenerCore<Vector3, Vector3, VectorOptions> DOMoveZ(this VisualElement target, float endValue, float duration, bool snapping = false)
|
||||
{
|
||||
TweenerCore<Vector3, Vector3, VectorOptions> t
|
||||
= DOTween.To(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), new Vector3(0, 0, endValue), duration);
|
||||
t.SetOptions(AxisConstraint.Z, snapping).SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a VisualElement's scale (via style.scale) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOScale(this VisualElement target, Vector2 endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t
|
||||
= DOTween.To(() => (Vector2)target.resolvedStyle.scale.value, x => target.style.scale = new Scale(x), endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
/// <summary>Tweens a VisualElement's scale (via style.scale) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOScale(this VisualElement target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t
|
||||
= DOTween.To(() => (Vector2)target.resolvedStyle.scale.value, x => target.style.scale = new Scale(x), new Vector2(endValue, endValue), duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a VisualElement's rotation (via style.rotate) to the given value.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param><param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<float, float, FloatOptions> DORotate(this VisualElement target, float endValue, float duration)
|
||||
{
|
||||
TweenerCore<float, float, FloatOptions> t
|
||||
= DOTween.To(() => target.resolvedStyle.rotate.angle.value, x => target.style.rotate = new Rotate(x), endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Punches a VisualElement's position towards the given direction and then back to the starting one
|
||||
/// as if it was connected to the starting position via an elastic.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="punch">The direction and strength of the punch (added to the VisualElement's current position)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="vibrato">Indicates how much will the punch vibrate</param>
|
||||
/// <param name="elasticity">Represents how much (0 to 1) the vector will go beyond the starting position when bouncing backwards.
|
||||
/// 1 creates a full oscillation between the punch direction and the opposite direction,
|
||||
/// while 0 oscillates only between the punch and the start position</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
public static Tweener DOPunch(this VisualElement target, Vector3 punch, float duration, int vibrato = 10, float elasticity = 1, bool snapping = false)
|
||||
{
|
||||
return DOTween.Punch(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), punch, duration, vibrato, elasticity)
|
||||
.SetTarget(target).SetOptions(snapping);
|
||||
}
|
||||
|
||||
/// <summary>Shakes a VisualElement's position with the given values.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="strength">The shake strength</param>
|
||||
/// <param name="vibrato">Indicates how much will the shake vibrate</param>
|
||||
/// <param name="randomness">Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware).
|
||||
/// Setting it to 0 will shake along a single direction.</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
/// <param name="fadeOut">If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not</param>
|
||||
/// <param name="randomnessMode">Randomness mode</param>
|
||||
public static Tweener DOShake(this VisualElement target, float duration, float strength = 100, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true, ShakeRandomnessMode randomnessMode = ShakeRandomnessMode.Full)
|
||||
{
|
||||
return DOTween.Shake(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), duration, strength, vibrato, randomness, true, fadeOut, randomnessMode)
|
||||
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping);
|
||||
}
|
||||
/// <summary>Shakes a VisualElement's position with the given values.
|
||||
/// Also stores the VisualElement as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
/// <param name="strength">The shake strength on each axis</param>
|
||||
/// <param name="vibrato">Indicates how much will the shake vibrate</param>
|
||||
/// <param name="randomness">Indicates how much the shake will be random (0 to 180 - values higher than 90 kind of suck, so beware).
|
||||
/// Setting it to 0 will shake along a single direction.</param>
|
||||
/// <param name="snapping">If TRUE the tween will smoothly snap all values to integers</param>
|
||||
/// <param name="fadeOut">If TRUE the shake will automatically fadeOut smoothly within the tween's duration, otherwise it will not</param>
|
||||
/// <param name="randomnessMode">Randomness mode</param>
|
||||
public static Tweener DOShake(this VisualElement target, float duration, Vector2 strength, int vibrato = 10, float randomness = 90, bool snapping = false, bool fadeOut = true, ShakeRandomnessMode randomnessMode = ShakeRandomnessMode.Full)
|
||||
{
|
||||
return DOTween.Shake(() => target.resolvedStyle.translate, x => target.style.translate = new Translate(x.x, x.y, x.z), duration, strength, vibrato, randomness, fadeOut, randomnessMode)
|
||||
.SetTarget(target).SetSpecialStartupMode(SpecialStartupMode.SetShake).SetOptions(snapping);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c0a6d2683fb84e4193f2aa968264881
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,389 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
//#if UNITY_2018_1_OR_NEWER && (NET_4_6 || NET_STANDARD_2_0)
|
||||
//using Task = System.Threading.Tasks.Task;
|
||||
//#endif
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
/// <summary>
|
||||
/// Shortcuts/functions that are not strictly related to specific Modules
|
||||
/// but are available only on some Unity versions
|
||||
/// </summary>
|
||||
public static class DOTweenModuleUnityVersion
|
||||
{
|
||||
#region Material
|
||||
|
||||
/// <summary>Tweens a Material's color using the given gradient
|
||||
/// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener).
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="gradient">The gradient to use</param><param name="duration">The duration of the tween</param>
|
||||
public static Sequence DOGradientColor(this Material target, Gradient gradient, float duration)
|
||||
{
|
||||
Sequence s = DOTween.Sequence();
|
||||
GradientColorKey[] colors = gradient.colorKeys;
|
||||
int len = colors.Length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
GradientColorKey c = colors[i];
|
||||
if (i == 0 && c.time <= 0) {
|
||||
target.color = c.color;
|
||||
continue;
|
||||
}
|
||||
float colorDuration = i == len - 1
|
||||
? duration - s.Duration(false) // Verifies that total duration is correct
|
||||
: duration * (i == 0 ? c.time : c.time - colors[i - 1].time);
|
||||
s.Append(target.DOColor(c.color, colorDuration).SetEase(Ease.Linear));
|
||||
}
|
||||
s.SetTarget(target);
|
||||
return s;
|
||||
}
|
||||
/// <summary>Tweens a Material's named color property using the given gradient
|
||||
/// (NOTE 1: only uses the colors of the gradient, not the alphas - NOTE 2: creates a Sequence, not a Tweener).
|
||||
/// Also stores the image as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="gradient">The gradient to use</param>
|
||||
/// <param name="property">The name of the material property to tween (like _Tint or _SpecColor)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
public static Sequence DOGradientColor(this Material target, Gradient gradient, string property, float duration)
|
||||
{
|
||||
Sequence s = DOTween.Sequence();
|
||||
GradientColorKey[] colors = gradient.colorKeys;
|
||||
int len = colors.Length;
|
||||
for (int i = 0; i < len; ++i) {
|
||||
GradientColorKey c = colors[i];
|
||||
if (i == 0 && c.time <= 0) {
|
||||
target.SetColor(property, c.color);
|
||||
continue;
|
||||
}
|
||||
float colorDuration = i == len - 1
|
||||
? duration - s.Duration(false) // Verifies that total duration is correct
|
||||
: duration * (i == 0 ? c.time : c.time - colors[i - 1].time);
|
||||
s.Append(target.DOColor(c.color, property, colorDuration).SetEase(Ease.Linear));
|
||||
}
|
||||
s.SetTarget(target);
|
||||
return s;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CustomYieldInstructions
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed or complete.
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForCompletion(true);</code>
|
||||
/// </summary>
|
||||
public static CustomYieldInstruction WaitForCompletion(this Tween t, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForCompletion(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed or rewinded.
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForRewind();</code>
|
||||
/// </summary>
|
||||
public static CustomYieldInstruction WaitForRewind(this Tween t, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForRewind(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed.
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForKill();</code>
|
||||
/// </summary>
|
||||
public static CustomYieldInstruction WaitForKill(this Tween t, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForKill(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed or has gone through the given amount of loops.
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForElapsedLoops(2);</code>
|
||||
/// </summary>
|
||||
/// <param name="elapsedLoops">Elapsed loops to wait for</param>
|
||||
public static CustomYieldInstruction WaitForElapsedLoops(this Tween t, int elapsedLoops, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForElapsedLoops(t, elapsedLoops);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed
|
||||
/// or has reached the given time position (loops included, delays excluded).
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForPosition(2.5f);</code>
|
||||
/// </summary>
|
||||
/// <param name="position">Position (loops included, delays excluded) to wait for</param>
|
||||
public static CustomYieldInstruction WaitForPosition(this Tween t, float position, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForPosition(t, position);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="CustomYieldInstruction"/> that waits until the tween is killed or started
|
||||
/// (meaning when the tween is set in a playing state the first time, after any eventual delay).
|
||||
/// It can be used inside a coroutine as a yield.
|
||||
/// <para>Example usage:</para><code>yield return myTween.WaitForStart();</code>
|
||||
/// </summary>
|
||||
public static CustomYieldInstruction WaitForStart(this Tween t, bool returnCustomYieldInstruction)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return null;
|
||||
}
|
||||
return new DOTweenCYInstruction.WaitForStart(t);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
#region Unity 2018.1 or Newer
|
||||
|
||||
#region Material
|
||||
|
||||
/// <summary>Tweens a Material's named texture offset property with the given ID to the given value.
|
||||
/// Also stores the material as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="propertyID">The ID of the material property to tween (also called nameID in Unity's manual)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOOffset(this Material target, Vector2 endValue, int propertyID, float duration)
|
||||
{
|
||||
if (!target.HasProperty(propertyID)) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogMissingMaterialProperty(propertyID);
|
||||
return null;
|
||||
}
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.GetTextureOffset(propertyID), x => target.SetTextureOffset(propertyID, x), endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
/// <summary>Tweens a Material's named texture scale property with the given ID to the given value.
|
||||
/// Also stores the material as the tween's target so it can be used for filtered operations</summary>
|
||||
/// <param name="endValue">The end value to reach</param>
|
||||
/// <param name="propertyID">The ID of the material property to tween (also called nameID in Unity's manual)</param>
|
||||
/// <param name="duration">The duration of the tween</param>
|
||||
public static TweenerCore<Vector2, Vector2, VectorOptions> DOTiling(this Material target, Vector2 endValue, int propertyID, float duration)
|
||||
{
|
||||
if (!target.HasProperty(propertyID)) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogMissingMaterialProperty(propertyID);
|
||||
return null;
|
||||
}
|
||||
TweenerCore<Vector2, Vector2, VectorOptions> t = DOTween.To(() => target.GetTextureScale(propertyID), x => target.SetTextureScale(propertyID, x), endValue, duration);
|
||||
t.SetTarget(target);
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region .NET 4.6 or Newer
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER && (NET_4_6 || NET_STANDARD_2_0)
|
||||
|
||||
#region Async Instructions
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed or complete.
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.WaitForCompletion();</code>
|
||||
/// </summary>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForCompletion(this Tween t)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active && !t.IsComplete()) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed or rewinded.
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.AsyncWaitForRewind();</code>
|
||||
/// </summary>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForRewind(this Tween t)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active && (!t.playedOnce || t.position * (t.CompletedLoops() + 1) > 0)) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed.
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.AsyncWaitForKill();</code>
|
||||
/// </summary>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForKill(this Tween t)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed or has gone through the given amount of loops.
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.AsyncWaitForElapsedLoops();</code>
|
||||
/// </summary>
|
||||
/// <param name="elapsedLoops">Elapsed loops to wait for</param>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForElapsedLoops(this Tween t, int elapsedLoops)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active && t.CompletedLoops() < elapsedLoops) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed or started
|
||||
/// (meaning when the tween is set in a playing state the first time, after any eventual delay).
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.AsyncWaitForPosition();</code>
|
||||
/// </summary>
|
||||
/// <param name="position">Position (loops included, delays excluded) to wait for</param>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForPosition(this Tween t, float position)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active && t.position * (t.CompletedLoops() + 1) < position) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an async <see cref="System.Threading.Tasks.Task"/> that waits until the tween is killed.
|
||||
/// It can be used inside an async operation.
|
||||
/// <para>Example usage:</para><code>await myTween.AsyncWaitForKill();</code>
|
||||
/// </summary>
|
||||
public static async System.Threading.Tasks.Task AsyncWaitForStart(this Tween t)
|
||||
{
|
||||
if (!t.active) {
|
||||
if (Debugger.logPriority > 0) Debugger.LogInvalidTween(t);
|
||||
return;
|
||||
}
|
||||
while (t.active && !t.playedOnce) await System.Threading.Tasks.Task.Yield();
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
}
|
||||
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// ███ CLASSES █████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
|
||||
public static class DOTweenCYInstruction
|
||||
{
|
||||
public class WaitForCompletion : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active && !t.IsComplete();
|
||||
}}
|
||||
readonly Tween t;
|
||||
public WaitForCompletion(Tween tween)
|
||||
{
|
||||
t = tween;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitForRewind : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active && (!t.playedOnce || t.position * (t.CompletedLoops() + 1) > 0);
|
||||
}}
|
||||
readonly Tween t;
|
||||
public WaitForRewind(Tween tween)
|
||||
{
|
||||
t = tween;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitForKill : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active;
|
||||
}}
|
||||
readonly Tween t;
|
||||
public WaitForKill(Tween tween)
|
||||
{
|
||||
t = tween;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitForElapsedLoops : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active && t.CompletedLoops() < elapsedLoops;
|
||||
}}
|
||||
readonly Tween t;
|
||||
readonly int elapsedLoops;
|
||||
public WaitForElapsedLoops(Tween tween, int elapsedLoops)
|
||||
{
|
||||
t = tween;
|
||||
this.elapsedLoops = elapsedLoops;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitForPosition : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active && t.position * (t.CompletedLoops() + 1) < position;
|
||||
}}
|
||||
readonly Tween t;
|
||||
readonly float position;
|
||||
public WaitForPosition(Tween tween, float position)
|
||||
{
|
||||
t = tween;
|
||||
this.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
public class WaitForStart : CustomYieldInstruction
|
||||
{
|
||||
public override bool keepWaiting { get {
|
||||
return t.active && !t.playedOnce;
|
||||
}}
|
||||
readonly Tween t;
|
||||
public WaitForStart(Tween tween)
|
||||
{
|
||||
t = tween;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63c02322328255542995bd02b47b0457
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,167 @@
|
||||
// Author: Daniele Giardini - http://www.demigiant.com
|
||||
// Created: 2018/07/13
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using DG.Tweening.Core;
|
||||
using DG.Tweening.Plugins.Core.PathCore;
|
||||
using DG.Tweening.Plugins.Options;
|
||||
|
||||
#pragma warning disable 1591
|
||||
namespace DG.Tweening
|
||||
{
|
||||
/// <summary>
|
||||
/// Utility functions that deal with available Modules and rewrite them.
|
||||
/// Modules defines:
|
||||
/// - DOTAUDIO
|
||||
/// - DOTPHYSICS
|
||||
/// - DOTPHYSICS2D
|
||||
/// - DOTSPRITE
|
||||
/// - DOTUI
|
||||
/// Extra defines set and used for implementation of external assets:
|
||||
/// - DOTWEEN_TMP ► TextMesh Pro
|
||||
/// - DOTWEEN_TK2D ► 2D Toolkit
|
||||
/// </summary>
|
||||
public static class DOTweenModuleUtils
|
||||
{
|
||||
static bool _initialized;
|
||||
|
||||
#region Reflection
|
||||
|
||||
/// <summary>
|
||||
/// Called via Reflection by DOTweenComponent on Awake
|
||||
/// </summary>
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
#endif
|
||||
public static void Init()
|
||||
{
|
||||
if (_initialized) return;
|
||||
|
||||
_initialized = true;
|
||||
DOTweenExternalCommand.SetOrientationOnPath += Physics.SetOrientationOnPath;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1
|
||||
UnityEditor.EditorApplication.playmodeStateChanged += PlaymodeStateChanged;
|
||||
#else
|
||||
UnityEditor.EditorApplication.playModeStateChanged += PlaymodeStateChanged;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
#pragma warning disable
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
// Just used to preserve methods when building, never called
|
||||
static void Preserver()
|
||||
{
|
||||
Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
MethodInfo mi = typeof(MonoBehaviour).GetMethod("Stub");
|
||||
}
|
||||
#pragma warning restore
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Fires OnApplicationPause in DOTweenComponent even when Editor is paused (otherwise it's only fired at runtime)
|
||||
#if UNITY_4_3 || UNITY_4_4 || UNITY_4_5 || UNITY_4_6 || UNITY_5 || UNITY_2017_1
|
||||
static void PlaymodeStateChanged()
|
||||
#else
|
||||
static void PlaymodeStateChanged(UnityEditor.PlayModeStateChange state)
|
||||
#endif
|
||||
{
|
||||
if (DOTween.instance == null) return;
|
||||
DOTween.instance.OnApplicationPause(UnityEditor.EditorApplication.isPaused);
|
||||
}
|
||||
#endif
|
||||
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// ███ INTERNAL CLASSES ████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
// █████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
|
||||
|
||||
public static class Physics
|
||||
{
|
||||
// Called via DOTweenExternalCommand callback
|
||||
public static void SetOrientationOnPath(PathOptions options, Tween t, Quaternion newRot, Transform trans)
|
||||
{
|
||||
#if !DOTWEEN_NOPHYSICS // PHYSICS_MARKER
|
||||
if (options.isRigidbody) ((Rigidbody)t.target).rotation = newRot;
|
||||
else trans.rotation = newRot;
|
||||
#else
|
||||
trans.rotation = newRot;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns FALSE if the DOTween's Physics2D Module is disabled, or if there's no Rigidbody2D attached
|
||||
public static bool HasRigidbody2D(Component target)
|
||||
{
|
||||
#if !DOTWEEN_NOPHYSICS2D // PHYSICS2D_MARKER
|
||||
return target.GetComponent<Rigidbody2D>() != null;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#region Called via Reflection
|
||||
|
||||
|
||||
// Called via Reflection by DOTweenPathInspector
|
||||
// Returns FALSE if the DOTween's Physics Module is disabled, or if there's no rigidbody attached
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
#endif
|
||||
public static bool HasRigidbody(Component target)
|
||||
{
|
||||
#if !DOTWEEN_NOPHYSICS // PHYSICS_MARKER
|
||||
return target.GetComponent<Rigidbody>() != null;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Called via Reflection by DOTweenPath
|
||||
#if UNITY_2018_1_OR_NEWER
|
||||
[UnityEngine.Scripting.Preserve]
|
||||
#endif
|
||||
public static TweenerCore<Vector3, Path, PathOptions> CreateDOTweenPathTween(
|
||||
MonoBehaviour target, bool tweenRigidbody, bool isLocal, Path path, float duration, PathMode pathMode
|
||||
){
|
||||
TweenerCore<Vector3, Path, PathOptions> t = null;
|
||||
bool rBodyFoundAndTweened = false;
|
||||
#if !DOTWEEN_NOPHYSICS // PHYSICS_MARKER
|
||||
if (tweenRigidbody) {
|
||||
Rigidbody rBody = target.GetComponent<Rigidbody>();
|
||||
if (rBody != null) {
|
||||
rBodyFoundAndTweened = true;
|
||||
t = isLocal
|
||||
? rBody.DOLocalPath(path, duration, pathMode)
|
||||
: rBody.DOPath(path, duration, pathMode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if !DOTWEEN_NOPHYSICS2D // PHYSICS2D_MARKER
|
||||
if (!rBodyFoundAndTweened && tweenRigidbody) {
|
||||
Rigidbody2D rBody2D = target.GetComponent<Rigidbody2D>();
|
||||
if (rBody2D != null) {
|
||||
rBodyFoundAndTweened = true;
|
||||
t = isLocal
|
||||
? rBody2D.DOLocalPath(path, duration, pathMode)
|
||||
: rBody2D.DOPath(path, duration, pathMode);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!rBodyFoundAndTweened) {
|
||||
t = isLocal
|
||||
? target.transform.DOLocalPath(path, duration, pathMode)
|
||||
: target.transform.DOPath(path, duration, pathMode);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bcaf917d9cf5b84090421a5a2abe42e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0450fce0e45b5004c9f535129c35e6cb
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
public class ConstEventString
|
||||
{
|
||||
public const string SyncGameData_Rotate = "SyncGameData_Rotate";
|
||||
public const string SyncGameData_FireBullet = "SyncGameData_FireBullet";
|
||||
// SyncGameData_CreateFish 已废弃:鱼创建改由服务端 OnFishSpawn 事件下发
|
||||
public const string SyncGameData_ChangeTargetMonster = "SyncGameData_ChangeTargetMonster";
|
||||
public const string SyncGameData_RendromDieFish = "SyncGameData_RenderDieFish";
|
||||
public const string SyncGameData_TurretState = "SyncGameData_TurretState";
|
||||
public const string SyncGameData_ChangeTurret = "SyncGameData_ChangeTurret";
|
||||
public const string SyncGameData_FreezeFish = "SyncGameData_FreezeFish";
|
||||
public const string SyncGameData_ChangeCannonMultiple = "SyncGameData_ChangeCannonMultiple";
|
||||
public const string SyncGameData_ChangeWing = "SyncGameData_ChangeWing";
|
||||
/// <summary>战神切换帧同步(changeZhanShen):其他玩家装备/卸下战神,对应座位加载/清除战神模型</summary>
|
||||
public const string SyncGameData_ChangeZhanShen = "SyncGameData_ChangeZhanShen";
|
||||
/// <summary>表情包帧同步(biaoQing):某玩家发送表情(spine动画/文字),对应座位显示表情</summary>
|
||||
public const string SyncGameData_BiaoQing = "SyncGameData_BiaoQing";
|
||||
public const string SyncGameData_BotFireAngle = "SyncGameData_BotFireAngle";
|
||||
// SyncGameData_RequestSyncFish 已废弃:鱼同步改由服务端 OnFishSpawn(type=sync) 下发
|
||||
/// <summary>爆奖结束帧同步(baoJiangEnd):某玩家爆奖流程完成,其他客户端显示最终 BJEndUI 并加分</summary>
|
||||
public const string BaoJiangEnd = "BaoJiangEnd";
|
||||
/// <summary>钻头蟹/激光蟹释放帧同步(zuanTouRelease):击杀者点击(或超时)发射,所有客户端(含击杀者回广播)统一时刻发射钻头/激光</summary>
|
||||
public const string SyncGameData_ZuanTouRelease = "SyncGameData_ZuanTouRelease";
|
||||
/// <summary>加金币帧同步(addGold):刮刮卡等 HTTP 途径获得金币后广播,各客户端给对应座位加金币并刷新显示</summary>
|
||||
public const string SyncGameData_AddGold = "SyncGameData_AddGold";
|
||||
|
||||
// ================================================================
|
||||
// 服务端 → 客户端事件 (新协议)
|
||||
// ================================================================
|
||||
/// <summary>服务端出鱼事件(破坏性替代 createFish 帧同步)</summary>
|
||||
public const string OnFishSpawn = "OnFishSpawn";
|
||||
/// <summary>鱼列表刷新</summary>
|
||||
public const string OnFishList = "OnFishList";
|
||||
/// <summary>冰冻道具生效(40003),鱼存活时间延长 15 秒,客户端写死 15s 倒计时</summary>
|
||||
public const string FishFrozen = "FishFrozen";
|
||||
/// <summary>玩家挂机通知</summary>
|
||||
public const string PlayerAfkNotice = "PlayerAfkNotice";
|
||||
/// <summary>玩家取消挂机通知</summary>
|
||||
public const string PlayerCancelAfkNotice = "PlayerCancelAfkNotice";
|
||||
/// <summary>玩家信息同步(GetPlayerInfo 的新响应,含完整玩家数据)</summary>
|
||||
public const string OnPlayerInfo = "OnPlayerInfo";
|
||||
/// <summary>召唤卡召唤通知:某玩家使用召唤卡,服务端已创建召唤鱼(实际鱼由 OnFishSpawn 下发)</summary>
|
||||
public const string SummonCardFishNotice = "SummonCardFishNotice";
|
||||
/// <summary>全局击杀公告(真人击杀/机器人模拟)</summary>
|
||||
public const string KillNotice = "KillNotice";
|
||||
/// <summary>机器人退出房间</summary>
|
||||
public const string BotLeaveRoomNotice = "BotLeaveRoomNotice";
|
||||
/// <summary>房主断线,其他玩家可接受机器人控制权</summary>
|
||||
public const string HostDisconnect = "HostDisconnect";
|
||||
/// <summary>座位变更</summary>
|
||||
public const string OnSeatChange = "OnSeatChange";
|
||||
/// <summary>房主控制权移交</summary>
|
||||
public const string ChangeControllerUser = "ChangeControllerUser";
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a12b4d76c42f8d49b6af72e52653bb3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,89 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public interface IEventInfo{
|
||||
}
|
||||
|
||||
public class EventInfo<T>:IEventInfo
|
||||
{
|
||||
public UnityAction<T> actions;
|
||||
public EventInfo(UnityAction<T> action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
public class EventInfo : IEventInfo
|
||||
{
|
||||
public UnityAction actions;
|
||||
public EventInfo(UnityAction action)
|
||||
{
|
||||
actions += action;
|
||||
}
|
||||
}
|
||||
public class EventCenter : Singleton<EventCenter>
|
||||
{
|
||||
private Dictionary<string, IEventInfo> eventDic
|
||||
= new Dictionary<string, IEventInfo>();
|
||||
|
||||
public void AddEventListener<T>(string name,UnityAction<T> action)
|
||||
{
|
||||
if(eventDic.ContainsKey(name))
|
||||
{
|
||||
(eventDic[name] as EventInfo<T>).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventDic.Add(name, new EventInfo<T>(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEventListener(string name, UnityAction action)
|
||||
{
|
||||
if (eventDic.ContainsKey(name))
|
||||
{
|
||||
(eventDic[name] as EventInfo).actions += action;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventDic.Add(name, new EventInfo(action));
|
||||
}
|
||||
}
|
||||
|
||||
public void EventTrigger<T>(string name,T info)
|
||||
{
|
||||
if(eventDic.ContainsKey(name))
|
||||
{
|
||||
(eventDic[name] as EventInfo<T>).actions?.Invoke(info);
|
||||
}
|
||||
}
|
||||
public void EventTrigger(string name)
|
||||
{
|
||||
if (eventDic.ContainsKey(name))
|
||||
{
|
||||
(eventDic[name] as EventInfo).actions?.Invoke();
|
||||
}
|
||||
}
|
||||
public void RemoveEventListener<T>(string name, UnityAction<T> action)
|
||||
{
|
||||
if (eventDic.ContainsKey(name))
|
||||
{
|
||||
//移除这个委托
|
||||
(eventDic[name] as EventInfo<T>).actions -= action;
|
||||
}
|
||||
}
|
||||
public void RemoveEventListener(string name, UnityAction action)
|
||||
{
|
||||
if (eventDic.ContainsKey(name))
|
||||
{
|
||||
//移除这个委托
|
||||
(eventDic[name] as EventInfo).actions -= action;
|
||||
}
|
||||
}
|
||||
public void Clear()
|
||||
{
|
||||
eventDic.Clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae1cccb3b95b50f489c0aa9af1b41cb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c2f6fe8649ee1d4a92f5a5ab95d9f4a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,84 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class InputMgr : Singleton<InputMgr>
|
||||
{
|
||||
private bool isStart = false;
|
||||
public InputMgr()
|
||||
{
|
||||
MonoMgr.Instance.AddUpdateListener(MyUpdate);
|
||||
}
|
||||
public void StartOrEndCheck(bool isOpen)
|
||||
{
|
||||
isStart = isOpen;
|
||||
}
|
||||
private void MyUpdate()
|
||||
{
|
||||
if (!isStart)
|
||||
return;
|
||||
CheckKeyCode(KeyCode.J);
|
||||
CheckKeyCode(KeyCode.K);
|
||||
}
|
||||
private void CheckKeyCode(KeyCode key)
|
||||
{
|
||||
if(Input.GetKeyDown(key))
|
||||
{
|
||||
EventCenter.Instance.EventTrigger("KeyisDown", key);
|
||||
}
|
||||
if (Input.GetKeyUp(key))
|
||||
{
|
||||
EventCenter.Instance.EventTrigger("KeyisUp", key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region 用法
|
||||
//public class Inputtest : MonoBehaviour
|
||||
//{
|
||||
// void Start()
|
||||
// {
|
||||
// //开启输入检测
|
||||
// InputMgr.GetInstance().StartOrEndCheck(true);
|
||||
// //添加事件监听
|
||||
// EventCenter.GetInstance().AddEventListener<KeyCode>("KeyisDown", CheckInputDown);
|
||||
// EventCenter.GetInstance().AddEventListener<KeyCode>("KeyisUp", CheckInputUp);
|
||||
// }
|
||||
// private void CheckInputDown(KeyCode obj)
|
||||
// {
|
||||
// switch (obj)
|
||||
// {
|
||||
// case KeyCode.W:
|
||||
// Debug.Log("前进");
|
||||
// break;
|
||||
// case KeyCode.A:
|
||||
// break;
|
||||
// case KeyCode.S:
|
||||
// break;
|
||||
// case KeyCode.D:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// private void CheckInputUp(KeyCode obj)
|
||||
// {
|
||||
// switch (obj)
|
||||
// {
|
||||
// case KeyCode.W:
|
||||
// Debug.Log("不再前进");
|
||||
// break;
|
||||
// case KeyCode.A:
|
||||
// break;
|
||||
// case KeyCode.S:
|
||||
// break;
|
||||
// case KeyCode.D:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// private void OnDestroy()
|
||||
// {
|
||||
// EventCenter.GetInstance().RemoveEventListener<KeyCode>("KeyisDown", CheckInputDown);
|
||||
// EventCenter.GetInstance().RemoveEventListener<KeyCode>("KeyisUp", CheckInputUp);
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e2766e5e0166f242b79517926d95597
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d41394e5140f494fbf59c37a666ffbe
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Douyin.LiveOpenSDK
|
||||
{
|
||||
|
||||
|
||||
|
||||
public static class LogManager
|
||||
{
|
||||
private static string logPath = Path.Combine(Application.persistentDataPath, "GameLogs");
|
||||
private static int maxLogFiles = 7;
|
||||
private static LogLevel currentLogLevel = LogLevel.Verbose;
|
||||
|
||||
public enum LogLevel
|
||||
{
|
||||
Error = 0,
|
||||
Warning = 1,
|
||||
Info = 2,
|
||||
Verbose = 3
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void Initialize()
|
||||
{
|
||||
if (!Directory.Exists(logPath))
|
||||
{
|
||||
Directory.CreateDirectory(logPath);
|
||||
}
|
||||
CleanOldLogs();
|
||||
}
|
||||
|
||||
public static void Log(string message, LogLevel level = LogLevel.Info)
|
||||
{
|
||||
if (level > currentLogLevel) return;
|
||||
|
||||
string logFile = Path.Combine(logPath, $"{DateTime.Now:yyyy-MM-dd}.log");
|
||||
string logMessage = $"[{DateTime.Now:HH:mm:ss}] [{level}] {message}\n";
|
||||
|
||||
try
|
||||
{
|
||||
File.AppendAllText(logFile, logMessage);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Failed to write log: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CleanOldLogs()
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = new DirectoryInfo(logPath).GetFiles("*.log");
|
||||
if (files.Length > maxLogFiles)
|
||||
{
|
||||
Array.Sort(files, (a, b) => b.CreationTime.CompareTo(a.CreationTime));
|
||||
for (int i = maxLogFiles; i < files.Length; i++)
|
||||
{
|
||||
files[i].Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Failed to clean logs: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLogLevel(LogLevel level)
|
||||
{
|
||||
currentLogLevel = level;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21abda7a9f0e0fa4b8d7391e62a90bd4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39d079abfb60e4f4b9766473690fdc2f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class MonoController : MonoBehaviour
|
||||
{
|
||||
private event UnityAction updateEvent;
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
DontDestroyOnLoad(this.gameObject);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
if(updateEvent!=null)
|
||||
{
|
||||
updateEvent();
|
||||
}
|
||||
}
|
||||
|
||||
public void AddUpdateListener(UnityAction func)
|
||||
{
|
||||
updateEvent += func;
|
||||
}
|
||||
public void RemoveUpdateListener(UnityAction func)
|
||||
{
|
||||
updateEvent -= func;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f382d5951cb60254785d2d0c5e1a912e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Internal;
|
||||
|
||||
public class MonoMgr : Singleton<MonoMgr>
|
||||
{
|
||||
private MonoController controller;
|
||||
public MonoMgr()
|
||||
{
|
||||
GameObject obj = new GameObject("MonoController");
|
||||
controller = obj.AddComponent<MonoController>();
|
||||
}
|
||||
public void AddUpdateListener(UnityAction func)
|
||||
{
|
||||
controller.AddUpdateListener(func);
|
||||
}
|
||||
public void RemoveUpdateListener(UnityAction func)
|
||||
{
|
||||
controller.RemoveUpdateListener(func);
|
||||
}
|
||||
public Coroutine StartCoroutine(IEnumerator routine)
|
||||
{
|
||||
return controller.StartCoroutine(routine);
|
||||
}
|
||||
|
||||
public Coroutine StartCoroutine(string methodName,[DefaultValue("null")]object value)
|
||||
{
|
||||
return controller.StartCoroutine(methodName, value);
|
||||
}
|
||||
public Coroutine StartCoroutine(string methodName)
|
||||
{
|
||||
return controller.StartCoroutine(methodName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c28f170c2c1ab9e42a71fb2131d920e2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c7deb4e7874fad7478108786b33d426e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
|
||||
public class MusicMgr : Singleton<MusicMgr>
|
||||
{
|
||||
private AudioSource bkMusic = null;
|
||||
private float bkVaule = 1;
|
||||
private float soundVaule = 1;
|
||||
private GameObject soundObj = null;
|
||||
private List<AudioSource> soundList = new List<AudioSource>();
|
||||
|
||||
public MusicMgr()
|
||||
{
|
||||
MonoMgr.Instance.AddUpdateListener(MyUpdate);
|
||||
}
|
||||
|
||||
private void MyUpdate()
|
||||
{
|
||||
for(int i=soundList.Count-1;i>=0;i--)
|
||||
{
|
||||
if(soundList[i].isPlaying)
|
||||
{
|
||||
Object.Destroy(soundList[i]);
|
||||
soundList.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void PlayBKMusic(string name)
|
||||
{
|
||||
if(bkMusic==null)
|
||||
{
|
||||
GameObject obj = new GameObject("BKMusic");
|
||||
bkMusic = obj.AddComponent<AudioSource>();
|
||||
}
|
||||
ResMgr.Instance.LoadAsync<AudioClip>("Music/BackgrondMusic/" + name,
|
||||
(clip) =>
|
||||
{
|
||||
bkMusic.clip = clip;
|
||||
bkMusic.loop = true;
|
||||
bkMusic.volume = bkVaule;
|
||||
bkMusic.Play();
|
||||
});
|
||||
}
|
||||
|
||||
public void ChangeBKValue(float v)
|
||||
{
|
||||
bkVaule = v;
|
||||
if(bkMusic=null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bkMusic.volume = bkVaule;
|
||||
}
|
||||
|
||||
public void PauseBKMusic()
|
||||
{
|
||||
if (bkMusic = null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bkMusic.Pause();
|
||||
}
|
||||
public void StopBKMusic()
|
||||
{
|
||||
if (bkMusic = null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
bkMusic.Stop();
|
||||
}
|
||||
|
||||
public void PlaySound(string name,bool isLoop,UnityAction<AudioSource> callback=null)
|
||||
{
|
||||
if(soundObj==null)
|
||||
{
|
||||
soundObj = new GameObject();
|
||||
soundObj.name = "Sounds";
|
||||
}
|
||||
AudioSource source = soundObj.AddComponent<AudioSource>();
|
||||
ResMgr.Instance.LoadAsync<AudioClip>("Music/Sounds/" + name,
|
||||
(clip) =>
|
||||
{
|
||||
source.clip = clip;
|
||||
source.loop = isLoop;
|
||||
source.volume = soundVaule;
|
||||
source.Play();
|
||||
soundList.Add(source);
|
||||
if (callback != null)
|
||||
{
|
||||
callback(source);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void ChangeSoundValue(float value)
|
||||
{
|
||||
soundVaule = value;
|
||||
for(int i=0;i<soundList.Count;++i)
|
||||
{
|
||||
soundList[i].volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void StopSound(AudioSource source)
|
||||
{
|
||||
if(soundList.Contains(source))
|
||||
{
|
||||
soundList.Remove(source);
|
||||
source.Stop();
|
||||
Object.Destroy(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ea7711fd37c7d449bcd48c4c9bf1dda
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cb18cec2edfeb049b9c7ced2fbc6b10
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,202 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 子弹专用对象池 — 按 prefab.GetInstanceID() 分桶,与鱼的 Pool 完全隔离
|
||||
/// 用法:
|
||||
/// var go = BulletPool.Instance.Get(prefab, pos, rot, parent);
|
||||
/// BulletPool.Instance.Return(go); // 代替 Destroy(单个回收)
|
||||
/// BulletPool.Instance.ClearAll(); // 换炮台/切场景调用:销毁所有活跃子弹 + 清池
|
||||
/// prefabID 直接用 prefab.GetInstanceID()(Unity 内部 hash,全局唯一)
|
||||
/// 活跃子弹→prefabID 的映射用 Dictionary<instanceID, prefabID> 存储,不挂组件不改 name
|
||||
/// </summary>
|
||||
public class BulletPool : Singleton<BulletPool>
|
||||
{
|
||||
// prefab.GetInstanceID() → 该 prefab 的池
|
||||
private Dictionary<int, BulletPoolData> dic = new Dictionary<int, BulletPoolData>();
|
||||
|
||||
// 活跃子弹映射:子弹GameObject → prefab.GetInstanceID()
|
||||
// key 用 GameObject 本身(Unity 重载了 GetHashCode/Equals,按实例区分)
|
||||
// value 是 prefabID,回收时凭此找到对应池
|
||||
private Dictionary<GameObject, int> activeMap = new Dictionary<GameObject, int>();
|
||||
|
||||
// 每个池子的最大缓存数(超出直接 Destroy,防止内存膨胀)
|
||||
private const int MaxCachePerPrefab = 200;
|
||||
|
||||
// 池子根节点(隐藏在场景里)
|
||||
private GameObject poolRoot;
|
||||
|
||||
/// <summary>从池中取一个子弹(池空则 Instantiate)</summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation, Transform parent)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
|
||||
int prefabID = prefab.GetInstanceID();
|
||||
GameObject obj = null;
|
||||
|
||||
if (dic.TryGetValue(prefabID, out var data))
|
||||
{
|
||||
// ⭐ 循环跳过已销毁的坏对象(ClearAll 用 Destroy 延迟销毁,时序竞争中可能残留)
|
||||
while (data.poolList.Count > 0)
|
||||
{
|
||||
obj = data.GetObj();
|
||||
if (obj != null) break; // Unity 重载 ==,能识别已 Destroy 的假 null
|
||||
obj = null; // 坏对象丢弃,继续取下一个
|
||||
}
|
||||
}
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
// ⭐ 必须先 SetParent 再设 position:模仿 Instantiate(prefab, pos, rot, parent)
|
||||
obj.transform.SetParent(parent, false);
|
||||
obj.transform.position = position;
|
||||
obj.transform.rotation = rotation;
|
||||
obj.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = GameObject.Instantiate(prefab, position, rotation, parent);
|
||||
obj.SetActive(true);
|
||||
}
|
||||
|
||||
// 记录映射:子弹实例 → prefabID(回收时凭此找到对应池)
|
||||
activeMap[obj] = prefabID;
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>无 parent 重载</summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation)
|
||||
{
|
||||
return Get(prefab, position, rotation, null);
|
||||
}
|
||||
|
||||
/// <summary>回收子弹到池(超容量则 Destroy)</summary>
|
||||
public void Return(GameObject obj)
|
||||
{
|
||||
if (obj == null) return;
|
||||
|
||||
// 取不到映射 → 非 pool 对象 → 兜底 Destroy
|
||||
if (!activeMap.TryGetValue(obj, out int prefabID) || prefabID == 0)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
activeMap.Remove(obj);
|
||||
|
||||
if (!dic.TryGetValue(prefabID, out var data))
|
||||
dic[prefabID] = data = new BulletPoolData(EnsurePoolRoot().transform, prefabID);
|
||||
|
||||
if (data.poolList.Count >= MaxCachePerPrefab)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
// 重置子弹状态(若有 BullitMove 组件)
|
||||
var bm = obj.GetComponent<BullitMove>();
|
||||
if (bm != null) bm.ResetState();
|
||||
|
||||
data.PushObj(obj);
|
||||
}
|
||||
|
||||
/// <summary>预加载 N 个某 prefab 到池</summary>
|
||||
public void Preload(GameObject prefab, int count)
|
||||
{
|
||||
if (prefab == null || count <= 0) return;
|
||||
int prefabID = prefab.GetInstanceID();
|
||||
|
||||
if (!dic.TryGetValue(prefabID, out var data))
|
||||
dic[prefabID] = data = new BulletPoolData(EnsurePoolRoot().transform, prefabID);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var obj = GameObject.Instantiate(prefab, EnsurePoolRoot().transform);
|
||||
// 预加载的对象直接入池,不进 activeMap(它们没被"借出")
|
||||
data.PushObj(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>销毁所有活跃子弹 + 清空所有池(换炮台/切场景调用)</summary>
|
||||
public void ClearAll()
|
||||
{
|
||||
// 销毁所有借出未归还的子弹
|
||||
foreach (var kv in activeMap.Keys)
|
||||
{
|
||||
if (kv != null) GameObject.Destroy(kv);
|
||||
}
|
||||
activeMap.Clear();
|
||||
|
||||
// 清空所有池
|
||||
foreach (var kv in dic.Values)
|
||||
kv.Clear();
|
||||
dic.Clear();
|
||||
|
||||
if (poolRoot != null)
|
||||
{
|
||||
GameObject.Destroy(poolRoot);
|
||||
poolRoot = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>只销毁活跃子弹,保留池缓存(换炮台时调用:清屏但池能复用)</summary>
|
||||
public void ClearActive()
|
||||
{
|
||||
foreach (var kv in activeMap.Keys)
|
||||
{
|
||||
if (kv != null) GameObject.Destroy(kv);
|
||||
}
|
||||
activeMap.Clear();
|
||||
// ⭐ 不清 dic,池里的缓存保留,同 prefab 下次能复用
|
||||
}
|
||||
|
||||
private GameObject EnsurePoolRoot()
|
||||
{
|
||||
if (poolRoot == null)
|
||||
{
|
||||
poolRoot = new GameObject("[BulletPool]");
|
||||
poolRoot.SetActive(false); // 池根节点隐藏,池内对象跟随隐藏
|
||||
}
|
||||
return poolRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>单个 prefab 的子弹池数据</summary>
|
||||
public class BulletPoolData
|
||||
{
|
||||
public Transform fatherObj;
|
||||
public List<GameObject> poolList;
|
||||
|
||||
public BulletPoolData(Transform root, int id)
|
||||
{
|
||||
fatherObj = new GameObject("bulletPool_" + id).transform;
|
||||
fatherObj.SetParent(root, false);
|
||||
poolList = new List<GameObject>();
|
||||
}
|
||||
|
||||
public void PushObj(GameObject obj)
|
||||
{
|
||||
if (obj == null) return;
|
||||
poolList.Add(obj);
|
||||
obj.transform.SetParent(fatherObj, false);
|
||||
obj.SetActive(false);
|
||||
}
|
||||
|
||||
public GameObject GetObj()
|
||||
{
|
||||
GameObject obj = poolList[poolList.Count - 1];
|
||||
poolList.RemoveAt(poolList.Count - 1);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var obj in poolList)
|
||||
{
|
||||
if (obj != null) GameObject.Destroy(obj);
|
||||
}
|
||||
poolList.Clear();
|
||||
|
||||
if (fatherObj != null)
|
||||
GameObject.Destroy(fatherObj.gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b450d462c4ecd3349b396f1ff2014f40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,217 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
/// <summary>
|
||||
/// 特效专用对象池 — 按 prefab.GetInstanceID() 分桶
|
||||
/// 粒子播放完自动回池(通过 EffectAutoReturn 组件检测)
|
||||
/// 用法:
|
||||
/// var go = EffectPool.Instance.Get(prefab, pos, rot, parent);
|
||||
/// // 无需手动回收,EffectAutoReturn 会在粒子播完后自动回池
|
||||
/// EffectPool.Instance.ClearAll(); // 切场景时彻底清理
|
||||
/// </summary>
|
||||
public class EffectPool : Singleton<EffectPool>
|
||||
{
|
||||
// prefab.GetInstanceID() → 该 prefab 的池
|
||||
private Dictionary<int, BulletPoolData> dic = new Dictionary<int, BulletPoolData>();
|
||||
|
||||
// 活跃特效映射:特效GameObject → prefab.GetInstanceID()
|
||||
private Dictionary<GameObject, int> activeMap = new Dictionary<GameObject, int>();
|
||||
|
||||
private const int MaxCachePerPrefab = 100;
|
||||
|
||||
private GameObject poolRoot;
|
||||
|
||||
/// <summary>从池中取一个特效(池空则 Instantiate),取出后自动播放并在播完时回池</summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation, Transform parent)
|
||||
{
|
||||
return Get(prefab, position, rotation, parent, autoReturn: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从池中取一个特效。
|
||||
/// autoReturn=true: 粒子特效,EffectAutoReturn 检测粒子播完自动回池
|
||||
/// autoReturn=false: 动画/UI 驱动特效(如 BJBase/DieEffect_TSY),由动画事件手动调用 Return()
|
||||
/// </summary>
|
||||
public GameObject Get(GameObject prefab, Vector3 position, Quaternion rotation, Transform parent, bool autoReturn)
|
||||
{
|
||||
return GetCore(prefab, position, rotation, parent, autoReturn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从池中取一个特效,不设置位置/旋转——位置、大小完全保留预制体里配置好的
|
||||
/// (爆奖特效用,z 也用预制体自带的,不被生成位置带偏)。
|
||||
/// </summary>
|
||||
public GameObject Get(GameObject prefab, Transform parent, bool autoReturn)
|
||||
{
|
||||
return GetCore(prefab, null, null, parent, autoReturn);
|
||||
}
|
||||
|
||||
/// <summary>取用核心:position/rotation 传 null 时不设置,保留预制体配置好的变换</summary>
|
||||
private GameObject GetCore(GameObject prefab, Vector3? position, Quaternion? rotation, Transform parent, bool autoReturn)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
|
||||
int prefabID = prefab.GetInstanceID();
|
||||
GameObject obj = null;
|
||||
|
||||
if (dic.TryGetValue(prefabID, out var data))
|
||||
{
|
||||
// 循环跳过已销毁的坏对象
|
||||
while (data.poolList.Count > 0)
|
||||
{
|
||||
obj = data.GetObj();
|
||||
if (obj != null) break;
|
||||
obj = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj != null)
|
||||
{
|
||||
obj.transform.SetParent(parent, false);
|
||||
// ⭐ 只在传入时才设置位置/旋转;不传则保留预制体配置好的位置和大小
|
||||
if (position.HasValue) obj.transform.position = position.Value;
|
||||
if (rotation.HasValue) obj.transform.rotation = rotation.Value;
|
||||
obj.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = position.HasValue
|
||||
? GameObject.Instantiate(prefab, position.Value, rotation ?? Quaternion.identity, parent)
|
||||
: GameObject.Instantiate(prefab, parent);
|
||||
obj.SetActive(true);
|
||||
}
|
||||
|
||||
activeMap[obj] = prefabID;
|
||||
|
||||
if (autoReturn)
|
||||
{
|
||||
// 粒子特效:挂上自动回收组件(已挂则复用)
|
||||
var auto = obj.GetComponent<EffectAutoReturn>();
|
||||
if (auto == null)
|
||||
auto = obj.AddComponent<EffectAutoReturn>();
|
||||
auto.prefabID = prefabID;
|
||||
auto.Play();
|
||||
}
|
||||
// autoReturn=false: 动画/UI 驱动特效,不挂自动回收组件
|
||||
// 由动画事件(coinEvent/ScoreNumScrollEvent 等)调用 EffectPool.Instance.Return(gameObject) 回池
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>回收特效到池(通常由 EffectAutoReturn 自动调用)</summary>
|
||||
public void Return(GameObject obj)
|
||||
{
|
||||
if (obj == null) return;
|
||||
|
||||
if (!activeMap.TryGetValue(obj, out int prefabID) || prefabID == 0)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
activeMap.Remove(obj);
|
||||
|
||||
if (!dic.TryGetValue(prefabID, out var data))
|
||||
dic[prefabID] = data = new BulletPoolData(EnsurePoolRoot().transform, prefabID);
|
||||
|
||||
if (data.poolList.Count >= MaxCachePerPrefab)
|
||||
{
|
||||
GameObject.Destroy(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
data.PushObj(obj);
|
||||
}
|
||||
|
||||
/// <summary>销毁所有活跃特效 + 清空所有池(切场景调用)</summary>
|
||||
public void ClearAll()
|
||||
{
|
||||
foreach (var kv in activeMap.Keys)
|
||||
{
|
||||
if (kv != null) GameObject.Destroy(kv);
|
||||
}
|
||||
activeMap.Clear();
|
||||
|
||||
foreach (var kv in dic.Values)
|
||||
kv.Clear();
|
||||
dic.Clear();
|
||||
|
||||
if (poolRoot != null)
|
||||
{
|
||||
GameObject.Destroy(poolRoot);
|
||||
poolRoot = null;
|
||||
}
|
||||
}
|
||||
|
||||
private GameObject EnsurePoolRoot()
|
||||
{
|
||||
if (poolRoot == null)
|
||||
{
|
||||
poolRoot = new GameObject("[EffectPool]");
|
||||
poolRoot.SetActive(false);
|
||||
}
|
||||
return poolRoot;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>挂在池内特效上,粒子播放完自动回池</summary>
|
||||
public class EffectAutoReturn : MonoBehaviour
|
||||
{
|
||||
[HideInInspector] public int prefabID;
|
||||
|
||||
private ParticleSystem[] particles;
|
||||
private float checkTimer;
|
||||
private const float MinPlayTime = 0.3f; // 至少播 0.3s 再检测,避免第一帧 IsAlive=false 误判
|
||||
private const float MaxLifetime = 6f; // ⭐ 兜底:超过 6 秒强制回池,防止 looping 残留导致特效永生
|
||||
|
||||
/// <summary>重新播放所有粒子</summary>
|
||||
public void Play()
|
||||
{
|
||||
if (particles == null || particles.Length == 0)
|
||||
particles = GetComponentsInChildren<ParticleSystem>(true);
|
||||
|
||||
checkTimer = 0f;
|
||||
foreach (var p in particles)
|
||||
{
|
||||
if (p != null)
|
||||
{
|
||||
// ⭐ 强制关闭 looping:有些预制体子级 ParticleSystem 设了 looping=1,
|
||||
// 会导致 IsAlive(true) 永远返回 true,特效一直累加直至内存爆满死机
|
||||
var main = p.main;
|
||||
main.loop = false;
|
||||
|
||||
p.Clear(true);
|
||||
p.Play(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
checkTimer += Time.deltaTime;
|
||||
if (checkTimer < MinPlayTime) return;
|
||||
|
||||
// ⭐ 6 秒兜底:无论是否还存活,超过 6 秒强制回池
|
||||
if (checkTimer >= MaxLifetime)
|
||||
{
|
||||
EffectPool.Instance.Return(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
// 所有粒子都播完 → 回池
|
||||
if (particles == null || particles.Length == 0)
|
||||
{
|
||||
EffectPool.Instance.Return(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
bool anyAlive = false;
|
||||
foreach (var p in particles)
|
||||
{
|
||||
if (p != null && p.IsAlive(true)) { anyAlive = true; break; }
|
||||
}
|
||||
if (!anyAlive)
|
||||
{
|
||||
EffectPool.Instance.Return(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e095098a1433eb4408b49fa20449bcb3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,176 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
public class PoolData
|
||||
{
|
||||
public GameObject fatherObj;
|
||||
public List<GameObject> poolList;
|
||||
public PoolData(GameObject obj,GameObject poolParent,int id)
|
||||
{
|
||||
fatherObj = new GameObject(obj.name);
|
||||
fatherObj.transform.parent = poolParent.transform;
|
||||
poolList = new List<GameObject>();
|
||||
PushObj(obj,id);
|
||||
}
|
||||
|
||||
public void PushObj(GameObject obj,int id)
|
||||
{
|
||||
// 先实例化,再隐藏(原代码对 prefab 调 SetActive(false) 无效且语义混乱)
|
||||
obj = GameObject.Instantiate(obj);
|
||||
obj.name = id.ToString();
|
||||
obj.transform.parent = fatherObj.transform;
|
||||
obj.SetActive(false);
|
||||
poolList.Add(obj);
|
||||
}
|
||||
public void PushObj(GameObject obj)
|
||||
{
|
||||
poolList.Add(obj);
|
||||
obj.transform.parent = fatherObj.transform;
|
||||
obj.SetActive(false);
|
||||
}
|
||||
public GameObject GetObj()
|
||||
{
|
||||
GameObject obj;
|
||||
obj = poolList[0];
|
||||
poolList.RemoveAt(0);
|
||||
obj.SetActive(true);
|
||||
obj.transform.parent = null;
|
||||
return obj;
|
||||
}
|
||||
/// <summary>
|
||||
/// 清理当前池子,销毁所有对象并释放父节点
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var obj in poolList)
|
||||
{
|
||||
if (obj != null)
|
||||
GameObject.Destroy(obj);
|
||||
}
|
||||
poolList.Clear();
|
||||
|
||||
if (fatherObj != null)
|
||||
GameObject.Destroy(fatherObj);
|
||||
}
|
||||
}
|
||||
|
||||
public class Pool : Singleton<Pool>
|
||||
{
|
||||
public Dictionary<int, PoolData> dic = new Dictionary<int, PoolData>();//生成一个字典
|
||||
private GameObject poolObj;//Scene窗口中的“pool”总收纳盒
|
||||
|
||||
/// <summary>获取/创建池总父节点(初始化和 Return 共用同一个 poolObj)</summary>
|
||||
public GameObject EnsurePoolRoot()
|
||||
{
|
||||
if (poolObj == null)
|
||||
poolObj = new GameObject("pool");
|
||||
return poolObj;
|
||||
}
|
||||
|
||||
public GameObject Get(int id, Vector3 position, Quaternion rotation)//返回一个预制体,
|
||||
{
|
||||
GameObject obj;
|
||||
if (dic.ContainsKey(id) && dic[id].poolList.Count > 0)//如果字典里有这个东西,并且它的数量大于0就取出来
|
||||
{
|
||||
obj = dic[id].GetObj();
|
||||
obj.transform.position = position;//实例化时候的参数传过来
|
||||
obj.transform.rotation = rotation;//同上
|
||||
}
|
||||
else
|
||||
{
|
||||
GameObject temp = FishResourcesData.GetFishPrefab(id);
|
||||
//if (rotation == Quaternion.identity)
|
||||
//{
|
||||
// rotation = temp.transform.rotation;
|
||||
//}
|
||||
obj = Object.Instantiate(temp, position, rotation) as GameObject;//没有就读取一个,不用存入字典
|
||||
obj.name = id.ToString();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
public GameObject Get(int id, Vector3 position, Quaternion rotation, Transform parent )//返回一个预制体,
|
||||
{
|
||||
GameObject obj;
|
||||
if (dic.ContainsKey(id) && dic[id].poolList.Count > 0)//如果字典里有这个东西,并且它的数量大于0就取出来
|
||||
{
|
||||
obj = dic[id].GetObj();
|
||||
// ⭐ 设置位置不带 z 轴:z 用预制体自带的深度,不被生成位置(如 9999,9999,0)擦掉
|
||||
obj.transform.position = new Vector3(position.x, position.y, obj.transform.position.z);
|
||||
obj.transform.rotation = rotation;//同上
|
||||
obj.transform.SetParent(parent);
|
||||
}
|
||||
else
|
||||
{
|
||||
//GameObject temp = FishResourcesData.GetFishPrefab(id);
|
||||
//if (rotation == Quaternion.identity)
|
||||
//{
|
||||
// rotation = temp.transform.rotation;
|
||||
//}
|
||||
var prefab = FishResourcesData.GetFishPrefab(id);
|
||||
if (prefab == null)
|
||||
{
|
||||
Debug.LogError($"[Pool] 找不到鱼 prefab, fishNumber={id}");
|
||||
return null;
|
||||
}
|
||||
// ⭐ 无位置实例化(保留预制体自带的位置/深度),再只覆盖 x/y,z 用预制体自带的
|
||||
obj = Object.Instantiate(prefab, parent) as GameObject;//没有就读取一个,不用存入字典
|
||||
obj.transform.rotation = rotation;
|
||||
obj.transform.position = new Vector3(position.x, position.y, obj.transform.position.z);
|
||||
obj.SetActive(true);
|
||||
|
||||
obj.name = id.ToString();
|
||||
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
public GameObject Return(GameObject obj)//隐藏掉
|
||||
{
|
||||
if(obj.activeSelf)
|
||||
{
|
||||
// ⭐ 统一用 poolObj 作为池总父节点(初始化时也用 poolObj,保证 Clear 能统一销毁)
|
||||
if(poolObj==null)
|
||||
{
|
||||
poolObj = new GameObject("pool");
|
||||
}
|
||||
int id =int.Parse( obj.name);
|
||||
if (dic.ContainsKey(id))//如果找到了这个名字
|
||||
{
|
||||
dic[id].PushObj(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
//dic.Add(id, new PoolData(obj, poolObj) { });
|
||||
GameObject.Destroy(obj);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
//public void Clear()//切换场景时将所有缓存清除
|
||||
//{
|
||||
// dic.Clear();
|
||||
// poolObj = null;
|
||||
//}
|
||||
/// <summary>
|
||||
/// 清理所有池子,销毁对象并释放资源
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
// ⭐ 防重入:已经清空过直接返回
|
||||
if (dic.Count == 0 && poolObj == null) return;
|
||||
|
||||
foreach (var kv in dic.Values)
|
||||
{
|
||||
if (kv != null) kv.Clear();
|
||||
}
|
||||
dic.Clear();
|
||||
|
||||
if (poolObj != null)
|
||||
{
|
||||
GameObject.Destroy(poolObj);
|
||||
poolObj = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 680ca01afe29bb84481776c727d9886c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 583a80fd7e23470499d70f7440bcb14e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
|
||||
public class ResMgr : Singleton<ResMgr>
|
||||
{
|
||||
public T Load<T>(string name)where T:Object
|
||||
{
|
||||
T res = Resources.Load<T>(name);
|
||||
if (res is GameObject)
|
||||
return Object.Instantiate(res);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
public T Load<T>(string name,Vector3 position,Quaternion rotation) where T : Object
|
||||
{
|
||||
T res = Resources.Load<T>(name);
|
||||
if (res is GameObject)
|
||||
return Object.Instantiate(res, position, rotation);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
public void LoadAsync<T>(string name,UnityAction<T> callback)where T:Object
|
||||
{
|
||||
MonoMgr.Instance.StartCoroutine(ReallyLoadAsync(name,callback));
|
||||
}
|
||||
private IEnumerator ReallyLoadAsync<T>(string name,UnityAction<T> callback)where T:Object
|
||||
{
|
||||
ResourceRequest r = Resources.LoadAsync<T>(name);
|
||||
yield return r;
|
||||
if (r.asset is GameObject)
|
||||
{
|
||||
callback(Object.Instantiate(r.asset) as T);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(r.asset as T);
|
||||
}
|
||||
}
|
||||
#region 异步加载使用方法(得到加载物体并设定位置等)
|
||||
//需要注意的是,异步加载中,调用异步加载后,物体并没有被加载,需要等n帧才会被加载,所以我们不能直接返回物体,而是在方法中将物体传出去。
|
||||
//private void Update()
|
||||
//{
|
||||
// if (Input.GetMouseButtonDown(1))
|
||||
// {
|
||||
// ResMgr.Instance.LoadAsync<GameObject>("cube", DoSome);
|
||||
// }
|
||||
//}
|
||||
//private void DoSome(GameObject obj)
|
||||
//{
|
||||
// Debug.Log("调用了回调函数");
|
||||
//}
|
||||
////为了方便,我们还可以直接使用Lambda表达式来方便书写
|
||||
//private void Update()
|
||||
//{
|
||||
// if (Input.GetMouseButtonDown(1))
|
||||
// {
|
||||
// ResMgr.GetInstance().LoadAsync<GameObject>("cube", (obj) =>
|
||||
// {
|
||||
// Debug.Log("调用了回调函数");
|
||||
// });
|
||||
// }
|
||||
//}
|
||||
#endregion
|
||||
|
||||
|
||||
//Addressable
|
||||
public void AALoadAsync<T>(string name, UnityAction<T> callback) where T : Object
|
||||
{
|
||||
MonoMgr.Instance.StartCoroutine(AAReallyLoadAsync(name, callback));
|
||||
}
|
||||
private IEnumerator AAReallyLoadAsync<T>(string name, UnityAction<T> callback) where T : Object
|
||||
{
|
||||
AsyncOperationHandle async = Addressables.LoadAssetAsync<T>(name);
|
||||
yield return async;
|
||||
if (async.Result is GameObject)
|
||||
{
|
||||
callback(Object.Instantiate(async.Result as GameObject) as T);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(async.Result as T);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb81f807b0e79ff4a80b2972cdb0a1ba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2de5017dd0315fb4a844080a4dfa73f8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,25 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DontDestroyMgr : Singleton<DontDestroyMgr>
|
||||
{
|
||||
List<GameObject> dontDesObj = new List<GameObject>();
|
||||
public void DontDesOnLoad(GameObject obj)
|
||||
{
|
||||
if(!dontDesObj.Contains(obj))
|
||||
{
|
||||
Object.DontDestroyOnLoad(obj);
|
||||
dontDesObj.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach(GameObject obj in dontDesObj)
|
||||
{
|
||||
Object.DestroyImmediate(obj);
|
||||
}
|
||||
dontDesObj.Clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79fbb7224a32bfa4fa3620ce2ab28027
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.SceneManagement;
|
||||
public class SceneMgr : Singleton<SceneMgr>
|
||||
{
|
||||
public void LoadScene(string name,UnityAction func)
|
||||
{
|
||||
SceneManager.LoadScene(name);
|
||||
func();
|
||||
}
|
||||
|
||||
public void LoadSceneAsync(string name,UnityAction func)
|
||||
{
|
||||
MonoMgr.Instance.StartCoroutine(ReallyLoadSceneAsync(name, func));
|
||||
}
|
||||
|
||||
private IEnumerator ReallyLoadSceneAsync(string name,UnityAction func)
|
||||
{
|
||||
AsyncOperation ao = SceneManager.LoadSceneAsync(name);
|
||||
while(!ao.isDone)
|
||||
{
|
||||
EventCenter.Instance.EventTrigger("Loading", ao.progress);
|
||||
yield return ao.progress;
|
||||
}
|
||||
func();
|
||||
}
|
||||
|
||||
public string GetActiveSceneName()
|
||||
{
|
||||
return SceneManager.GetActiveScene().name;
|
||||
}
|
||||
|
||||
public void AALoadSceneAsync(string name, UnityAction func)
|
||||
{
|
||||
|
||||
MonoMgr.Instance.StartCoroutine(AAReallyLoadSceneAsync(name + ".unity", func));
|
||||
}
|
||||
|
||||
private IEnumerator AAReallyLoadSceneAsync(string name, UnityAction func)
|
||||
{
|
||||
AsyncOperationHandle async = Addressables.LoadSceneAsync(name);
|
||||
while (!async.IsDone)
|
||||
{
|
||||
EventCenter.Instance.EventTrigger("Loading", async.PercentComplete);
|
||||
yield return async.PercentComplete;
|
||||
}
|
||||
func();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0ed3cda81921ae4e8f401c8bcb7afb7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58059954ae8931742a7c9a3813847f51
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee414068f48db7e4b9f9b39a5c04ee64
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "Game.Hotfix.Editor.StaticTool",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"Game.Hotfix",
|
||||
"CameraShake",
|
||||
"spine-unity",
|
||||
"Coffee.UIParticle",
|
||||
"Unity.Addressables",
|
||||
"Unity.ResourceManager",
|
||||
"Unity.TextMeshPro",
|
||||
"UnityEngine.UI",
|
||||
"Unity.InputSystem",
|
||||
"Unity.VisualScripting.Core"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb2d3645caea19c4e90cbf31b9c8afa0
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9acb66381f2e0ed408f0666b0c47df0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,82 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
/// This just exposes the Sorting Layer / Order in MeshRenderer since it's there
|
||||
/// but not displayed in the inspector. Getting MeshRenderer to render in front
|
||||
/// of a SpriteRenderer is pretty hard without this.
|
||||
[CustomEditor(typeof(MeshRenderer))]
|
||||
public class MeshRendererSortingEditor : Editor
|
||||
{
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
MeshRenderer renderer = target as MeshRenderer;
|
||||
|
||||
|
||||
var layers = SortingLayer.layers;
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int newId = DrawSortingLayersPopup(renderer.sortingLayerID);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
renderer.sortingLayerID = newId;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUI.BeginChangeCheck();
|
||||
int order = EditorGUILayout.IntField("Sorting Order", renderer.sortingOrder);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
renderer.sortingOrder = order;
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
}
|
||||
|
||||
int DrawSortingLayersPopup(int layerID)
|
||||
{
|
||||
var layers = SortingLayer.layers;
|
||||
var names = layers.Select(l => l.name).ToArray();
|
||||
if (!SortingLayer.IsValid(layerID))
|
||||
{
|
||||
layerID = layers[0].id;
|
||||
}
|
||||
var layerValue = SortingLayer.GetLayerValueFromID(layerID);
|
||||
var newLayerValue = EditorGUILayout.Popup("Sorting Layer", layerValue, names);
|
||||
return layers[newLayerValue].id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
//
|
||||
// Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
// distribute this software, either in source code form or as a compiled
|
||||
// binary, for any purpose, commercial or non-commercial, and by any
|
||||
// means.
|
||||
//
|
||||
// In jurisdictions that recognize copyright laws, the author or authors
|
||||
// of this software dedicate any and all copyright interest in the
|
||||
// software to the public domain. We make this dedication for the benefit
|
||||
// of the public at large and to the detriment of our heirs and
|
||||
// successors. We intend this dedication to be an overt act of
|
||||
// relinquishment in perpetuity of all present and future rights to this
|
||||
// software under copyright law.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
// OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 512428fac1f0ad7489f05b039e604f5b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb45e8174068d9e4d864cf995e3164f0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a88821ac8cb24fb4199e26f58fb95a6f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8448f2800dcf3d441adb407db216308e
|
||||
folderAsset: yes
|
||||
timeCreated: 1501133226
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3371e9602fc12543b4026c95d444839
|
||||
folderAsset: yes
|
||||
timeCreated: 1501134707
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,211 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// 保存需要烘焙的动画的相关数据
|
||||
/// </summary>
|
||||
public struct AnimData
|
||||
{
|
||||
#region 字段
|
||||
|
||||
public int vertexCount;
|
||||
public int mapWidth;
|
||||
public List<AnimationState> animClips;
|
||||
public string name;
|
||||
|
||||
private Animation animation;
|
||||
private SkinnedMeshRenderer skin;
|
||||
|
||||
#endregion
|
||||
|
||||
public AnimData(Animation anim, SkinnedMeshRenderer smr, string goName)
|
||||
{
|
||||
vertexCount = smr.sharedMesh.vertexCount;
|
||||
mapWidth = Mathf.NextPowerOfTwo(vertexCount);
|
||||
animClips = new List<AnimationState>(anim.Cast<AnimationState>());
|
||||
animation = anim;
|
||||
skin = smr;
|
||||
name = goName;
|
||||
}
|
||||
|
||||
#region 方法
|
||||
|
||||
public void AnimationPlay(string animName)
|
||||
{
|
||||
this.animation.Play(animName);
|
||||
}
|
||||
|
||||
public void SampleAnimAndBakeMesh(ref Mesh m)
|
||||
{
|
||||
this.SampleAnim();
|
||||
this.BakeMesh(ref m);
|
||||
}
|
||||
|
||||
private void SampleAnim()
|
||||
{
|
||||
if (this.animation == null)
|
||||
{
|
||||
Debug.LogError("animation is null!!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.animation.Sample();
|
||||
}
|
||||
|
||||
private void BakeMesh(ref Mesh m)
|
||||
{
|
||||
if (this.skin == null)
|
||||
{
|
||||
Debug.LogError("skin is null!!");
|
||||
return;
|
||||
}
|
||||
|
||||
this.skin.BakeMesh(m);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 烘焙后的数据
|
||||
/// </summary>
|
||||
public struct BakedData
|
||||
{
|
||||
#region 字段
|
||||
|
||||
public string name;
|
||||
public float animLen;
|
||||
public byte[] rawAnimMap;
|
||||
public int animMapWidth;
|
||||
public int animMapHeight;
|
||||
|
||||
#endregion
|
||||
|
||||
public BakedData(string name, float animLen, Texture2D animMap)
|
||||
{
|
||||
this.name = name;
|
||||
this.animLen = animLen;
|
||||
this.animMapHeight = animMap.height;
|
||||
this.animMapWidth = animMap.width;
|
||||
this.rawAnimMap = animMap.GetRawTextureData();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 烘焙器
|
||||
/// </summary>
|
||||
public class AnimMapBaker{
|
||||
|
||||
#region 字段
|
||||
|
||||
private AnimData? animData = null;
|
||||
private List<Vector3> vertices = new List<Vector3>();
|
||||
private Mesh bakedMesh;
|
||||
|
||||
private List<BakedData> bakedDataList = new List<BakedData>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region 方法
|
||||
|
||||
public void SetAnimData(GameObject go)
|
||||
{
|
||||
if(go == null)
|
||||
{
|
||||
Debug.LogError("go is null!!");
|
||||
return;
|
||||
}
|
||||
|
||||
Animation anim = go.GetComponent<Animation>();
|
||||
SkinnedMeshRenderer smr = go.GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
|
||||
if(anim == null || smr == null)
|
||||
{
|
||||
Debug.LogError("anim or smr is null!!");
|
||||
return;
|
||||
}
|
||||
this.bakedMesh = new Mesh();
|
||||
this.animData = new AnimData(anim, smr, go.name);
|
||||
}
|
||||
int animNum;
|
||||
public List<BakedData> Bake()
|
||||
{
|
||||
if(this.animData == null)
|
||||
{
|
||||
Debug.LogError("bake data is null!!");
|
||||
return this.bakedDataList;
|
||||
}
|
||||
//每一个动作都生成一个动作图
|
||||
for(int i = 0; i < this.animData.Value.animClips.Count; i++)
|
||||
{
|
||||
animNum = i;
|
||||
if (!this.animData.Value.animClips[i].clip.legacy)
|
||||
{
|
||||
|
||||
Debug.LogError(string.Format("{0} is not legacy!!", this.animData.Value.animClips[i].clip.name));
|
||||
continue;
|
||||
}
|
||||
|
||||
BakePerAnimClip(this.animData.Value.animClips[i]);
|
||||
}
|
||||
|
||||
return this.bakedDataList;
|
||||
}
|
||||
|
||||
private void BakePerAnimClip(AnimationState curAnim)
|
||||
{
|
||||
int curClipFrame = 0;
|
||||
float sampleTime = 0;
|
||||
float perFrameTime = 0;
|
||||
|
||||
curClipFrame = Mathf.ClosestPowerOfTwo((int)(curAnim.clip.frameRate * curAnim.length));
|
||||
perFrameTime = curAnim.length / curClipFrame; ;
|
||||
|
||||
Texture2D animMap = new Texture2D(this.animData.Value.mapWidth, curClipFrame, TextureFormat.RGBAHalf, false);
|
||||
animMap.name = string.Format("{0}_{1}.animMap", this.animData.Value.name, curAnim.name);
|
||||
this.animData.Value.AnimationPlay(curAnim.name);
|
||||
|
||||
for (int i = 0; i < curClipFrame; i++)
|
||||
{
|
||||
//EditorUtility.DisplayCancelableProgressBar("转换进度", $"正在处理第 {i}/{curClipFrame} 步", (float)i / curClipFrame);
|
||||
curAnim.time = sampleTime;
|
||||
|
||||
this.animData.Value.SampleAnimAndBakeMesh(ref this.bakedMesh);
|
||||
|
||||
for(int j = 0; j < this.bakedMesh.vertexCount; j++)
|
||||
{
|
||||
EditorUtility.DisplayCancelableProgressBar("转换进度", $"正在处理第 {i}/{curClipFrame} 步 {j}/{bakedMesh.vertexCount}点", (float)i / curClipFrame);
|
||||
Vector3 vertex = this.bakedMesh.vertices[j];
|
||||
animMap.SetPixel(j, i, new Color(vertex.x, vertex.y, vertex.z));
|
||||
}
|
||||
|
||||
sampleTime += perFrameTime;
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
animMap.Apply();
|
||||
Debug.Log($"{animNum}/{animData.Value.animClips.Count-1}");
|
||||
if (animNum== animData.Value.animClips.Count - 1)
|
||||
{
|
||||
Debug.Log("转换完成");
|
||||
}
|
||||
|
||||
this.bakedDataList.Add(new BakedData(animMap.name, curAnim.clip.length, animMap));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region 属性
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d58f874be9d391e43866e5e334ddf986
|
||||
timeCreated: 1501134718
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,174 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
|
||||
public class AnimMapBakerWindow : EditorWindow {
|
||||
|
||||
private enum SaveStrategy
|
||||
{
|
||||
AnimMap,//only anim map
|
||||
Mat,//with shader
|
||||
Prefab//prefab with mat
|
||||
}
|
||||
|
||||
#region 字段
|
||||
|
||||
public static GameObject targetGo;
|
||||
private static AnimMapBaker baker;
|
||||
private static string path = "GamePlay_ECS\\EntityConvert";
|
||||
|
||||
private static string subPath = "SubPath";
|
||||
private static SaveStrategy stratege = SaveStrategy.AnimMap;
|
||||
private static Shader _animMapShader;
|
||||
|
||||
private static Shader animMapShader
|
||||
{
|
||||
get
|
||||
{
|
||||
if(_animMapShader == null)
|
||||
_animMapShader = Shader.Find(animMapShaderName);
|
||||
return _animMapShader;
|
||||
}
|
||||
}
|
||||
private static string animMapShaderName = "ECSGame/URP/UnlitAnim";
|
||||
#endregion
|
||||
|
||||
|
||||
#region 方法
|
||||
|
||||
[MenuItem("Tools/AnimMapBaker")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
EditorWindow.GetWindow(typeof(AnimMapBakerWindow));
|
||||
baker = new AnimMapBaker();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
targetGo = (GameObject)EditorGUILayout.ObjectField(targetGo, typeof(GameObject), true);
|
||||
subPath = targetGo == null ? subPath : targetGo.name;
|
||||
EditorGUILayout.LabelField(string.Format("保存路径output path:{0}", Path.Combine(path, subPath)));
|
||||
path = EditorGUILayout.TextField(path);
|
||||
subPath = EditorGUILayout.TextField(subPath);
|
||||
stratege = (SaveStrategy)EditorGUILayout.EnumPopup("保存策略output type:", stratege);
|
||||
if (GUILayout.Button("Bake"))
|
||||
{
|
||||
if(targetGo == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("err", "targetGo is null!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
if(baker == null)
|
||||
{
|
||||
baker = new AnimMapBaker();
|
||||
}
|
||||
baker.SetAnimData(targetGo);
|
||||
List<BakedData> list =baker.Bake();
|
||||
if (list != null)
|
||||
{
|
||||
for(int i = 0; i < list.Count; i++)
|
||||
{
|
||||
BakedData data = list[i];
|
||||
Save(ref data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Save(ref BakedData data)
|
||||
{
|
||||
switch(stratege)
|
||||
{
|
||||
case SaveStrategy.AnimMap:
|
||||
SaveAsAsset(ref data);
|
||||
break;
|
||||
case SaveStrategy.Mat:
|
||||
SaveAsMat(ref data);
|
||||
break;
|
||||
case SaveStrategy.Prefab:
|
||||
SaveAsPrefab(ref data);
|
||||
break;
|
||||
}
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private Texture2D SaveAsAsset(ref BakedData data)
|
||||
{
|
||||
string folderPath = CreateFolder();
|
||||
Texture2D animMap = new Texture2D(data.animMapWidth, data.animMapHeight, TextureFormat.RGBAHalf, false);
|
||||
animMap.LoadRawTextureData(data.rawAnimMap);
|
||||
AssetDatabase.CreateAsset(animMap, Path.Combine(folderPath, GetValidName(data.name) + ".asset"));
|
||||
return animMap;
|
||||
}
|
||||
|
||||
public static string GetValidName(string pName)
|
||||
{
|
||||
pName = pName.Replace("|", "@");
|
||||
return pName;
|
||||
}
|
||||
|
||||
private Material SaveAsMat(ref BakedData data)
|
||||
{
|
||||
if(animMapShader == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("err", "shader is null!!", "OK");
|
||||
return null;
|
||||
}
|
||||
|
||||
if(targetGo == null || !targetGo.GetComponentInChildren<SkinnedMeshRenderer>())
|
||||
{
|
||||
EditorUtility.DisplayDialog("err", "SkinnedMeshRender is null!!", "OK");
|
||||
return null;
|
||||
}
|
||||
|
||||
SkinnedMeshRenderer smr = targetGo.GetComponentInChildren<SkinnedMeshRenderer>();
|
||||
Material mat = new Material(animMapShader);
|
||||
Texture2D animMap = SaveAsAsset(ref data);
|
||||
mat.SetTexture("_MainTex", smr.sharedMaterial.mainTexture);
|
||||
mat.SetTexture("_AnimMap", animMap);
|
||||
mat.SetFloat("_AnimLen", data.animLen);
|
||||
|
||||
string folderPath = CreateFolder();
|
||||
AssetDatabase.CreateAsset(mat, Path.Combine(folderPath, GetValidName(data.name) + ".mat"));
|
||||
|
||||
return mat;
|
||||
}
|
||||
|
||||
private void SaveAsPrefab(ref BakedData data)
|
||||
{
|
||||
Material mat = SaveAsMat(ref data);
|
||||
|
||||
if(mat == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("err", "mat is null!!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject go = new GameObject();
|
||||
go.AddComponent<MeshRenderer>().sharedMaterial = mat;
|
||||
go.AddComponent<MeshFilter>().sharedMesh = targetGo.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
|
||||
|
||||
string folderPath = CreateFolder();
|
||||
PrefabUtility.CreatePrefab(Path.Combine(folderPath, GetValidName(data.name) + ".prefab").Replace("\\", "/"), go);
|
||||
}
|
||||
|
||||
private string CreateFolder()
|
||||
{
|
||||
string folderPath = Path.Combine("Assets/" + path, subPath);
|
||||
if (!AssetDatabase.IsValidFolder(folderPath))
|
||||
{
|
||||
AssetDatabase.CreateFolder("Assets/" + path, subPath);
|
||||
}
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b0821312d64995540ae7372c5af049c0
|
||||
timeCreated: 1501143281
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "Game.Hotfix.Editor.AnimMapBaker",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"Game.Hotfix",
|
||||
"CameraShake",
|
||||
"spine-unity",
|
||||
"Coffee.UIParticle",
|
||||
"Unity.Addressables",
|
||||
"Unity.ResourceManager",
|
||||
"Unity.TextMeshPro",
|
||||
"UnityEngine.UI",
|
||||
"Unity.InputSystem",
|
||||
"Unity.VisualScripting.Core"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9dc34cc9588f7c04d887b97a4747f393
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e072dbe8965ad9440aed440c55f81680
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: ECSGame_URP_UnlitAnim
|
||||
m_Shader: {fileID: 4800000, guid: ebdcc09f7cb55fc44ac470f5bd7735bd, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _AnimMap:
|
||||
m_Texture: {fileID: 2800000, guid: c97a11d5fda59bf4aac7fa0ed2e9d24f, type: 2}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _AnimLen: 0
|
||||
m_Colors:
|
||||
- _BaseColor: {r: 1, g: 0, b: 0, a: 1}
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d46dbf44bad4c9499d457c512a24142
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: ECSGame_URP_UnlitNormal
|
||||
m_Shader: {fileID: 4800000, guid: 4f6aed460e447d74185e39330aab44fa, type: 3}
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats: []
|
||||
m_Colors: []
|
||||
m_BuildTextureStacks: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dc5ecf6006d10941a0717457781c1c9
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,95 @@
|
||||
Shader "ECSGame/URP/UnlitAnim"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_BaseColor("BaseColor", color) = (1,1,1,1)
|
||||
_MainTex("Texture", 2D) = "white" {}
|
||||
_AnimMap("AnimMap", 2D) = "white" {}
|
||||
_AnimLen("Anim Length", Float) = 0
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline"}
|
||||
Cull off
|
||||
|
||||
Pass
|
||||
{
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
// Includes
|
||||
// Changed
|
||||
//#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
//Changed
|
||||
//#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
|
||||
//new
|
||||
#pragma target 4.5
|
||||
#pragma multi_compile _ DOTS_INSTANCING_ON
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UniversalDOTSInstancing.hlsl"
|
||||
//new
|
||||
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 pos : POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertex : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
|
||||
CBUFFER_START(UnityPerMaterial)
|
||||
float _AnimLen;
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
sampler2D _AnimMap;
|
||||
float4 _AnimMap_TexelSize;//x == 1/width
|
||||
float4 _BaseColor;
|
||||
CBUFFER_END
|
||||
|
||||
float4 ObjectToClipPos(float3 pos)
|
||||
{
|
||||
return mul(UNITY_MATRIX_VP, mul(UNITY_MATRIX_M, float4 (pos,1)));
|
||||
}
|
||||
|
||||
v2f vert(appdata v, uint vid : SV_VertexID)
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
|
||||
float f = _Time.y / _AnimLen;
|
||||
|
||||
fmod(f, 1.0);
|
||||
|
||||
float animMap_x = (vid + 0.5) * _AnimMap_TexelSize.x;
|
||||
float animMap_y = f;
|
||||
|
||||
float4 pos = tex2Dlod(_AnimMap, float4(animMap_x, animMap_y, 0, 0));
|
||||
|
||||
v2f o;
|
||||
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
o.vertex = ObjectToClipPos(pos);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float4 col = tex2D(_MainTex, i.uv);
|
||||
return _BaseColor;
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebdcc09f7cb55fc44ac470f5bd7735bd
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures:
|
||||
- _MainTex: {instanceID: 0}
|
||||
- _AnimMap: {instanceID: 0}
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,83 @@
|
||||
Shader "ECSGame/URP/UnlitNormal"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex("Texture", 2D) = "white" {}
|
||||
}
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline"}
|
||||
Cull off
|
||||
|
||||
Pass
|
||||
{
|
||||
Tags { "LightMode" = "UniversalForward" }
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex vert
|
||||
#pragma fragment frag
|
||||
|
||||
// Includes
|
||||
//changed
|
||||
//#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
|
||||
//new
|
||||
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
||||
//changed
|
||||
//#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
|
||||
//new
|
||||
#pragma target 4.5
|
||||
#pragma multi_compile _ DOTS_INSTANCING_ON
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/UniversalDOTSInstancing.hlsl"
|
||||
//new
|
||||
|
||||
struct appdata
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 pos : POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct v2f
|
||||
{
|
||||
float2 uv : TEXCOORD0;
|
||||
float4 vertex : SV_POSITION;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
|
||||
CBUFFER_START(UnityPerMaterial)
|
||||
float _AnimLen;
|
||||
sampler2D _MainTex;
|
||||
float4 _MainTex_ST;
|
||||
sampler2D _AnimMap;
|
||||
float4 _AnimMap_TexelSize;//x == 1/width
|
||||
CBUFFER_END
|
||||
|
||||
float4 ObjectToClipPos(float3 pos)
|
||||
{
|
||||
return mul(UNITY_MATRIX_VP, mul(UNITY_MATRIX_M, float4 (pos,1)));
|
||||
}
|
||||
|
||||
v2f vert(appdata v, uint vid : SV_VertexID)
|
||||
{
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
|
||||
|
||||
v2f o;
|
||||
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
|
||||
o.vertex = ObjectToClipPos(v.pos);
|
||||
return o;
|
||||
}
|
||||
|
||||
float4 frag(v2f i) : SV_Target
|
||||
{
|
||||
float4 col = tex2D(_MainTex, i.uv);
|
||||
return col;
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4f6aed460e447d74185e39330aab44fa
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures:
|
||||
- _MainTex: {instanceID: 0}
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5d425136cef53c4b96119a051acee9d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c5dd14d58b09344e8068bd676a4ec9d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user