Unity学习90天-第3天-认识触屏输入(手游基础)并完成手机点击屏幕,物体向点击位置移动

一、什么是触屏输入?

手机游戏没有鼠标和键盘,玩家唯一的输入设备就是手指。

Unity 把每一次手指触碰屏幕,封装成一个叫做 Touch 的结构体。

Touch 记录了三个核心信息:

  • position 触点位置(手指在屏幕哪里)
  • phase 触摸阶段(手指现在处于什么状态)
  • deltaPosition 移动量(这一帧手指移动了多少)

可以把 Touch 理解为"手指的档案",每根手指有自己的一份档案,随时更新。

二、两个最常用的 API

在 Update() 里,我们用这两个 API 获取触摸信息:

复制代码
Input.touchCount           // 当前屏幕上有几根手指
Input.GetTouch(index)      // 获取第 index 根手指的 Touch 数据

touchCount 就像数人头------你得先知道"有没有人",再去拿数据。

GetTouch(0) 中的 0 是索引,代表第一根手指(和数组一样,从0开始)。

三、TouchPhase------触摸的五个阶段

这是触屏输入里最重要的概念。

每根手指在屏幕上的生命周期分为五个阶段:

阶段 英文枚举 触发时机
按下 TouchPhase.Began 手指刚放上去的那一帧
移动 TouchPhase.Moved 手指在移动的每一帧
静止 TouchPhase.Stationary 手指按着但没动
抬起 TouchPhase.Ended 手指离开屏幕的那一帧
中断 TouchPhase.Canceled 来电话等系统打断

类比:就像开门的过程------推门(Began)→ 门在动(Moved)→ 门停住(Stationary)→ 门关上(Ended)

四、Touch 结构体详解

复制代码
Touch touch = Input.GetTouch(0);

touch.fingerId        // 手指的唯一编号(区分哪根手指)
touch.position        // 屏幕像素坐标,Vector2,左下角是(0,0)
touch.deltaPosition   // 本帧相对上一帧的位移,Vector2
touch.phase           // 当前所处阶段(见上表)
touch.tapCount        // 连续点击次数(单击=1,双击=2)

position 的坐标系是这样的:

(0, 1080)------------------------(1920, 1080)

屏幕中心

(0, 0)---------------------------(1920, 0)

注意:触摸坐标原点在左下角,和 Unity UI 的锚点方向一致。

五、脚本实现------点击检测

那么我们手机触屏的基本知识就已经学完啦,接下来我们来运用知识进行实现脚本吧!

目标:手指点下屏幕时,打印触点的屏幕坐标。

复制代码
using UnityEngine;

public class TapDemo : MonoBehaviour
{
    void Update()
    {
        // 第一步:先判断有没有手指在屏幕上
        if (Input.touchCount > 0)
        {
            // 第二步:取第一根手指的数据
            Touch touch = Input.GetTouch(0);

            // 第三步:只在"按下的那一帧"响应
            if (touch.phase == TouchPhase.Began)
            {
                Debug.Log("点击位置:" + touch.position);
            }
        }
    }
}

为什么要判断 TouchPhase.Began?

因为手指放在屏幕上不动,Update() 每帧都会执行。如果不判断 Began,只要手指还按着,就会每帧都打印------这不是我们想要的"点击"效果。

Began 只在放下的那一帧为 true,之后变成 Stationary 或 Moved,所以只会触发一次。

六、脚本实现------点击位置移动

6.1 实现思路拆解

在动手写代码之前,先把这个功能拆解成几个小问题:

  1. 手指点击屏幕 → 获取屏幕坐标(2D像素坐标)
  2. 屏幕坐标 → 转换成世界坐标(3D空间位置)
  3. 物体当前位置 → 平滑移动到目标位置

最关键的一步是第2步------屏幕坐标和世界坐标不是一回事:

坐标类型 单位 示例
屏幕坐标(touch.position) 像素 (540, 960)
世界坐标(物体 Transform) Unity单位 (2.3f, 0, -1.5f)

Unity 提供了转换函数:Camera.main.ScreenToWorldPoint(),帮我们完成这个换算。

6.2 ScreenToWorldPoint------屏幕转世界坐标

复制代码
Camera.main.ScreenToWorldPoint(Vector3 position)

参数说明:

参数 类型 说明
position.x float 触点的屏幕 x 坐标
position.y float 触点的屏幕 y 坐标
position.z float 距相机的深度,必须手动指定

为什么需要 z?因为相机把 3D 世界"拍扁"成了 2D 屏幕,丢失了深度信息。z 就是告诉 Unity:"我要的那个点,在相机前方多远的平面上?"

z 值怎么填?

把物体当前离相机的距离赋给 z,这样转换出来的世界坐标就和物体在同一个深度平面上。

复制代码
// 先算出物体离相机有多远
float distToCamera = Vector3.Distance(transform.position, Camera.main.transform.position);

// 再传给 ScreenToWorldPoint
Vector3 worldPos = Camera.main.ScreenToWorldPoint(
    new Vector3(touch.position.x, touch.position.y, distToCamera)
);

6.3 平滑移动------Vector3.MoveTowards

移动到目标点有两种常见方式:

方式 函数 效果
匀速移动 Vector3.MoveTowards 全程速度一致,到达即停
缓动移动 Vector3.Lerp 越接近目标越慢,丝滑感

在这里我使用 MoveTowards,更适合"点哪走哪"的手游操控感:

