unity使用input system实现相机屏幕手势丝滑拖拽

input action设置

操作对象设置

camera

具体操作类

PlayerInputView类

csharp 复制代码
using System.Collections;
using UnityEngine;
using UnityEngine.InputSystem;
using TouchPhase = UnityEngine.InputSystem.TouchPhase;

public class FingerScale : MonoBehaviour
{
    private Vector3 _offset;
    [SerializeField] private Camera mainCamera;
    private Vector2 _firstTouchPosition;
    private Vector2 _firstTouchStartPosition;
    private Vector3 _firstTouchStartPositionToWorld;
    private Vector2 _secondTouchPosition;
    private Vector2 _secondTouchStartPosition;

    public void OnFirstTouch(InputAction.CallbackContext context)
    {
        Debug.Log("OnFirstTouch"+context.phase);
        _firstTouchStartPosition = context.ReadValue<Vector2>();
        _firstTouchStartPositionToWorld = mainCamera.ScreenToWorldPoint(_firstTouchStartPosition);
       
    }

    public void OnTap(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            Vector3 worldPosition = new Vector3(_firstTouchStartPositionToWorld.x, 
                _firstTouchStartPositionToWorld.y, -20f);
            StartCoroutine(MoveSmooth(worldPosition));
        }
    }

    public void OnFirstPosition(InputAction.CallbackContext context)
    {
        _firstTouchPosition = context.ReadValue<Vector2>();
        Debug.Log("onFirstPosition"+context.phase);
    }

    public void OnFirstMove(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
           _offset = mainCamera.ScreenToWorldPoint(_firstTouchPosition)-_firstTouchStartPositionToWorld;
           Debug.Log("_offset"+_offset);
            mainCamera.transform.position -= _offset;
        }
    }

    
    IEnumerator MoveSmooth(Vector3 targetPosition)
    {
        Vector3 start = mainCamera.transform.position;
        Vector3 speed = Vector3.zero;
        while (Vector3.Distance(start, targetPosition) > 0.001f)
        {
            mainCamera.transform.position = Vector3.SmoothDamp(start, targetPosition, ref speed, 0.3f);
            start = mainCamera.transform.position;
            yield return new WaitForEndOfFrame();
        }
        mainCamera.transform.position = targetPosition;
    }
    
}

出现的问题相机位置变化后通过screenToWorldPoint获取的位置和上一帧的位置,坐标系完全不一样

如何解决:改变相机位置后再通过screentoworldpoint 修改上一帧的位置,实现丝滑拖拽

新解决:根本不需要更新lastframpos ,只需每次触发更新当前位置就可以了。因为改变相机位置后再通过screentoworldpoint 修改上一帧的位置,这一计算的结果在每一帧都一样,都是初始点击的位置。想想也确实如此。因为实现丝滑的拖拽就是要让屏幕触摸的位置相对与地图来说完全不变。在第一次接触时获取这个lastframepos的值就可以了。

ps;使用了近10多个小时才解决,不过收获颇丰。不过在input action中仍存在优化空间一个是状态机优化,一个是input action接收端接受过于冗余不利于扩展

相关推荐
gxgldyh几秒前
Android Framework源码解析(六):Launcher3 启动流程详解——AMS 如何拉起系统桌面?
android
XiaoLeisj1 分钟前
HandlerThread 与 IntentService 使用及源码解析
android·handler
2601_9574188026 分钟前
从 Demo 到商用:一个照片直播系统的 Android 相机连接实践
数码相机
我命由我123459 小时前
Android Studio - Android Studio 自定义预览尺寸
android·java·ide·java-ee·android studio·android-studio·android runtime
取个名字太难了~12 小时前
越用越便宜,越用越强大:影像 SDK 的边际成本递减与网络效应实践
android·数码相机·美颜·相机连接·demu
双翌视觉12 小时前
晶圆光刻对准系统:半导体制造中的精准对位艺术
数码相机·制造
AFinalStone15 小时前
Android 7系统网络(四)Native层(下)—netd Controller详解
android·网络
爱笑鱼16 小时前
Handler(一):post 之后,Runnable 到底在哪个线程执行?
android
木木子2216 小时前
[特殊字符] 音乐播放器——状态驱动的多媒体控制
android·开发语言·华为·php·harmonyos
雨白17 小时前
C 语言基础:结构体、联合体与枚举
android