Unity 移动UI Image及抖动问题
本Demo实测结果
| - | 显卡型号 | 测试结果 |
| 1 | Intel(R) HD Graphics 530 | 平滑 |
| 2 | Intel(R) HD Graphics 3000 | 卡顿严重 |
| 3 | NVIDIA GeForce GT610 | 卡顿明显 |
| 4 | NVIDIA GeForce GTX 1650 | 平滑 |
移动Image的方法一
以下是我最开始使用的移动方法,此方法会出现抖动:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class ImageScript : MonoBehaviour
{
public Image image;
public float moveSpeed = 5f;
private RectTransform imageRectTransform;
private void Start()
{
// 获取Image的RectTransform组件
imageRectTransform = image.GetComponent<RectTransform>();
}
private void Update()
{
Debug.Log(string.Format("Update {0}", "123456"));
MoveDo1();//
}
/// <summary>
///
/// </summary>
private void MoveDo1() {
// 根据moveSpeed修改Image的X坐标
// float newX = imageRectTransform.anchoredPosition.x + moveSpeed * Time.deltaTime;
float newX = imageRectTransform.anchoredPosition.x - moveSpeed;
imageRectTransform.anchoredPosition = new Vector2(newX, imageRectTransform.anchoredPosition.y);
}
public void OnClick()
{
Debug.Log(string.Format("点击事件响应{0}","123456"));
}
public void OnClick2(string param)
{
Debug.Log(string.Format("点击事件响应{0}", param));
}
}
移动Image的方法二(Vector2.Lerp)
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class ImageScript : MonoBehaviour
{
public Image image;
private RectTransform imageRectTransform;//Image的RectTransform组件
private float temp = 0f;//计时器
public float timespan = 0.015f;//多少秒移动一次(变相降低了更新位置的间隔)
public float moveSpeed = 100f;//移动速度
private Vector2 targetPosition;//目标位置
private Vector2 oldPosition;//记下原始位置
Vector2 direct;//方向
private void Start()
{
Application.targetFrameRate = 60;
// 获取Image的RectTransform组件
imageRectTransform = image.GetComponent<RectTransform>();
// 设置起始位置和目标位置为当前位置
oldPosition = targetPosition = imageRectTransform.anchoredPosition;
//方向
direct = Vector2.right;
}
private void Update()
{
//ResetPosition();
if (imageRectTransform.anchoredPosition.x > 760)
{
direct = Vector2.left;
} else if (imageRectTransform.anchoredPosition.x < -760)
{
direct = Vector2.right;
}
temp += Time.deltaTime;// 时长=时长+调用间隔
if (temp >= timespan)
{
// 计算新的位置
// targetPosition += Vector2.right * moveSpeed * temp;//方向*速度*时长
targetPosition += direct * moveSpeed * temp;//方向*速度*时长
Debug.Log(string.Format("方向={0},当前位置={1},目标位置={2}", direct, imageRectTransform.anchoredPosition, targetPosition));
// 平滑移动到新的位置
imageRectTransform.anchoredPosition = Vector2.Lerp(imageRectTransform.anchoredPosition, targetPosition, moveSpeed * Time.deltaTime);
temp = 0f;//还原计时
}
}
/// <summary>
///
/// </summary>
private void MoveDo1() {
// 根据moveSpeed修改Image的X坐标
// float newX = imageRectTransform.anchoredPosition.x + moveSpeed * Time.deltaTime;
float newX = imageRectTransform.anchoredPosition.x - moveSpeed;
imageRectTransform.anchoredPosition = new Vector2(newX, imageRectTransform.anchoredPosition.y);
}
public void OnClick()
{
Debug.Log(string.Format("点击事件响应{0}","123456"));
#if UNITY_EDITOR //如果是在编辑器环境下
UnityEditor.EditorApplication.isPlaying = false;
#else//在打包出来的环境下
Application.Quit();
#endif
}
public void OnClick2(string param)
{
Debug.Log(string.Format("点击事件响应{0}", param));
}
// Time.deltaTime 上一帧和当前帧之间的时间间隔(以秒为单位)
// Vector2.right是一个Unity内置的向量,它表示二维空间中的一个单位向右的向量。具体来说,它表示一个X轴正向的单位向量。
// 在Unity中,使用Vector2.right可以方便地获取一个向量,用于表示沿着X轴正方向的运动或方向。
/// <summary>
/// 回到初始位置
/// </summary>
private void ResetPosition()
{
if (imageRectTransform.anchoredPosition.x > 760)
{
targetPosition = oldPosition;//目标位置=原位置
imageRectTransform.anchoredPosition = oldPosition;//超过了1920,还原到原位置
}
}
}
二者结合(可通过按钮切换,便于比较)


