U3D实战笔记02(问题&解决方案)
1.点击按钮无响应时:
*按钮必须正面超前,即旋转度数都为正
*不能有其他UI遮挡在按钮之前
2.全景图以材质类型贴在球体上时,网格划分较粗的球体会导致画面变形,这时需要将球体面数变大。
3.播放序列帧时需要不时清理缓存,避免造成播放卡顿:
Resources.UnloadUnusedAssets();
System.GC.Collect();
注意:需要在脚本头部加上:
using System.IO;
【自动播放序列帧的代码(插件:Dotween)】:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using DG.Tweening;
public class AutoPlayFrameTweenerController : MonoBehaviour
{
[Header("Frame Images")]
//图片加载路径(StreamingAssets)
public string framePath;
//图片起始索引值
public int frameStartIndex;
//图片结束索引值
public int frameEndIndex;
//索引值位数
public int frameIndexPlace;
//图片格式
public string frameImgFormat;
//图片尺寸
public int frameImgWidth;
public int frameImgHeight;
[Header("Play Setting")]
//帧率
public float fps=0.1f;
//每帧停留时间
private float spf;
//是否循环
public bool isLoop;
[Header("Next Animation")]
//是否有下一组动画
public bool hasNextAnimation;
//播放下一组动画的预设体
public GameObject nextPlayerPerfab;
//加载帧的图片
private Texture2D texture;
//当前播放帧序
private int currentFrameIndex;
//播放动画
private Tweener tweener;
public void Start()
{
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
//默认图片宽高
frameImgWidth = 2048;
frameImgHeight = 1536;
//默认图片格式
frameImgFormat = "jpg";
//默认帧率
spf = 1 / fps;
//默认索引值位数
frameIndexPlace = 5;
currentFrameIndex = frameStartIndex;
texture = new Texture2D(frameImgWidth, frameImgHeight);
//为防止闪白,先将播放容器初始化为第一帧的样子
PlayFrame();
currentFrameIndex++;
PlayFrameByTween();
}
//播放序列帧
private void PlayFrame()
{
Resources.UnloadUnusedAssets();
System.GC.Collect();
string path = Application.streamingAssetsPath + "/" + framePath + currentFrameIndex.ToString().PadLeft(frameIndexPlace, '0') + "." + frameImgFormat;
LoadImg(path);
}
//设置tweener控制帧序列播放
private void PlayFrameByTween()
{
tweener = DOTween.To(() => frameStartIndex, x => currentFrameIndex = x, frameEndIndex, spf);
tweener.SetEase(Ease.Linear);
tweener.OnUpdate(() => PlayFrame());
if (isLoop)
{
tweener.SetLoops(-1);
}
if (hasNextAnimation)
{
tweener.OnComplete(() => LoadNextAnimation());
}
}
//加载后续动画
private void LoadNextAnimation()
{
GameObject gameObject = GameObject.Instantiate(nextPlayerPerfab, transform.parent);
Destroy(this.gameObject);
}
private void LoadImg(string path)
{
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, (int)fileStream.Length);
fileStream.Close();
fileStream.Dispose();
texture.LoadImage(bytes);
gameObject.GetComponent<RawImage>().texture = texture;
}
private void OnDisable()
{
tweener.Kill();
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
}
}
4.调用带参的按钮响应函数需要用代理方式【delegate】
5.dotween倒放动画是,OnComplete()失效,需要用OnStepComplete()
6.场景中的UI是否随着相机视角移动与Canvas组件中的Rennder Mode有关,当该属性值为【World Space】时,按钮固定在场景中不随相机视角移动。
7.触控播放序列帧代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class TouchPalyFrameController : MonoBehaviour
{
//帧加载路径
public string framePath;
//图片索引
public int startIndex;
public int endIndex;
//图片格式
public string imgFormat;
//索引补全位数
public int indexPlaces;
//图片尺寸
public int frameWidth;
public int frameHeight;
//单张停留时间
public float stayTime;
//计时器
private float currentDurring;
//当前播放的帧索引
public int currentIndex;
//图片材质
private Texture2D texture;
//序列帧播放状态
private enum framePlayState { left,right,stop};
private framePlayState currentState;
//触控开关
[HideInInspector]
public bool isTouch = false;
private void Awake()
{
indexPlaces = 5;
stayTime = 0.03f;
imgFormat = "jpg";
//初始化默认图片尺寸
frameHeight = 1536;
frameWidth = 2048;
//初始化帧播放状态
currentState = framePlayState.stop;
texture = new Texture2D(frameWidth, frameHeight);
currentDurring = 0;
//显示第一张
currentIndex = startIndex;
}
// Start is called before the first frame update
public void Start()
{
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
ChangeFrame();
currentIndex++;
}
// Update is called once per frame
void Update()
{
if (isTouch)
{
if (Input.touchCount == 1)
{
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
if (Input.GetTouch(0).deltaPosition.x < 0 - Mathf.Epsilon)
{
//左转
currentState = framePlayState.left;
}
else
{
//右转
currentState = framePlayState.right;
}
}
if (Input.touchCount == 1 && (Input.GetTouch(0).phase == TouchPhase.Stationary || Input.GetTouch(0).phase == TouchPhase.Ended))
{
//停滞
currentState = framePlayState.stop;
}
}
if (currentState != framePlayState.stop)
{
if (currentState == framePlayState.left)
{
//左转
currentDurring += Time.deltaTime;
if (currentDurring > stayTime)
{
currentIndex = currentIndex == startIndex ? endIndex : --currentIndex;
ChangeFrame();
currentDurring = 0;
}
}
else
{
//右转
currentDurring += Time.deltaTime;
if (currentDurring > stayTime)
{
currentIndex = currentIndex == endIndex ? startIndex : ++currentIndex;
ChangeFrame();
currentDurring = 0;
}
}
}
}
}
public void ChangeFrame()
{
string path = Application.streamingAssetsPath + "/" + framePath + currentIndex.ToString().PadLeft(indexPlaces, '0') + '.' + imgFormat;
LoadImg(path);
}
private void LoadImg(string path)
{
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
FileStream fileStream = new FileStream(path,FileMode.Open,FileAccess.Read);
fileStream.Seek(0, SeekOrigin.Begin);
byte[] bytes = new byte[fileStream.Length];
fileStream.Read(bytes, 0, (int)fileStream.Length);
fileStream.Close();
fileStream.Dispose();
texture.LoadImage(bytes);
gameObject.GetComponent<RawImage>().texture = texture;
}
private void OnDisable()
{
Resources.UnloadUnusedAssets();
Resources.UnloadUnusedAssets();
System.GC.Collect();
System.GC.Collect();
}
}
8.当场景背景为空时,UI的显示将出错变糊
9.当项目不是因为脚本死循环等问题造成的无响应,在资源管理器中关闭unity shader也许也可解决运行就无响应的问题。
10.当项目运行出现逻辑错误时,也许时Awake和Start唤醒先后顺序造成的。
#####未完待续###########