(已回答)即使“更新模式”设置为“在动态更新中处理事件”,新输入系统在时间刻度 0 下也无法正常工作

(Answered) New Input System not Working at Timescale 0 even when Update Mode is set to "Process Events in Dynamic Update"

提问人:Seboops 提问时间:9/17/2023 最后编辑:Seboops 更新时间:9/19/2023 访问量:72

问:

我一直在学习 Unity 的新输入系统,一切都运行良好,直到时间刻度设置为 0 并且根本没有读取任何输入。我浏览了其他论坛,发现我应该将更新模式设置为“在动态更新中处理事件”,但事实证明这是默认启用的。

我在这里做错了什么吗?还是我错过了什么?

这是我的代码:如果我删除将 Time.Timescale 设置为 0(位于不同位置)的部分,它工作得很好,但即使是我的 Print() 函数也没有任何作用

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

public class QuickMenuScript : MonoBehaviour
{
    public int MenuItemsAmount;
    public float cursorMoveSpeed;


    int cursorPosition;
    float progress;
    public Animator MenuHost;
    public void action(int id)
    {
        Animator animator = GetComponent<Animator>();

        if (id == 0)
        {
            MenuHost.SetBool("Continue", true);
        }
        if (id == 1)
        {
            MenuHost.gameObject.GetComponent<killPlayerFromUI>().kill();
        }
        if (id == 2)
        {
            Application.Quit();
        }
    }
    public void moveCursor(InputAction.CallbackContext context)
    {
        print("moving");
        if (context.performed)
        {
            if (context.ReadValue<float>() != 0)
            {
                if (context.ReadValue<float>() < 0)
                {
                    cursorPosition++;
                }
                else
                {
                    cursorPosition--;
                }
            }

            if (cursorPosition > MenuItemsAmount)
            {
                cursorPosition = 1;
            }
            if (cursorPosition < 1)
            {
                cursorPosition = MenuItemsAmount;
            }
        }
    }

    private void Update()
    {
        Animator animator = GetComponent<Animator>();
        progress = Mathf.MoveTowards(progress,cursorPosition,cursorMoveSpeed*Time.deltaTime);
        animator.SetFloat("Blend",progress);

    }
    public void Submit(InputAction.CallbackContext context)
    {
        print("submitting");
        if(context.performed)
        {
            action(cursorPosition);
        }
    }
    public void Back(InputAction.CallbackContext context)
    {
        if (context.performed)
        {
            MenuHost.SetBool("Continue", true);
        }
    }

    public void timeReturn()
    {
        Time.timeScale = 1;
    }

}

这是我用于此目的的播放器输入组件: 图像

C# unity-game-engine 输入

评论

0赞 derHugo 9/18/2023
你所有的方法都是从哪里调用的?public
0赞 Seboops 9/18/2023
@derHugo 你是说公共空白吗?它们被玩家输入组件调用。我正在使用 Unity Events 方法。它们在时间上工作得很好。时间刻度 !=0,但一旦它为零,我的任何输入都不会被注册。

答:

0赞 Seboops 9/19/2023 #1

我想通了: 事实证明,如果我从使用 UnityEvents 切换到使用 C# 类(并且还切换到使用 Time.UnscaledDeltaTime),它就可以正常工作。

选中“输入操作资产属性”中的“生成 C# 类”框

然后订阅 InputAction.ActionMap.Action.Performed 事件,在创建定义到新 InputAction() 资产的变量后。(确保将 InputAction、ActionMap 和 Action 设置为相应的 Input 操作资产、Action Map 和 Actions 的名称)此外,我还需要制作一个新的 OnDestroy() 函数,该函数在对象被销毁时取消订阅该事件,这样我就不会收到任何错误。

附加说明:首次声明 InputAction 时不要将它分配给新的 InputAction(),而是在 start() 函数中执行。 更新代码:

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

public class QuickMenuScript : MonoBehaviour
{
    public int MenuItemsAmount;
    public float cursorMoveSpeed;

    int cursorPosition;
    float progress;
    public Animator MenuHost;
    RollItGeneralInputs input;

    private void Awake()
    {
        input = new RollItGeneralInputs();

        input.QuickMenu.Enable();
        
        input.QuickMenu.MoveCursor.performed += moveCursor;
        input.QuickMenu.Submit.performed += Submit;
        input.QuickMenu.Back.performed += Back;
        
    }
    public void action(int id)
    {
        if (GetComponent<Animator>() == null) return;

        Animator animator = GetComponent<Animator>();

        if (id == 0)
        {
            MenuHost.SetBool("Continue", true);
        }
        if (id == 1)
        { 
            MenuHost.gameObject.GetComponent<killPlayerFromUI>().kill();
            MenuHost.SetBool("Continue", true);
            
        }
        if (id == 2)
        {
            Application.Quit();
        }
    }
    public void moveCursor(InputAction.CallbackContext context)
    {
        if (!context.performed) return;

        if (context.ReadValue<float>() != 0)
        {
            if (context.ReadValue<float>() < 0)
            {
                cursorPosition++;
            }
            else
            {
                cursorPosition--;
            }
        }

        if (cursorPosition > MenuItemsAmount)
        {
            cursorPosition = 0;
        }
        if (cursorPosition < 0)
        {
            cursorPosition = MenuItemsAmount;
        }

    }
    private void Update()
    {
        Animator animator = GetComponent<Animator>();
        progress = Mathf.MoveTowards(progress,cursorPosition + 1,cursorMoveSpeed*Time.unscaledDeltaTime);
        animator.SetFloat("Blend",progress);

    }

    public void Submit(InputAction.CallbackContext context)
    {
        Debug.Log("submitting " + cursorPosition);
        if (!context.performed) return;

        action(cursorPosition);

    }
    public void Back(InputAction.CallbackContext context)
    {
        print(MenuHost);
        if (!context.performed) return;
        if (MenuHost == null) return;


        input.QuickMenu.MoveCursor.performed -= moveCursor;
        input.QuickMenu.Submit.performed -= Submit;
        input.QuickMenu.Back.performed -= Back;

        print(MenuHost);
        MenuHost.SetBool("Continue", true);

        

    }
    private void OnDestroy()
    {

        input.QuickMenu.MoveCursor.performed -= moveCursor;
        input.QuickMenu.Submit.performed -= Submit;
        input.QuickMenu.Back.performed -= Back;
    }
    public void timeReturn()
    {
        Time.timeScale = 1;
    }

}

另一个注意事项:要订阅活动,只需执行以下操作:

nameOfEvent += NameOfFunctionToCallOnEvent

然后取消订阅就行了

nameOfEvent -= PreviousFunctionYouSubscribedTo

在本例中,nameOfEvent 将为 我们之前执行的 InputAction.ActionMap.Action.Performed 事件。