复制代码
transform.position = Vector3.MoveTowards(
    transform.position,   // 当前位置
    targetPos,            // 目标位置
    speed * Time.deltaTime // 每帧移动距离
);
  • transform.position:物体当前所在位置
  • targetPos:我们想让它去的位置(点击处)
  • speed * Time.deltaTime:每帧最多走多远(乘以 deltaTime 保证帧率无关)

6.4 脚本总结

在这里我将展示完整的代码给大家以供参考:

复制代码
using UnityEngine;

public class ClickMoveDemo : MonoBehaviour
{
    public float speed = 5f;          // 移动速度
    private Vector3 targetPos;        // 目标位置

    void Start()
    {
        // 初始目标位置就是自身位置(防止一开始就乱跑)
        targetPos = transform.position;
    }

    void Update()
    {
        HandleInput();    // 第一步:处理输入,更新目标点
        MoveToTarget();   // 第二步:每帧向目标点靠近
    }

    // ── 输入处理 ──────────────────────────────
    void HandleInput()
    {
#if UNITY_EDITOR
        // 编辑器里用鼠标左键模拟点击
        if (Input.GetMouseButtonDown(0))
        {
            SetTargetFromScreen(Input.mousePosition);
        }
#else
        // 真机上用触摸
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            SetTargetFromScreen(Input.GetTouch(0).position);
        }
#endif
    }

    // ── 屏幕坐标 → 世界坐标 → 更新目标点 ─────
    void SetTargetFromScreen(Vector2 screenPos)
    {
        // 用物体到相机的距离作为深度值
        float distToCamera = Vector3.Distance(
            transform.position,
            Camera.main.transform.position
        );

        // 屏幕坐标转世界坐标
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(
            new Vector3(screenPos.x, screenPos.y, distToCamera)
        );

        // 保持 y 轴不变(物体在地面上,不要飞起来或陷地里)
        worldPos.y = transform.position.y;

        targetPos = worldPos;
        Debug.Log("新目标点:" + targetPos);
    }

    // ── 每帧向目标位置移动 ────────────────────
    void MoveToTarget()
    {
        transform.position = Vector3.MoveTowards(
            transform.position,
            targetPos,
            speed * Time.deltaTime
        );
    }
}

七、在编辑器里怎么测试?

真机触屏没法在 PC 编辑器里直接测,用下面这段代码可以一套脚本,编辑器用鼠标,手机用触摸,自动切换:

复制代码
void Update()
{
#if UNITY_EDITOR
    // 编辑器中用鼠标模拟
    if (Input.GetMouseButtonDown(0))
    {
        Debug.Log("【编辑器】点击:" + Input.mousePosition);
    }
#else
    // 真机上用触摸
    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
    {
        Debug.Log("【真机】点击:" + Input.GetTouch(0).position);
    }
#endif
}

#if UNITY_EDITOR 是预编译指令 ,Unity 打包到手机时,UNITY_EDITOR 那段代码会被自动剔除,只保留触摸部分。

八、总结

下面我将总结本章的关键函数为表给大家

功能 关键代码
检测有无触摸 Input.touchCount > 0
点击瞬间 touch.phase == TouchPhase.Began
抬起瞬间 touch.phase == TouchPhase.Ended
滑动方向 Ended时 (终点 - 起点)
坐标转世界坐标 Camera.main.ScreenToWorldPoint()

**今天的教学就到这里!**接下来我将连续更新90天的Untiy教程从基础到一个网络部分,有兴趣的朋友们可以收藏关注,谢谢!如果有疑问,评论区见。

成果展示

由于不是真机测试这个博主用的是鼠标模拟屏幕点击,忘记的可以回看Unity学习90天-第2天-认识键盘 / 鼠标输入(PC)并实现WASD 移动,鼠标控制物体转向https://blog.csdn.net/qq_57101277/article/details/160084017?spm=1001.2014.3001.5501

相关推荐
夏天的清晨5 小时前
C++入门学习
开发语言·c++·学习
传奇开心果编程5 小时前
【ArkUI进阶练中学】第18课:Agent亲和架构与应用智能化改造
学习·ui·华为·harmonyos
代码山河5 小时前
Java的前世今生:从Oak语言到Java 23的发展史
java·学习·架构·教程·面向对象·项目
一木 之林5 小时前
《OpenAI库基础学习总结:Client 初始化、流式输出 delta 拼接与多轮历史 messages 全流程拆解》
人工智能·学习·计算机视觉·stable diffusion·aigc
m4Rk_5 小时前
【论文阅读】Agent 记忆机制(90):HyperMem——用超图建模长期记忆中的高阶关联
论文阅读·人工智能·学习·开源·github
星恒随风5 小时前
Linux开发工具详解(二):Git版本控制、GitHub协作与GDB调试实战
linux·笔记·git·学习·github
QQ_21696290966 小时前
基于C#(Asp.net)电竞陪玩信息管理系统的设计与实现
java·大数据·spring boot·微信小程序·c#·云计算·asp.net
未来之窗软件服务15 小时前
C# 截图源码支持自动保存-东方仙盟
c#·仙盟创梦ide·东方仙盟·电脑工具
青柠之夏cc16 小时前
AI与教育:个性化学习助手让“因材施教“成为现实,但代价是隐私?
人工智能·学习
for_ever_love__17 小时前
机器学习入门——手写线性回归与梯度下降
人工智能·python·学习·机器学习·线性回归