美文网首页
Unity中,触屏控制相机

Unity中,触屏控制相机

作者: 全新的饭 | 来源:发表于2023-06-24 16:00 被阅读0次

功能

单指滑屏控制相机移动
双指滑屏控制相机视野缩放

原理

借助Input.GetTouch,在正确的时机发出6个事件:

  1. 单指按下、滑动、抬起
  2. 双指按下、滑动、抬起
单指滑动控制相机移动

在 单指按下 时:记录当前位置,进入 控制移动状态。

在 单指移动 时:若此时处于 控制移动状态,将当前位置与前一位置做差获得向量,让相机基于该向量进行移动。

在 单指抬起、双指按下滑动抬起时:退出 控制移动状态。

双指滑动控制相机移动

在 双指按下 时:记录当前两指位置的距离,作为本次的标准距离。

在 双指移动 时:将当前两指位置的距离与标准距离做差,算得应缩放的值。

代码

TouchSys.cs
在合适的时机发出各事件。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchSys : MonoBehaviour
{
    public event Action<Vector2> SingleTouchBeginEvent;
    public event Action<Vector2> SingleTouchMoveEvent;
    public event Action<Vector2> SingleTouchEndEvent;

    public event Action<Vector2,Vector2> DoubleTouchBeginEvent;
    public event Action<Vector2,Vector2> DoubleTouchMoveEvent;
    public event Action<Vector2,Vector2> DoubleTouchEndEvent;

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }
    
    private void OnDestroy()
    {
        MyDestroy();
    }
    
    private void Init()
    {
        
    }

    private void MyUpdate()
    {
        if (Input.touchCount == 1)
        {
            if (Input.GetTouch(0).phase == TouchPhase.Began)
            {
                SingleTouchBeginEvent?.Invoke(Input.GetTouch(0).position);
            }
            else if (Input.GetTouch(0).phase == TouchPhase.Moved)
            {
                SingleTouchMoveEvent?.Invoke(Input.GetTouch(0).position);
            }
            else if (Input.GetTouch(0).phase == TouchPhase.Ended)
            {
                SingleTouchEndEvent?.Invoke(Input.GetTouch(0).position);
            }
        }
        else if (Input.touchCount == 2)
        {
            Vector2 pos0 = Input.GetTouch(0).position;
            Vector2 pos1 = Input.GetTouch(1).position;

            if (Input.GetTouch(1).phase == TouchPhase.Began)
            {
                DoubleTouchBeginEvent?.Invoke(pos0,pos1);
            }
            else if (Input.GetTouch(0).phase == TouchPhase.Moved || Input.GetTouch(1).phase == TouchPhase.Moved)
            {
                DoubleTouchMoveEvent?.Invoke(pos0,pos1);
            }
            else if (Input.GetTouch(0).phase == TouchPhase.Ended || Input.GetTouch(1).phase == TouchPhase.Ended)
            {
                DoubleTouchEndEvent?.Invoke(pos0,pos1);
            }
        }
    }
    
    private void MyDestroy()
    {
        
    }
}

MoveCamCtrOnMobile.cs
在合适的时机控制相机移动。


image.png
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveCamCtrOnMobile : MonoBehaviour
{
    private TouchSys _touchSys;
    private CamCtrSys _camCtrSys;
    [SerializeField]
    private float _moveSpeedFactor = 1;

    private Vector2 _lastPos;
    private Vector2 _curPos;

    private bool _isInMoveCtrState;
    private bool IsInMoveCtrState{get{return _isInMoveCtrState;}}

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }
    
    private void OnDestroy()
    {
        MyDestroy();
    }
    
    private void Init()
    {
        ExitMoveCtrState();
        _camCtrSys = FindObjectOfType<CamCtrSys>();
        _touchSys = FindObjectOfType<TouchSys>();
        _touchSys.SingleTouchBeginEvent += OnSingleTouchBegin;
        _touchSys.SingleTouchMoveEvent += OnSingleTouchMove;
        _touchSys.SingleTouchEndEvent += OnSingleTouchEnd;
        _touchSys.DoubleTouchBeginEvent += OnDoubleTouchBegin;
        _touchSys.DoubleTouchMoveEvent += OnDoubleTouchMove;
        _touchSys.DoubleTouchEndEvent += OnDoubleTouchEnd;
    }

    private void MyUpdate()
    {
        
    }
    
    private void MyDestroy()
    {
        _touchSys.SingleTouchBeginEvent -= OnSingleTouchBegin;
        _touchSys.SingleTouchMoveEvent -= OnSingleTouchMove;
        _touchSys.SingleTouchEndEvent -= OnSingleTouchEnd;
        _touchSys.DoubleTouchBeginEvent -= OnDoubleTouchBegin;
        _touchSys.DoubleTouchMoveEvent -= OnDoubleTouchMove;
        _touchSys.DoubleTouchEndEvent -= OnDoubleTouchEnd;
        _touchSys = null;
        _camCtrSys = null;
    }

    private void OnSingleTouchBegin(Vector2 pos)
    {
        _lastPos = pos;
        EnterMoveCtrState();
    }
    private void OnSingleTouchMove(Vector2 pos)
    {
        if (IsInMoveCtrState)
        {
            _curPos = pos;
            _camCtrSys.Move((_curPos - _lastPos)*_moveSpeedFactor * _camCtrSys.CameraZoomSize);
            _lastPos = _curPos;
        }
    }
    private void OnSingleTouchEnd(Vector2 pos)
    {
        ExitMoveCtrState();
    }
    private void OnDoubleTouchBegin(Vector2 pos0, Vector2 pos1)
    {
        ExitMoveCtrState();
    }
    private void OnDoubleTouchMove(Vector2 pos0, Vector2 pos1)
    {
        ExitMoveCtrState();
    }
    private void OnDoubleTouchEnd(Vector2 pos0, Vector2 pos1)
    {
        ExitMoveCtrState();
    }

    private void EnterMoveCtrState()
    {
        _isInMoveCtrState = true;
    }
    private void ExitMoveCtrState()
    {
        _isInMoveCtrState = false;
    }
}

