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接收端接受过于冗余不利于扩展

相关推荐
胖虎130 分钟前
Android 布局系列(五):GridLayout 网格布局的使用
android·网格布局·安卓布局·gridlayout
云泽野1 小时前
Pytest之parametrize参数化
android·python·pytest
野有蔓草W2 小时前
Android实现漂亮的波纹动画
android·java
万户猴3 小时前
【Flow进阶篇一】SharedFlow 入门:冷流 vs. 热流的区别与基础用法
android·kotlin
万户猴3 小时前
【Flow进阶篇二】SharedFlow 缓存机制深度解析
android·kotlin·android jetpack
Summer_34163 小时前
Unity学习笔记之——ugui的性能优化
笔记·学习·unity
李大圣的博客3 小时前
使用binlog2sql来恢复mysql误删除数据
android
奥顺4 小时前
PHP函数与类:面向对象编程实践指南
android·开发语言·mysql·开源·php
向上的车轮5 小时前
40岁开始学Java:Java中单例模式(Singleton Pattern),适用场景有哪些?
android·java·单例模式
Nicole Potter5 小时前
请说明字符串中 string str = null string str = ““ string str = string.Empty 三者的区别
游戏·unity·面试·c#