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

Я новичок в новой системе ввода 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;
    }

}

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

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 для открытия/закрытия функции. это не сработало для меня, но я не знаю, как это исправить. пожалуйста помоги.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
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

пришлите мне свои коды на ([email protected]), если ваша проблема не решится.

KiynL 17.05.2022 14:36

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

Okashi 17.05.2022 14:43

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

Okashi 17.05.2022 15:48

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