在 Unity 中通过屏幕触摸控制移动 Cinemachine 摄像机

问题描述 投票:0回答:1

我正在为 Android 制作统一的第三人称射击游戏,这是我第一次从事触摸控制工作,因此在 YouTube 视频的帮助下,我能够使用 On_Screen Stick 和 On_Screen Button 按钮制作虚拟操纵杆和按钮以及新的统一输入处理运动和所有其他东西的系统。

所以我想要是屏幕触摸来控制摄像机运动,特别是电影机摄像机运动来环顾四周,因此我尝试搜索另一个YouTube视频来创建一个特定的触摸区域,我可以在其中使用触摸控件将值提供给垂直和水平方向电影机摄像机的轴,但我找不到类似的东西。如何制作特定区域,触摸可以让我的电影机摄像机环顾四周,并且如果我触摸操纵杆,摄像机移动的触摸场不受影响?

注意:我的电影机摄像机是虚拟摄像机,带有瞄准 POV 组件来环顾四周,我已经编写了代码以沿摄像机方向旋转我的播放器,所以我需要的只是通过触摸触摸场来移动我的摄像机,正如我所说以前我使用新的输入系统,但我也使用旧的输入系统,所以两者都可以工作,但我主要有新的输入系统控件,并且更喜欢使用它们,我不需要另一个操纵杆来移动我的相机,我使用了空图像制作触摸场的组件。

PS:如果有人可以修复任何错误或提供建议,我将不胜感激,因为我是 Android 游戏开发和统一的新手。

我确实尝试要求聊天 GPT 为我制作一个确实有效的脚本,但它没有什么问题,比如当我触摸我的移动操纵杆时,它也在移动我的相机,我无法同时移动操纵杆和相机,而且还有一些问题当我按下其他按钮(例如开火按钮)时,即使它们不在触摸区域上,也会突然发生触摸事件,就像相机突然移动一样。

这是我从聊天 GPT 中获得的代码


using UnityEngine;
using UnityEngine.EventSystems;

public class TouchField : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
    [HideInInspector]
    public Vector2 TouchDist;
    [HideInInspector]
    public bool Pressed;

    private RectTransform rectTransform; // Reference to the RectTransform component

    private Vector2 previousTouchPos; // Store the previous touch position

    // Use this for initialization
    void Start()
    {
        // Get the RectTransform component of the image field
        rectTransform = GetComponent<RectTransform>();
    }

    // Update is called once per frame
    void Update()
    {
        // Check if there is only one active touch
        if (Input.touchCount == 1)
        {
            Touch touch = Input.GetTouch(0);

            // Check if the touch is within the bounds of the RectTransform
            if (RectTransformUtility.RectangleContainsScreenPoint(rectTransform, touch.position))
            {
                if (touch.phase == TouchPhase.Moved || touch.phase == TouchPhase.Stationary)
                {
                    if (Pressed)
                    {
                        // Calculate the distance from the previous touch position
                        TouchDist = touch.position - previousTouchPos;
                        previousTouchPos = touch.position;
                    }
                    else
                    {
                        // Initialize the previous touch position
                        previousTouchPos = touch.position;
                        Pressed = true;
                    }
                }
                else
                {
                    // Reset when touch is not moving or released
                    Pressed = false;
                    TouchDist = Vector2.zero;
                }
            }
            else
            {
                // Reset when touch is outside the bounds
                Pressed = false;
                TouchDist = Vector2.zero;
            }
        }
        else
        {
            // Reset when there are no active touches
            Pressed = false;
            TouchDist = Vector2.zero;
        }
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        // Handle pointer down event if needed
    }

    public void OnPointerUp(PointerEventData eventData)
    {
        // Handle pointer up event if needed
    }
}

我像这样设置 cinemachine 的值

povComponent.m_HorizontalAxis.Value += touchField.TouchDist.x * SensitivityX * Time.deltaTime;
povComponent.m_VerticalAxis.Value -= touchField.TouchDist.y * SensitivityY * Time.deltaTime;
c# unity-game-engine controls touch cinemachine
1个回答
0
投票

所以,是的,我自己能够弄清楚,如果有人想知道我是如何做到的,这里是代码,这是使用全新的输入系统,并且不使用触摸字段或任何类型的东西,这意味着触摸正在发生在所有屏幕上,但它将避免使用事件系统的所有 UI 按钮。您需要添加事件系统和新的输入系统名称空间才能使其工作,aimPov1和aimPov2这里是cinemachine虚拟相机目标POV组件参考,您可以在启动方法中获取它,原因有两个是因为我使用两个Cinemachine 如果您想要一个 cam,那么您可以删除 IF 和 Else 语句,其中我正在检查 cam 1 是否处于活动状态,您也可以删除检查,因为这是我在我的场景中想要的,您也可以使用其他 Cinemachine 摄像机。

 if (Touchscreen.current.touches.Count == 0)
        return;

    if (EventSystem.current.IsPointerOverGameObject(Touchscreen.current.touches[0].touchId.ReadValue()))
    {
        if (Touchscreen.current.touches.Count > 1 && Touchscreen.current.touches[1].isInProgress)
        {
            if (EventSystem.current.IsPointerOverGameObject(Touchscreen.current.touches[1].touchId.ReadValue()))
                return;

            Vector2 touchDeltaPosition = Touchscreen.current.touches[1].delta.ReadValue();
            if (_cam1.gameObject.activeSelf == true)
            {
                aimPOV1.m_VerticalAxis.Value -= touchDeltaPosition.y * _touchSensitivityY;
                aimPOV1.m_HorizontalAxis.Value += touchDeltaPosition.x * _touchSensitivityX;
            }
            else
            {
                aimPOV2.m_VerticalAxis.Value -= touchDeltaPosition.y * _touchSensitivityY;
                aimPOV2.m_HorizontalAxis.Value += touchDeltaPosition.x * _touchSensitivityX;
            }

        }
    }
    else
    {
        if (Touchscreen.current.touches.Count > 0 && Touchscreen.current.touches[0].isInProgress)
        {
            if (EventSystem.current.IsPointerOverGameObject(Touchscreen.current.touches[0].touchId.ReadValue()))
                return;

            Vector2 touchDeltaPosition = Touchscreen.current.touches[0].delta.ReadValue();
            if (_cam1.gameObject.activeSelf == true)
            {
                aimPOV1.m_VerticalAxis.Value -= touchDeltaPosition.y * _touchSensitivityY;
                aimPOV1.m_HorizontalAxis.Value += touchDeltaPosition.x * _touchSensitivityX;
            }
            else
            {
                aimPOV2.m_VerticalAxis.Value -= touchDeltaPosition.y * _touchSensitivityY;
                aimPOV2.m_HorizontalAxis.Value += touchDeltaPosition.x * _touchSensitivityX;
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.