增加A2WToolBox工具集,增加Launch场景核LaunchPanel

This commit is contained in:
Wurui
2025-11-08 11:06:48 +08:00
parent 3e92e5684a
commit 3b43829e85
726 changed files with 87807 additions and 215 deletions

View File

@@ -0,0 +1,17 @@
{
"name": "A2W.Runtime",
"rootNamespace": "",
"references": [
"GUID:f51ebe6a0ceec4240a699833d6309b23",
"GUID:e34a5702dd353724aa315fb8011f08c3"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 96fa0b7a72b176f49bb5a1f65f04de47
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6706138384a723b4288ee83fc2a5ecf7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public class AudioPlayer : Singleton<AudioPlayer>
{
public float bgmVolume
{
get
{
return _bgmVolume;
}
set
{
_bgmVolume = value;
if (bgmPlayer is null) return;
bgmPlayer.volume = _bgmVolume;
}
}
public float soundVolume
{
get
{
return _soundVolume;
}
set
{
_soundVolume = value;
if (soundPlayers is null) return;
foreach (var player in soundPlayers)
{
player.volume = _soundVolume;
}
}
}
private float _bgmVolume = 0.5f;
private float _soundVolume = 0.5f;
private AudioSource bgmPlayer;
private List<AudioSource> soundPlayers;
public void PlayBGM(AudioClip clip)
{
if (bgmPlayer is null)
{
bgmPlayer = CreateAudioSource("BGMPlayer");
}
bgmPlayer.clip = clip;
bgmPlayer.loop = true;
bgmPlayer.volume = bgmVolume;
bgmPlayer.Play();
}
public void PauseBGM()
{
bgmPlayer.Pause();
}
public void UnPauseBGM()
{
bgmPlayer.UnPause();
}
public void StopBGM()
{
bgmPlayer.Stop();
}
public void PlaySound(AudioClip clip)
{
AudioSource soundPlayer = GetEmptyAudioSource();
soundPlayer.volume = soundVolume;
soundPlayer.PlayOneShot(clip);
}
public void PauseAllSound()
{
foreach (var player in soundPlayers)
{
player.Pause();
}
}
public void UnPauseAllSound()
{
foreach (var player in soundPlayers)
{
player.UnPause();
}
}
public void StopAllSound()
{
foreach (var player in soundPlayers)
{
player.Stop();
}
}
private AudioSource GetEmptyAudioSource()
{
if (soundPlayers is null)
{
soundPlayers = new List<AudioSource>();
}
foreach (var player in soundPlayers)
{
if (player.isPlaying is false)
{
return player;
}
}
AudioSource audioSource = CreateAudioSource("SoundPlayer");
soundPlayers.Add(audioSource);
return audioSource;
}
private AudioSource CreateAudioSource(string name)
{
GameObject go = new GameObject();
go.name = name;
go.transform.SetParent(transform, false);
return go.AddComponent<AudioSource>();
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bfa0e43b2c704b840899ee81da682c7b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,149 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public static class Extensions
{
public static List<T> Shuffle<T>(this List<T> _list)
{
List<T> tempList = new List<T>(_list);
int rand;
T tempValue;
for (int i = tempList.Count - 1; i >= 0; i--)
{
rand = Random.Range(0, i + 1);
tempValue = tempList[rand];
tempList[rand] = tempList[i];
tempList[i] = tempValue;
}
return tempList;
}
public static string RemoveNameSpece(this string typeString)
{
string result;
string[] str = typeString.Split('.');
result = str[str.Length - 1];
return result;
}
}
public static class MathExtensions
{
/// <summary>
/// 返回大值
/// </summary>
/// <param name="a">原值</param>
/// <param name="b">比较值</param>
/// <returns>结果</returns>
public static float Max(this float a, float b)
{
return Mathf.Max(a, b);
}
public static float Min(this float a, float b)
{
return Mathf.Min(a, b);
}
public static int Max(this int a, int b)
{
return Mathf.Max(a, b);
}
public static int Min(this int a, int b)
{
return Mathf.Min(a, b);
}
public static float Abs(this float value)
{
return Mathf.Abs(value);
}
public static int Abs(this int value)
{
return Mathf.Abs(value);
}
}
public static class ConfigExtensions
{
public static List<int> ParseStringToIntList(this string str, char sep = ',')
{
List<int> result = new List<int>();
string[] subs = str.Split(sep);
foreach (var sub in subs)
{
result.Add(int.Parse(sub));
}
return result;
}
}
public static class ComponentExtensions
{
public static T TryAddComponent<T>(this GameObject go) where T : Component
{
go.TryGetComponent<T>(out T result);
if (result is null)
{
result = go.AddComponent<T>();
}
return result;
}
public static void RemoveComponent<T>(this GameObject go) where T : Component
{
go.TryGetComponent<T>(out T result);
if (result)
{
Object.Destroy(result);
}
}
public static T AddChildComponent<T>(this GameObject go) where T : Component
{
GameObject child = new GameObject();
string[] str = typeof(T).ToString().Split('.');
child.name = str[str.Length - 1];
child.transform.SetParent(go.transform, false);
T result = child.AddComponent<T>();
return result;
}
}
public static class AnimatorExtensions
{
public static bool IsAnimationDone(this Animator animator)
{
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
return true;
else
return false;
}
public static bool IsAnimationDone(this Animator animator, string name)
{
if (animator.GetCurrentAnimatorStateInfo(0).IsName(name) is false) return false;
if (animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1)
return true;
else
return false;
}
public static bool IsAnimation(this Animator animator, string name)
{
return animator.GetCurrentAnimatorStateInfo(0).IsName(name);
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cdce2793bb4fb41489503936cbb8c146
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using UnityEngine;
namespace MonsterLove.Collections
{
public class ObjectPool<T>
{
private List<ObjectPoolContainer<T>> list;
private Dictionary<T, ObjectPoolContainer<T>> lookup;
private Func<T> factoryFunc;
private int lastIndex = 0;
public ObjectPool(Func<T> factoryFunc, int initialSize)
{
this.factoryFunc = factoryFunc;
list = new List<ObjectPoolContainer<T>>(initialSize);
lookup = new Dictionary<T, ObjectPoolContainer<T>>(initialSize);
Warm(initialSize);
}
private void Warm(int capacity)
{
for (int i = 0; i < capacity; i++)
{
CreateContainer();
}
}
private ObjectPoolContainer<T> CreateContainer()
{
var container = new ObjectPoolContainer<T>();
container.Item = factoryFunc();
list.Add(container);
return container;
}
public T GetItem()
{
ObjectPoolContainer<T> container = null;
for (int i = 0; i < list.Count; i++)
{
lastIndex++;
if (lastIndex > list.Count - 1) lastIndex = 0;
if (list[lastIndex].Used)
{
continue;
}
else
{
container = list[lastIndex];
break;
}
}
if (container == null)
{
container = CreateContainer();
}
container.Consume();
lookup.Add(container.Item, container);
return container.Item;
}
public void ReleaseItem(object item)
{
ReleaseItem((T) item);
}
public void ReleaseItem(T item)
{
if (lookup.ContainsKey(item))
{
var container = lookup[item];
container.Release();
lookup.Remove(item);
}
else
{
Debug.LogWarning("This object pool does not contain the item provided: " + item);
}
}
public int Count
{
get { return list.Count; }
}
public int CountUsedItems
{
get { return lookup.Count; }
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: abe90b2b30f65a548825fbeba21cf864
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,32 @@
namespace MonsterLove.Collections
{
public class ObjectPoolContainer<T>
{
private T item;
public bool Used { get; private set; }
public void Consume()
{
Used = true;
}
public T Item
{
get
{
return item;
}
set
{
item = value;
}
}
public void Release()
{
Used = false;
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 64373aeb4afc30d43a9cbef9f4e90778
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using MonsterLove.Collections;
using UnityEngine;
namespace A2W
{
public class PoolManager : MonoBehaviour
{
public bool logStatus;
public Transform root;
private Dictionary<GameObject, ObjectPool<GameObject>> prefabLookup;
private Dictionary<GameObject, ObjectPool<GameObject>> instanceLookup;
private bool dirty = false;
public void Init()
{
prefabLookup = new Dictionary<GameObject, ObjectPool<GameObject>>();
instanceLookup = new Dictionary<GameObject, ObjectPool<GameObject>>();
}
public void WarmPool(GameObject prefab, int size)
{
if (prefabLookup is null)
{
Init();
}
if (prefabLookup.ContainsKey(prefab))
{
throw new Exception("Pool for prefab " + prefab.name + " has already been created");
}
var pool = new ObjectPool<GameObject>(() => { return instantiatePrefab(prefab); }, size);
prefabLookup[prefab] = pool;
dirty = true;
}
public GameObject SpawnObject(GameObject prefab)
{
return SpawnObject(prefab, Vector3.zero, Quaternion.identity);
}
public GameObject SpawnObject(GameObject prefab, Vector3 position, Quaternion rotation)
{
if (!prefabLookup.ContainsKey(prefab))
{
WarmPool(prefab, 1);
}
var pool = prefabLookup[prefab];
var clone = pool.GetItem();
clone.transform.SetPositionAndRotation(position, rotation);
clone.SetActive(true);
instanceLookup.Add(clone, pool);
dirty = true;
return clone;
}
public void ReleaseObject(GameObject clone)
{
clone.SetActive(false);
if (root != null) clone.transform.SetParent(root, false);
if (instanceLookup.ContainsKey(clone))
{
instanceLookup[clone].ReleaseItem(clone);
instanceLookup.Remove(clone);
dirty = true;
}
else
{
Debug.LogWarning("No pool contains the object: " + clone.name);
}
}
private GameObject instantiatePrefab(GameObject prefab)
{
var go = Instantiate(prefab) as GameObject;
//if (root != null) go.transform.parent = root;
if (root != null) go.transform.SetParent(root, false);
go.SetActive(false);
return go;
}
private void logUpdate()
{
if (logStatus && dirty)
{
printStatus();
dirty = false;
}
}
private void printStatus()
{
foreach (KeyValuePair<GameObject, ObjectPool<GameObject>> keyVal in prefabLookup)
{
Debug.Log(string.Format("Object Pool for Prefab: {0} In Use: {1} Total {2}", keyVal.Key.name, keyVal.Value.CountUsedItems, keyVal.Value.Count));
}
}
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 430d968e63581624e84fc43c08982663
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c70abcc76542897438343574bd737d8f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public interface ITransition
{
public void Init(Transform parent);
public void Begin();
public void Finish();
public bool IsDone();
}
}

View File

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

View File

@@ -0,0 +1,146 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
namespace A2W
{
public class SceneLoader : Singleton<SceneLoader>
{
ITransition currentTransition; // 当前的过场实例
Canvas canvas;
public bool isPreLoading { get; set; } = false; // 预加载中
public Action OnFinished; // 转场结束
bool isLoading = false;// 现在是否可以转场
WaitForSeconds leastTime;
public void Init()
{
GameObject go = new GameObject();
go.name = "LoadingCanvas";
go.transform.SetParent(transform, false);
canvas = go.AddComponent<Canvas>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 1000;
CanvasScaler canvasScaler = go.AddComponent<CanvasScaler>();
canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2(Screen.width, Screen.height);
}
/// <summary>
/// 使用转场加载场景
/// </summary>
/// <param name="SceneName">场景名称</param>
/// <param name="transition">转场方式</param>
/// <param name="hasPreload">是否有预加载</param>
/// <param name="leastTime">至少等待一定时间</param>
public void LoadScene(string SceneName, ITransition transition = null, bool hasPreload = false, float leastSecond = 0.2f)
{
// 如果现在不能转换场景直接返回
if (isLoading) return;
if (canvas is null)
{
Init();
}
isPreLoading = hasPreload;
leastTime = new WaitForSeconds(leastSecond);
currentTransition = transition;
// 如果有设置过场就设置过场
if (transition is not null)
{
currentTransition.Init(canvas.transform);
}
// 开始转换场景
StartCoroutine(LoadLevel(SceneName));
}
/// <summary>
/// 转换场景并且使用过场动画
/// </summary>
/// <param name="levelName">场景名称</param>
/// <returns></returns>
private IEnumerator LoadLevel(string levelName)
{
// 异步加载场景
AsyncOperation loading = SceneManager.LoadSceneAsync(levelName);
// 不允许场景加载完后直接转换
loading.allowSceneActivation = false;
// 现在不再能转换场景
isLoading = true;
if (currentTransition is not null)
{
// 开始过场
currentTransition.Begin();
// 等待一帧
// 理由再下面有解释,但其实这里本来不需要,因为检查动画前还夹着一个检查加载的过程。基本不会在一帧内就加载完
// 但是保险起见还是在播放动画后延迟一帧
yield return null;
// 至少等待一定时间
yield return leastTime;
// 等待动画播放完成
while (!currentTransition.IsDone())
yield return null;
}
// 等待场景加载几乎完成
while (loading.progress < 0.899)
yield return null;
// 允许场景加载完成
loading.allowSceneActivation = true;
// 等待场景加载彻底完成
while (loading.progress != 1)
yield return null;
//等待预加载完毕
while (isPreLoading)
yield return null;
if (currentTransition is not null)
{
// 结束过场
currentTransition.Finish();
// 等待一帧
// 因为我发现如果在开始动画后不等待一帧的话,第二个动画其实还没开始播放,
// 后面检测动画完成检测的就是第一个动画,就起不到检测第二个动画的作用。
yield return null;
// 至少等待一定时间
yield return leastTime;
// 等待动画播放完成
while (!currentTransition.IsDone())
yield return null;
}
// 可以继续转换场景
isLoading = false;
OnFinished?.Invoke();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bd380fab4cbd20747980f58db0daf6da
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- currentTransition: {fileID: 8901318832893215821, guid: be9b6eba0b0d6734f9f8a5fac438bdc1, type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1e2adb07173e97941a72950654b14704
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public class SceneSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<T>();
}
return _instance;
}
}
private static T _instance;
}
}

View File

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

View File

@@ -0,0 +1,51 @@
using UnityEngine;
namespace A2W
{
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance;
private static object _lock = new object();
public static T instance
{
get
{
if (applicationIsQuitting)
{
return null;
}
lock (_lock)
{
if (_instance == null)
{
_instance = (T)FindObjectOfType(typeof(T));
if (FindObjectsOfType(typeof(T)).Length > 1)
{
return _instance;
}
if (_instance == null)
{
GameObject singleton = new GameObject();
_instance = singleton.AddComponent<T>();
singleton.name = "(singleton)" + typeof(T).ToString();
DontDestroyOnLoad(singleton);
}
}
return _instance;
}
}
}
private static bool applicationIsQuitting = false;
public void OnDestroy()
{
applicationIsQuitting = true;
}
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 801d92a5bb83264408fc2ee41036b7ab
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using A2W;
using Cysharp.Threading.Tasks;
using System.Linq;
namespace A2W
{
public class UIManager : Singleton<UIManager>
{
public const string panel_prefabs_dir_path = "Assets/Gameplay/Prefabs/UIPanel/"; // UI面板预制体目录
// 这里保存IUIPanel的list
List<UIPanel> panels;
private Canvas mainCanvas;
private GameObject canvasObject;
private string defaultPanelPath;
public void Init(string defaultPanelPath = panel_prefabs_dir_path)
{
this.defaultPanelPath = defaultPanelPath;
if (panels is null)
{
panels = new List<UIPanel>();
}
// 生成canvas
CreateCanvas();
}
public void DestroyAllExceptLoading()
{
var panelsToRemove = panels.Where(panel => !(panel is ITransition)).ToList();
foreach (var panel in panelsToRemove)
{
Destroy(panel.gameObject);
panels.Remove(panel);
}
}
private void CreateCanvas()
{
if (canvasObject is not null) return;
canvasObject = new GameObject("UICanvas");
canvasObject.transform.SetParent(transform, false);
mainCanvas = canvasObject.AddComponent<Canvas>();
mainCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
//mainCanvas.sortingOrder = 1000;
UnityEngine.UI.CanvasScaler canvasScaler = canvasObject.AddComponent<UnityEngine.UI.CanvasScaler>();
canvasScaler.uiScaleMode = UnityEngine.UI.CanvasScaler.ScaleMode.ScaleWithScreenSize;
canvasScaler.referenceResolution = new Vector2(Screen.width, Screen.height);
canvasObject.AddComponent<UnityEngine.UI.GraphicRaycaster>();
}
public async UniTask<T> InitPanel<T>() where T : UIPanel
{
// 在这里加载对应panel的预制体
T panel = (T)await Resources.LoadAsync<T>(GetPanelPath<T>());
// 加载完了以后存在panels里
if (panel != null)
{
panel.transform.SetParent(mainCanvas.transform, false);
panels.Add(panel);
panel.Init();
}
return panel;
}
public async UniTask<T> InitPanel<T>(string path) where T : UIPanel
{
// 在这里加载对应panel的预制体
T panel = (T)await Resources.LoadAsync<T>(GetPanelPath<T>());
// 加载完了以后存在panels里
if (panel != null)
{
panel.transform.SetParent(mainCanvas.transform, false);
panels.Add(panel);
panel.Init();
}
return panel;
}
public async UniTask<T> ShowPanel<T>() where T : UIPanel
{
// 先判断panels里有没有对应的panel没有就先调用InitPanel
T panel = GetPanel<T>();
if (panel == null)
{
await InitPanel<T>();
panel = GetPanel<T>();
}
// 播放Show动画 直接调用UIPanel的 public abstract UniTask Show();
if (panel != null)
{
await panel.Show();
}
return panel;
}
public async UniTask<T> HidePanel<T>() where T : UIPanel
{
// 播放Hide动画 直接调用UIPanel的 public abstract UniTask Hide();
T panel = GetPanel<T>();
if (panel != null)
{
await panel.Hide();
}
// 后续会增加回收机制资源紧张时释放不需要的panel
return panel;
}
public T GetPanel<T>() where T : UIPanel
{
if (panels == null) return null;
return panels.OfType<T>().FirstOrDefault();
}
private string GetPanelPath<T>() where T : UIPanel
{
return defaultPanelPath + typeof(T).Name; // 使用Name而不是ToString()获取更简洁的类型名
}
}
}

View File

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

View File

@@ -0,0 +1,19 @@
using Cysharp.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public abstract class UIPanel : MonoBehaviour
{
public abstract void Init();
public abstract UniTask Show();
public abstract UniTask Hide();
}
}

View File

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

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c3317c04f34837b4091b497cd0f35b84
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,49 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace A2W
{
public static class Utils
{
public static T GetRandomEnumValue<T>() where T : System.Enum
{
T[] values = (T[])System.Enum.GetValues(typeof(T));
return values[UnityEngine.Random.Range(0, values.Length)];
}
// 调用示例MyEnum randomValue = GetRandomEnumValue<MyEnum>();
public static Texture2D CaptureScreenshot(Rect rect)
{
Texture2D screenshot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
screenshot.ReadPixels(rect, 0, 0);
screenshot.Apply();
return screenshot;
}
public static Texture2D CaptureCamera(Camera camera, Rect rect)
{
RenderTexture rt = new RenderTexture((int)rect.width, (int)rect.height, 0);
camera.targetTexture = rt;
camera.Render();
// 可以做多个相机
RenderTexture.active = rt;
Texture2D screenshot = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.RGB24, false);
screenshot.ReadPixels(rect, 0, 0);
screenshot.Apply();
camera.targetTexture = null;
RenderTexture.active = null;
GameObject.Destroy(rt);
return screenshot;
}
}
}

View File

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