You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity3D:点击触发器后如何让GameObject单次点击平滑移动到指定位置?

问题描述

需求:点击底部任意小立方体触发器,使对应的大立方体左右平滑移动至屏幕中心。
当前问题:使用Vector3.MoveTowards的脚本点击触发器后,物体仅移动一小段距离,需多次点击才能到达目标位置。希望实现单次点击即可让物体基于帧率平滑移动到目标,项目无需角色或刚体,曾尝试无效的do/while循环,考虑过Coroutine但想寻找更简便的解决方法。

问题原因

原代码将移动逻辑完全放在Input.GetMouseButtonDown(0)的分支中,这个判断仅在鼠标点击的单帧内执行一次,所以每次点击只会让物体移动一帧的距离(speed * Time.deltaTime),无法持续移动到目标位置。

优化方案

添加一个targetPosition变量存储目标位置,点击时仅更新这个目标值,然后在Update的每帧中执行移动逻辑,直到物体到达目标位置。同时优化标签判断逻辑,避免大量重复的if语句。

优化后的代码

public class MoveBoxes : MonoBehaviour
{
    Camera cam;     
    public LayerMask mask;     
    private float speed = 7500f;

    // 存储目标位置,默认初始位置
    private Vector3 targetPosition;

    // 用字典映射标签到目标位置,替代大量if判断
    private Dictionary<string, Vector3> tagToPosition = new Dictionary<string, Vector3>();

    void Awake() 
    { 
        cam = Camera.main;
        
        // 初始化位置映射
        tagToPosition.Add("1stBox", new Vector3(37000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("2ndBox", new Vector3(27000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("3rdBox", new Vector3(17000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("4thBox", new Vector3(7000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("5thBox", new Vector3(-3000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("6thBox", new Vector3(-13000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("7thBox", new Vector3(-23000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("8thBox", new Vector3(-33000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("9thBox", new Vector3(-43000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("10thBox", new Vector3(-53000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("11thBox", new Vector3(-63000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("12thBox", new Vector3(-73000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("13thBox", new Vector3(-83000.20f, -102.18f, -3919.06f));
        tagToPosition.Add("14thBox", new Vector3(-93000.20f, -102.18f, -3919.06f));
        
        // 初始目标位置设为当前物体位置
        targetPosition = transform.position;
        Debug.Log(transform.position);
    }
    
    void Update()
    {
        float moveStep = speed * Time.deltaTime;
        
        // 每帧执行移动,直到到达目标位置
        if (transform.position != targetPosition)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveStep);
            Debug.Log(transform.position);
        }

        // 处理点击逻辑,仅更新目标位置
        if (Input.GetMouseButtonDown(0))
        {
            Ray ray = cam.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
        
            if (Physics.Raycast(ray, out hit, 15000, mask))
            {
                string hitTag = hit.collider.tag;
                // 如果标签在映射字典中,更新目标位置
                if (tagToPosition.ContainsKey(hitTag))
                {
                    targetPosition = tagToPosition[hitTag];
                }
            }
        }
    }
}

关键改进点

  • 分离点击逻辑和移动逻辑:点击仅设置目标位置,移动逻辑在每帧Update中执行,保证持续平滑移动
  • 使用Dictionary替代大量重复的if判断,让代码更简洁易维护
  • 初始时将targetPosition设为物体当前位置,避免初始状态下的不必要移动

内容的提问来源于stack exchange,提问作者Eski Stoj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:50:27