using System.Collections;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class ImageScript : MonoBehaviour
{
public Image image;
private RectTransform imageRectTransform;//Image的RectTransform组件
private float temp = 0f;//计时器
public float timespan = 0.015f;//多少秒移动一次(变相降低了更新位置的间隔)
public float moveSpeed = 100f;//移动速度
private Vector2 targetPosition;//目标位置
private Vector2 oldPosition;//记下原始位置
Vector2 direct;//方向
public int codeType = 0;//实现的方式
public TextMeshProUGUI text;
private void Start()
{
Application.targetFrameRate = 60;
// 获取Image的RectTransform组件
imageRectTransform = image.GetComponent<RectTransform>();
// 设置起始位置和目标位置为当前位置
oldPosition = targetPosition = imageRectTransform.anchoredPosition;
//方向
direct = Vector2.right;
codeType = 0;//实现的方式
}
private void Update()
{
if (codeType == 0)
{
MoveDo0();//简单的移动
}else if (codeType == 1)
{
MoveDo1();//插值实现的移动
}
}
/// <summary>
/// 插值实现移动
/// </summary>
private void MoveDo1()
{
Debug.Log(string.Format("1 当前实现方式为:{0}", codeType));
text.text = "type 1";
DirectionConvert();//方向转变,实现来回移动
temp += Time.deltaTime;// 时长=时长+调用间隔
if (temp >= timespan)
{
// 计算新的位置
// targetPosition += Vector2.right * moveSpeed * temp;//方向*速度*时长
targetPosition += direct * moveSpeed * temp;//方向*速度*时长
Debug.Log(string.Format("1 方向={0},当前位置={1},目标位置={2}", direct, imageRectTransform.anchoredPosition, targetPosition));
// 平滑移动到新的位置
imageRectTransform.anchoredPosition = Vector2.Lerp(imageRectTransform.anchoredPosition, targetPosition, moveSpeed * Time.deltaTime);
temp = 0f;//还原计时
}
}
/// <summary>
/// 最原始的修改X坐标实现移动
/// </summary>
private void MoveDo0() {
Debug.Log(string.Format("0 当前实现方式为:{0}", codeType));
text.text = "type 0";
DirectionConvert();//方向转变,实现来回移动
// 根据moveSpeed修改Image的X坐标
float newX = 0f;
// float newX = imageRectTransform.anchoredPosition.x + moveSpeed * Time.deltaTime;
if (direct == Vector2.right)
{
newX = imageRectTransform.anchoredPosition.x + 6;
}
else if (direct == Vector2.left)
{
newX = imageRectTransform.anchoredPosition.x - 6;
}
Debug.Log(string.Format("0 方向={0},当前位置={1},目标位置={2}", direct, imageRectTransform.anchoredPosition.x, newX));
imageRectTransform.anchoredPosition = new Vector2(newX, imageRectTransform.anchoredPosition.y);
}
/// <summary>
/// 方向转变,实现来回移动
/// </summary>
private void DirectionConvert()
{
if (imageRectTransform.anchoredPosition.x > 760)
{
direct = Vector2.left;
}
else if (imageRectTransform.anchoredPosition.x < -760)
{
direct = Vector2.right;
}
}
public void OnClick()
{
Debug.Log(string.Format("点击事件响应{0}","123456"));
#if UNITY_EDITOR //如果是在编辑器环境下
UnityEditor.EditorApplication.isPlaying = false;
#else//在打包出来的环境下
Application.Quit();
#endif
}
public void OnClick2(string param)
{
Debug.Log(string.Format("点击事件响应{0}", param));
}
// Time.deltaTime 上一帧和当前帧之间的时间间隔(以秒为单位)
// Vector2.right是一个Unity内置的向量,它表示二维空间中的一个单位向右的向量。具体来说,它表示一个X轴正向的单位向量。
// 在Unity中,使用Vector2.right可以方便地获取一个向量,用于表示沿着X轴正方向的运动或方向。
/// <summary>
/// 回到初始位置
/// </summary>
private void ResetPosition()
{
if (imageRectTransform.anchoredPosition.x > 760)
{
targetPosition = oldPosition;//目标位置=原位置
imageRectTransform.anchoredPosition = oldPosition;//超过了1920,还原到原位置
}
}
/// <summary>
/// 设置运动实现方式0
/// </summary>
public void SetCodeType0()
{
this.codeType = 0;
ResetPosition();
}
/// <summary>
/// 设置运动实现方式1
/// </summary>
public void SetCodeType1()
{
this.codeType = 1;
ResetPosition();
}
}

浙公网安备 33010602011771号