ZoomCamCtrOnMobile.cs
在合适的时机调整相机视野大小。


image.png
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ZoomCamCtrOnMobile : MonoBehaviour
{
    private TouchSys _touchSys;
    private CamCtrSys _camCtrSys;
    [SerializeField]
    private float _zoomSpeedFactor = 1;

    private float _curStandardLength;

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }
    
    private void OnDestroy()
    {
        MyDestroy();
    }
    
    private void Init()
    {
        _camCtrSys = FindObjectOfType<CamCtrSys>();
        _touchSys = FindObjectOfType<TouchSys>();
        _touchSys.DoubleTouchBeginEvent += OnDoubleTouchBegin;
        _touchSys.DoubleTouchMoveEvent += OnDoubleTouchMove;
    }

    private void MyUpdate()
    {
        
    }
    
    private void MyDestroy()
    {
        _touchSys.DoubleTouchBeginEvent -= OnDoubleTouchBegin;
        _touchSys.DoubleTouchMoveEvent -= OnDoubleTouchMove;
        _touchSys = null;
        _camCtrSys = null;
    }

    private void OnDoubleTouchBegin(Vector2 pos0, Vector2 pos1)
    {
        _curStandardLength = Vector2.Distance(pos0, pos1);
    }
    private void OnDoubleTouchMove(Vector2 pos0, Vector2 pos1)
    {
        float curLength = Vector2.Distance(pos0, pos1);
        float curOffset = curLength - _curStandardLength;
        _camCtrSys.ZoomByOffset(curOffset * _zoomSpeedFactor);
    }
}

CamCtrSys.cs
相机参数(位置、视野大小)控制。

using System.Transactions;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CamCtrSys : MonoBehaviour
{
    [SerializeField]
    private Transform _camTrans;
    [SerializeField]
    private Camera _cam;
    [SerializeField]
    private Vector2 _zoomRange;

    private MapGenerator _mapGenerator;
    public float CameraZoomSize
    {
        get{return _cam.orthographicSize;}
    }

    private void Start()
    {
        Init();
    }

    private void Update()
    {
        MyUpdate();
    }
    
    private void OnDestroy()
    {
        MyDestroy();
    }
    
    private void Init()
    {
        _mapGenerator = FindObjectOfType<MapGenerator>();
        _mapGenerator.GenerateMapEvent += OnGenerateMap;
    }

    private void MyUpdate()
    {
        
    }
    
    private void MyDestroy()
    {
        _mapGenerator.GenerateMapEvent-= OnGenerateMap;
        _mapGenerator = null;
    }

    public void SetPos(Vector2 pos)
    {
        _camTrans.position = new Vector3(pos.x, _camTrans.position.y, pos.y);
    }

    public void Move(Vector2 offset)
    {
        var lastPos = new Vector2(_camTrans.position.x, _camTrans.position.z);
        var newPos = lastPos + offset;
        SetPos(newPos);
    }

    private void OnGenerateMap(Vector2Int size, Vector2 centerPos)
    {
        SetPos(centerPos);
    }

    // v表示比例:0~1
    public void ZoomByRatio(float v)
    {
        _cam.orthographicSize = _zoomRange.x+(_zoomRange.y-_zoomRange.x)*Mathf.Clamp01(v);
    }

    public void ZoomByOffset(float offset)
    {
        _cam.orthographicSize = Mathf.Clamp(_cam.orthographicSize + offset, _zoomRange.x, _zoomRange.y);
    }
}

相关文章

网友评论

      本文标题:Unity中,触屏控制相机

      本文链接:https://www.haomeiwen.com/subject/yyebydtx.html