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();
    }

}

  

 

posted @ 2023-07-19 15:53  牛大胆V5  阅读(1084)  评论(0)    收藏  举报