使用新输入系统处理不同的函数调用

Handling different functions calls using New Input System

我是 Unity 新输入系统的新手,我最近将我的项目从旧输入系统迁移到新输入系统,但我在使用它时遇到了一些困难。

我有一个名为 InputManager 的 class 管理我游戏的所有输入操作,还有另一个名为 PlayerInteractions 的 class 用于保存所有玩家的交互,例如如拾取物品、打开和关闭drawers/doors等。

playerInteraction class 在使用旧输入系统时工作得很好,但是当我将其更改为新输入系统时,我无法正确处理函数调用,因此它无法完全工作.我设法使拾取对象工作,但 opening/closing 部分没有工作,因为为此我从一个名为 InteractiveObjects 的 class 调用另一个函数,该函数附加到所有可以是 opened/closed 例如 door/drawers...

我很难处理这些函数调用,因为我在新输入系统方面不够好。

这是 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 class 是这样的:

 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 class 更改后:

 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 class:

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 class 从 playerInteractions 调用一个函数,它也从 InteractiveObjects 调用一个函数以实现 opening/closing 功能。这对我不起作用,但我不知道如何解决这个问题。请帮助。

解决方案在这里,您不再需要Open布尔值,您可以通过新的输入系统直接调用函数。为了这份工作;仅输入 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 条件在更新中重复出现。现在 运行 OnOpenB 键设置:

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();

希望这个回答全面实用。