Обработка вызовов различных функций с использованием новой системы ввода

Я новичок в новой системе ввода Unity, недавно я перенес свой проект со старой системы ввода на новую систему ввода, но столкнулся с некоторыми трудностями при ее использовании.

У меня есть класс под названием InputManager, который управляет всеми действиями ввода для моей игры, и еще один класс под названием PlayerInteractions, который содержит все взаимодействия игрока, такие как сбор предметов, открытие и закрытие ящиков/дверей и так далее.

playerInteraction класс отлично работал со старой системой ввода, но когда я перешел на новую систему ввода, я не мог правильно обрабатывать вызовы функций, поэтому он не работал полностью. Мне удалось заставить работать сбор объектов, но часть открытия/закрытия не работала, потому что для этого я вызываю другую функцию из класса с именем InteractiveObjects, которая прикреплена ко всем объектам, которые можно открывать/закрывать, например, двери/ящики. ..

и мне было трудно обрабатывать эти вызовы функций, так как я недостаточно хорошо разбираюсь в новой системе ввода.

Вот фрагмент PlayerInteractions Class

private InteractiveObjects interactiveObjects;
    bool PickingUp, Open;
  void Update()
    {
        raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
        RaycastHit hit;
        if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
        {
            lookObject = hit.collider.transform.gameObject;
        }
        else
        {
            lookObject=null;
        }

        if (PickingUp) 
        {
            if (currentlyPickedUpObject == null)
            {
                if (lookObject != null)
                {

                    PickupObject();
                }
            }
            else
            {
                
                BreakConnection();
            }
        }
        PickingUp = false;
        if (hit.transform)
        {
            interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
        }
        else
        {
            lookObject = null;
            interactiveObjects = null;
        }
        if (Open)
        {
            if (interactiveObjects)
            {               
                interactiveObjects.PerformAction();

            }
        }
        Open = false;
    }
    public void OnPickingUp() 
    {
        PickingUp = true;
    }
    public void OnOpen()
    {
        Open = true;
    }

Эта часть сверху:

 if (Open)
            {
                if (interactiveObjects)
                {               
                    interactiveObjects.PerformAction();
    
                }
            }

было так:

if (Input.GetKeyDown(KeyCode.E))
        {
            if (interactiveObjects)
            {
                interactiveObjects.PerformAction();
            }
        }

