在我们进行开发时,需要对物体进行动画帧处理,常规处理方式为创建animation,对animation进行处理
这是通过脚本对图片进行控制
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.UI;
public enum LoadMode
{
Resources,
StreamingAssets,
AssetBundle
}
public enum PlayMode
{
None,
Normal,
Inverse,
}
[RequireComponent(typeof(RawImage))]
public class AnimationBase : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
[HideInInspector]
public RawImage img;
public LoadMode loadMode;
[SerializeField]
private PlayMode playMode = PlayMode.Normal;
#region 三种加载方式共有参数
[HideInInspector] public List<Texture> textures;
public bool isAutoPlay;
public bool unScaleTime;
[Tooltip("自动播放时每张图片索引的间隔")]
public bool canDrag;
public float sample_Win = 30;
private float sample;
public string path;
public int aniStartIndex;
public int aniLastIndex;
public int textureInterval = 1;
[Tooltip("滑动时每张图片索引的间隔")]
public int dragInterval = 1;
//[Tooltip("图片路径中零的个数")]
public int zeroCount;
public float delayTime;
public bool isLoop;
[Tooltip("是否有间隔的循环")]
public bool isExtendLoop;
[Tooltip("每次循环间隔时间")]
public float loopTime;
private int index;
[HideInInspector]
public float animationTime;
protected int dir = 1;
private bool isPlaying;
private DateTime startUpTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
private double nowTime;
public delegate void AnimationDoneEventHandler();
/// <summary>
/// 只播放一次的序列,序列结束事件
/// </summary>
public event AnimationDoneEventHandler AnimationOnceDoneEvent;
/// <summary>
/// 循环播放的序列,序列结束事件
/// </summary>
public event Action AnimationPerLoopDoneEvent;
public event Action BeginDragEvent;
public event Action EndDragEvent;
public event Action OnDragEvent;
public event Action PlayToDoneEvent;
protected bool isDraging;
#endregion
#region StreamingAssets加载方式参数,存在内存泄漏问题,尽量避免使用
/ <summary>
/ 图片检索格式
/ </summary>
//[Tooltip("图片格式,例如:png、jpg")]
//public string pattern;
/ <summary>
/ 图片路径后缀
/ </summary>
//[Tooltip("路径索引号后缀,例如:001_00050(-\"fs8\")")]
[HideInInspector] public string suffix;
private List<FileInfo> fileInfos;
#endregion
#region AssetBundle加载方式参数
private AssetBundle textureBundle;
private string[] assetsName;
#endregion
public int Index
{
set
{
index = value;
if (((index == aniLastIndex - textureInterval) && playMode == PlayMode.Normal) || (index == aniStartIndex && playMode == PlayMode.Inverse))
{
if (isExtendLoop)
{
//InitIndex();
ExtendLoop();
if (AnimationPerLoopDoneEvent != null)
AnimationPerLoopDoneEvent();
}
else if (isLoop)
{
if (AnimationPerLoopDoneEvent != null)
AnimationPerLoopDoneEvent();
}
}
if (index >= aniLastIndex && isLoop)
{
index = aniStartIndex;
}
else if (index < 0 && isLoop)
{
index = aniLastIndex - textureInterval;
}
else if (((index >= aniLastIndex - textureInterval) && !isLoop && playMode == PlayMode.Normal) || ((index <= aniStartIndex) && !isLoop && playMode == PlayMode.Inverse))
{
Pause();
if (AnimationOnceDoneEvent != null)
{
AnimationOnceDoneEvent();
}
}
}
get
{
return index;
}
}
//public static AnimationBase Instance { private set; get; }
private void OnEnable()
{
InitTimer();
if (isExtendLoop)
Play(loopTime);
}
private void Awake()
{
Init();
}
protected virtual void Start()
{
//Instance = this;
//GetAnimationCount();
InitIndex();
SetSample(sample_Win);
LoadAssetBundle();
GetAnimationTime();
AutoPlay();
EnrolEvent();
}
private bool isOpen = false;
public RawImage Anim;
public Sprite[] sprites; // 存储图片的数组
public static void OnButtonClicTest()
{
Debug.Log("666");
}
public void OnButtonClick()
{
isOpen = !isOpen;
if (isOpen)
{
// Debug.Log("789" + index);
Anim.gameObject.SetActive(true);
// Replay();
Replay();
Debug.Log("11111");
}
else
{
RawImage rawImage = GetComponent<RawImage>();
Texture2D tex = rawImage.texture as Texture2D; //获取截图的位置和大小
Rect rect = new Rect(0, 0, 100, 100); //创建截图
Texture2D newTex = new Texture2D((int)rect.width, (int)rect.height); //获取截图数据
Color[] colors = tex.GetPixels((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height); //将数据设置到新纹理中
newTex.SetPixels(colors); //应用修改
newTex.Apply(); //将截图设置到RawImage中 rawImage.texture = newTex;
Anim.texture = newTex;
index = 0;
Anim.gameObject.SetActive(false);
Debug.Log("22222");
}
}
private void AutoPlay()
{
if (isAutoPlay)
Play(delayTime);
}
private void Init()
{
img = GetComponent<RawImage>();
textures = new List<Texture>();
fileInfos = new List<FileInfo>();
if (playMode == PlayMode.Normal)
{
dir = 1;
}
else
{
dir = -1;
}
if (loadMode == LoadMode.Resources && !string.IsNullOrEmpty(path))
{
Texture[] tempTex = Resources.LoadAll<Texture>(path);
if (tempTex.Length == 0) return;
//Array.Sort(tempTex, (a, b) => DrawNumFromString(a.name, '_').CompareTo(DrawNumFromString(b.name, '_')));
textures.AddRange(tempTex);
aniLastIndex = textures.Count;
}
else if (loadMode == LoadMode.StreamingAssets)
{
#if UNITY_STANDALONE_WIN
fileInfos.Clear();
FileInfo[] files = null;
string filePath = Application.streamingAssetsPath + "/" + path;
files = new DirectoryInfo(filePath).GetFiles();
#endif
//Array.Sort(files, (a, b) => DrawNumFromString(a.Name, '_').CompareTo(DrawNumFromString(b.Name, '_')));
#if UNITY_EDITOR&&!UNITY_IOS&&!UNITY_ANDROID
if (files != null)
{
for (int i = 0; i < files.Length; i++)
{
if (files[i].Name.Contains(".meta")) continue;
fileInfos.Add(files[i]);
}
aniLastIndex = fileInfos.Count;
}
#elif UNITY_STANDALONE_WIN
fileInfos.AddRange(files);
aniLastIndex = fileInfos.Count;
#endif
}
}
public void InitIndex()
{
Index = aniStartIndex;
}
private void InitTimer()
{
nowTime = GetUtcMiliseconds();
timer = nowTime + sample;
}
protected virtual void EnrolEvent()
{
//AnimationDoneEvent += ExtendLoop;
}
protected virtual void CancelEvent()
{
//AnimationDoneEvent -= ExtendLoop;
}
private void OnDestroy()
{
CancelEvent();
AssetBundle.UnloadAllAssetBundles(true);
}
private void ExtendLoop()
{
Pause();
Play(loopTime);
}
protected void LoadAssetBundle()
{
if (loadMode == LoadMode.AssetBundle && !string.IsNullOrEmpty(path))
{
string tempPath = Application.streamingAssetsPath + "/" + path;
textureBundle = AssetBundle.LoadFromFile(tempPath);
assetsName = textureBundle.GetAllAssetNames();
aniLastIndex = assetsName.Length;
}
}
protected void LoadAnimation()
{
if (!isDraging)
{
Index += textureInterval * dir;
}
if (isPlayTo)
{
if (Index == toIndex)
{
Pause();
canDrag = true;
PlayToDoneEvent?.Invoke();
}
}
if (loadMode == LoadMode.Resources)
{
//Texture texture = Resources.Load<Texture>(path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);
Texture texture = textures[Index];
if (texture)
img.texture = texture;
else
Debug.LogError("动画路径错误");
}
else if (loadMode == LoadMode.StreamingAssets)
{
//StartCoroutine(nameof(GetTexture), Application.streamingAssetsPath + "/" + path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);
//StartCoroutine(nameof(GetTexture), fileInfos[Index].FullName);
#if UNITY_STANDALONE_WIN
string tempPath = Application.streamingAssetsPath + "/" + path + "/" + fileInfos[Index].Name;
//string tempPath = Application.streamingAssetsPath + "/" + path+string.Format("{0:D"+zeroCount+"}",Index)+suffix;
#elif UNITY_IOS || UNITY_ANDROID
string tempPath = Application.streamingAssetsPath + "/" + path+string.Format("{0:D"+zeroCount+"}",Index)+suffix;
#endif
#if UNITY_STANDALONE_WIN || UNITY_IOS
Texture texture = LoadTexture(tempPath);
if (texture)
{
img.texture = texture;
}
else
{
Debug.LogError("动画路径错误");
}
#elif UNITY_ANDROID
StartCoroutine(nameof(GetTexture), tempPath);
#endif
}
else
{
img.texture = textureBundle.LoadAsset<Texture>(assetsName[Index]);
}
Resources.UnloadUnusedAssets();
}
private IEnumerator GetTexture(string name)
{
using (UnityWebRequest uwrt = UnityWebRequestTexture.GetTexture(name))
{
yield return uwrt.SendWebRequest();
if (!string.IsNullOrEmpty(uwrt.error))
{
Debug.LogError(uwrt.error);
}
else
{
img.texture = DownloadHandlerTexture.GetContent(uwrt);
img.SetNativeSize();
//System.GC.Collect();
}
}
}
private Texture LoadTexture(string path)
{
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
{
fs.Seek(0, SeekOrigin.Begin);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, data.Length);
Texture2D texture = new Texture2D(100, 100, TextureFormat.ARGB32, false);
texture.LoadImage(data);
if (texture)
{
texture.name = Index.ToString();
return texture;
}
else
{
return null;
}
}
}
private double timer;
private bool isStartPlay;
private void Update()
{
CheckAnimation();
}
private void CheckAnimation()
{
if (isStartPlay || isPlayTo)
{
nowTime = GetUtcMiliseconds();
if (nowTime.CompareTo(timer) > 0)
{
timer = GetUtcMiliseconds();
timer += sample;
LoadAnimation();
}
}
}
private IEnumerator DelayPlay(float delay)
{
yield return new WaitForSeconds(delay);
InitIndex();
nowTime = GetUtcMiliseconds();
timer = nowTime + sample;
isStartPlay = true;
isPlaying = true;
}
public virtual void OnBeginDrag(PointerEventData eventData)
{
if (!canDrag || Input.touchCount > 1) return;
isDraging = true;
isStartPlay = false;
BeginDragEvent?.Invoke();
}
public virtual void OnDrag(PointerEventData eventData)
{
if (!canDrag || Input.touchCount > 1) return;
if (eventData.delta.x < 0)
{
dir = -1;
dragInterval = Mathf.Clamp(Mathf.RoundToInt(Mathf.Abs(eventData.delta.x) * Time.deltaTime), 1, 5);
Index -= dragInterval;
}
else if (eventData.delta.x > 0)
{
dir = 1;
dragInterval = Mathf.Clamp(Mathf.RoundToInt(eventData.delta.x * Time.deltaTime), 1, 5);
Index += dragInterval;
}
if (!isLoop || !isExtendLoop)
{
Index = Mathf.Clamp(Index, aniStartIndex, aniLastIndex - 1);
}
OnDragEvent?.Invoke();
LoadAnimation();
}
public virtual void OnEndDrag(PointerEventData eventData)
{
if (!canDrag || Input.touchCount > 1) return;
isDraging = false;
EndDragEvent?.Invoke();
}
#region ToolMethod
private int DrawNumFromString(string str, char splitChar)
{
int index = str.LastIndexOf(splitChar);
return int.Parse(System.Text.RegularExpressions.Regex.Replace(str.Substring(index), @"[^0-9]+", ""));
}
private double GetUtcMiliseconds()
{
TimeSpan ts = DateTime.UtcNow - startUpTime;
return ts.TotalMilliseconds;
}
public void SetSample(float val)
{
sample = 1.0f / val * 1000;
nowTime = GetUtcMiliseconds();
timer = nowTime + sample;
}
public void SetAssetBundle(AssetBundle bundle)
{
textureBundle = bundle;
assetsName = textureBundle.GetAllAssetNames();
aniLastIndex = assetsName.Length;
}
public void SetLoadMode(LoadMode model)
{
loadMode = model;
}
public void ChangePath(string path, int aniStartIndex, int aniLastIndex)
{
this.path = path;
this.aniStartIndex = aniStartIndex;
this.aniLastIndex = aniLastIndex;
Index = aniStartIndex;
if (loadMode == LoadMode.StreamingAssets)
{
#if UNITY_STANDALONE_WIN
fileInfos.Clear();
FileInfo[] files = null;
string filePath = Application.streamingAssetsPath + "/" + path;
files = new DirectoryInfo(filePath).GetFiles();
#endif
//Array.Sort(files, (a, b) => DrawNumFromString(a.Name, '_').CompareTo(DrawNumFromString(b.Name, '_')));
#if UNITY_EDITOR&&!UNITY_IOS&&!UNITY_ANDROID
if (files != null)
{
for (int i = 0; i < files.Length; i++)
{
if (files[i].Name.Contains(".meta")) continue;
fileInfos.Add(files[i]);
}
this.aniLastIndex = fileInfos.Count;
}
#elif UNITY_STANDALONE_WIN
fileInfos.AddRange(files);
this.aniLastIndex = fileInfos.Count;
#endif
#if UNITY_STANDALONE_WIN
string tempPath = Application.streamingAssetsPath + "/" + path + "/" + fileInfos[Index].Name;
//string tempPath = Application.streamingAssetsPath + "/" + path + string.Format("{0:D" + zeroCount + "}", Index) + suffix;
#elif UNITY_IOS || UNITY_ANDROID
string tempPath = Application.streamingAssetsPath + "/" + path+ string.Format("{0:D" + zeroCount + "}", Index) + suffix;
#endif
#if UNITY_STANDALONE_WIN || UNITY_IOS
Texture texture = LoadTexture(tempPath);
if (texture)
img.texture = texture;
else
Debug.LogError("动画路径错误");
#elif UNITY_ANDROID
StartCoroutine(nameof(GetTexture), tempPath);
#endif
}
else if (loadMode == LoadMode.Resources)
{
textures.Clear();
textures.AddRange(Resources.LoadAll<Texture>(path));
this.aniLastIndex = textures.Count;
//Texture texture = Resources.Load<Texture>(path + string.Format("{0:D" + zeroCount + "}", Index) + suffix);
Texture texture = textures[Index];
if (texture)
img.texture = texture;
else
Debug.LogError("动画路径错误");
}
else
{
AssetBundle.UnloadAllAssetBundles(true);
string tempPath = Application.streamingAssetsPath + "/" + path;
textureBundle = AssetBundle.LoadFromFile(tempPath);
assetsName = textureBundle.GetAllAssetNames();
this.aniLastIndex = assetsName.Length;
img.texture = textureBundle.LoadAsset<Texture>(assetsName[Index]);
}
img.SetNativeSize();
Resources.UnloadUnusedAssets();
}
public float GetProgress()
{
return Index / aniLastIndex * 1.0f;
}
public void GetAnimationTime()
{
animationTime = aniLastIndex * sample / 1000;
}
public void Pause()
{
isPlaying = false;
isStartPlay = false;
isPlayTo = false;
}
public void Play(float delay = 0, PlayMode mode = PlayMode.None)
{
if (isPlaying) return;
if (mode != PlayMode.None)
playMode = mode;
if (playMode == PlayMode.Normal)
dir = 1;
else
dir = -1;
StopAllCoroutines();
StartCoroutine(DelayPlay(delay));
}
public void Replay(float delay = 0, PlayMode mode = PlayMode.Normal)
{
//if (isPlaying) return;
playMode = mode;
if (playMode == PlayMode.Normal)
dir = 1;
else
dir = -1;
//InitIndex();
Debug.Log("123456");
StopAllCoroutines();
StartCoroutine(DelayPlay(delay));
}
private bool isPlayTo;
private int toIndex;
public void PlayTo(int to, int from = 0)
{
if (isPlayTo) return;
if ((to >= aniLastIndex) || (from >= aniLastIndex) || from < 0 || to < 0)
{
Debug.LogError("超出序列范围");
return;
}
if (from != 0)
{
Index = from;
}
PlayMode mode = from <= to ? PlayMode.Normal : PlayMode.Inverse;
SetPlayMode(mode);
isPlayTo = true;
canDrag = false;
toIndex = to;
}
public void ClearPlayToEvent()
{
PlayToDoneEvent = null;
}
public void ClearBeginDragEvent()
{
BeginDragEvent = null;
}
public void ClearEndDragEvent()
{
EndDragEvent = null;
}
public void ClearOnDragEvent()
{
OnDragEvent = null;
}
public void ClearAllEvent()
{
AnimationPerLoopDoneEvent = null;
AnimationOnceDoneEvent = null;
BeginDragEvent = null;
EndDragEvent = null;
PlayToDoneEvent = null;
OnDragEvent = null;
}
public void SetPlayMode(PlayMode mode)
{
playMode = mode;
if (mode == PlayMode.Normal)
dir = 1;
else
dir = -1;
}
public void SetCurrentIndex(int index)
{
Index = index;
}
public void ChangeCurtSprite()
{
Texture texture = textures[0];
img.texture = texture;
}
#endregion
}