а класс InteractiveObject был примерно таким:

 public void PerformAction()
    {
        if (aSource) 
        {
            aSource.Play(); 
        }
        if (Input.GetKeyDown(KeyCode.E))
        {
            if (isOpen)
            {
                iTweenArgs["position"] = closedPosition;
                iTweenArgs["rotation"] = closedPosition;
            }
            else
            {
                iTweenArgs["position"] = openPosition;
                iTweenArgs["rotation"] = openPosition;
            }

            isOpen = !isOpen;


            switch(movementType)
            {
                case MovementType.Slide:
                    iTween.MoveTo(gameObject, iTweenArgs);
                    break;
                case MovementType.Rotate:
                    iTween.RotateTo(gameObject, iTweenArgs);
                    break; 
            } 
        }

if(Input.GetKeyDown(KeyCode.E)) было изменено на if (Open).

Вот полный класс IneractiveObject после изменения:

 public class InteractiveObjects : MonoBehaviour
    {
        [SerializeField] private Vector3 openPosition, closedPosition;
    
        [SerializeField] private float animationTime;
    
        [SerializeField] private bool isOpen = false;
    
        [SerializeField] private MovementType movementType;
    
        bool Open; 
    private enum MovementType { Slide, Rotate };

    private Hashtable iTweenArgs;

    private AudioSource aSource;

   
    void Start()
    {
        iTweenArgs = iTween.Hash();
        iTweenArgs.Add("position", openPosition);
        iTweenArgs.Add("time", animationTime);
        iTweenArgs.Add("islocal", true);

        aSource = GetComponent<AudioSource>();
    }

    public void PerformAction()
    {
        if (aSource)
        {
            aSource.Play();
        }
        
        if (Open)
        {
            if (isOpen)
            {
                iTweenArgs["position"] = closedPosition;
                iTweenArgs["rotation"] = closedPosition;
            }
            else
            {
                iTweenArgs["position"] = openPosition;
                iTweenArgs["rotation"] = openPosition;
            }

            isOpen = !isOpen;


            switch (movementType)
            {
                case MovementType.Slide:
                    iTween.MoveTo(gameObject, iTweenArgs);
                    break;
                case MovementType.Rotate:
                    iTween.RotateTo(gameObject, iTweenArgs);
                    break;
            }
        }
        Open = false;
        

    }

    public void OnOpen()
    {
        
        Open = true;
    }

}

Вот мое действие ввода: enter image description here

InputManager класс:

public class InputManager : MonoBehaviour
{
    [SerializeField] Movement movement;
    [SerializeField] PlayerInteractions playerInteractions;
    [SerializeField] MouseLook mouseLook;
    PlayerControls controls; 
    PlayerControls.GroundMovementActions groundMovement;
    Vector2 horizontalInput;
    Vector2 mouseInput;

    private void Awake() 
  {
        controls = new PlayerControls(); 
        groundMovement = controls.GroundMovement;
        // groundMovement.[action].performed += context => do something
        groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
        groundMovement.Jump.performed += _ => movement.OnJumpPressed();
        groundMovement.Running.performed += _ => movement.OnRunning();
        groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
        groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
        groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
        groundMovement.Open.performed += _ => playerInteractions.OnOpen(); 
     
    }   

    private void Update()
    {
        movement.ReceiveInput(horizontalInput);
        mouseLook.ReceiveInput(mouseInput); 
    }

    private void OnEnable()
    {
        controls.Enable(); 
    }

    private void OnDestroy()
    {
        controls.Disable(); 
    }


}

Таким образом, класс InputManager вызывает функцию из playerInteractions, которая также вызывает функцию из InteractiveObjects для открытия/закрытия функции. это не сработало для меня, но я не знаю, как это исправить. пожалуйста помоги.

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
0
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение здесь, вам больше не нужно Open Boolean, и вы можете вызывать функцию напрямую через новую систему ввода. для этой работы; Введите только содержимое if on OnOpen.

public void OnOpen()
{
    if (isOpen)
    {
        iTweenArgs["position"] = closedPosition;
        iTweenArgs["rotation"] = closedPosition;
    }
    else
    {
        iTweenArgs["position"] = openPosition;
        iTweenArgs["rotation"] = openPosition;
    }

    isOpen = !isOpen;

    switch(movementType)
    {
        case MovementType.Slide:
            iTween.MoveTo(gameObject, iTweenArgs);
            break;
        case MovementType.Rotate:
            iTween.RotateTo(gameObject, iTweenArgs);
            break; 
    } 
}

Это не только упрощает структуру кода. Скорее, это предотвращает повторение условия if в обновлении. Теперь запустите OnOpen, как вы установили, нажав клавишу B:

controls.GroundMovement.Open.performed += _ => playerInteraction.OnOpen();

Как условия работают постоянно?

Существует несколько способов создания функций, которые работают непрерывно. Это пример, который работает, определяя Func<bool> в скрипте целевого объекта:

public class PlayerInteraction : MonoBehaviour
{
    public Func<bool> IsPressingOpen;

    public void Update()
    {
        if (IsPressingOpen())
        {
            // do something...
        }
    }
}

И достаточно установить функцию по результату key pressing:

playerInteraction.IsPressingOpen = () => controls.GroundMovement.Open.IsPressed();

Надеюсь, этот ответ будет исчерпывающим и практичным.

Спасибо за ваш ответ. Итак, в первой части ответа я понял, что мне нужно изменить имя функции в классе InteractiveObject на OnOpen(), затем в классе InputManager функция была вызвана из класса PlayerInteractions следующим образом:controls.GroundMovement.Open.performed += _ => playerInteraction.OnOpen(); но вы не упомянули, как вызвать функцию из playerInteraction.

Okashi 17.05.2022 14:15

Я также попробовал часть ответа с булочками, IsPressed(); не определен. и это вызывает ошибки.

Okashi 17.05.2022 14:17

@Okashi Могу я спросить, вы обычно получаете обратный вызов, когда нажимаете клавиши, или какая-либо клавиша не работает, когда вы ее нажимаете?

KiynL 17.05.2022 14:19

Да, вообще все действия в Input Action работают, кроме Open.

Okashi 17.05.2022 14:32

Я думаю, проблема в том, что он никогда не доходит до функции в InteractiveObject из PLayerInteractions. Я попытался напечатать там строку, но она никогда не печатается, поэтому я думаю, что она не дошла до функции должным образом.

Okashi 17.05.2022 14:34

пришлите мне свои коды на (Kian.tianxuan@gmail.com), если ваша проблема не решится.

KiynL 17.05.2022 14:36

Большое спасибо за то, что вы так полезны. Я постараюсь еще немного, чтобы это сработало, если это не так, я пришлю вам. Спасибо еще раз

Okashi 17.05.2022 14:43

Спасибо наконец заработало. В конце концов, проблема была не в коде, а в инспекторе чего-то не хватало!

Okashi 17.05.2022 15:48

Другие вопросы по теме