Home > Enterprise >  Handling different functions calls using New Input System
Handling different functions calls using New Input System

Time:05-18

I'm new to Unity New Input System, I have recently migrated my project from the old input system to the new input system but I'm facing some difficulties using it.

I have a class called InputManager that manages all the input actions for my game, and another class called PlayerInteractions that holds all the player's interactions, such as picking up objects, opening and closing drawers/doors and so on.

playerInteraction class was working perfectly using the old input system, but when I changed it to the new input system I couldn't handle the function calls properly so it didn't work completely. I managed to make picking up objects work but the opening/closing part didn't work because for that I'm calling another function from a class called InteractiveObjects that is attached to all objects that can be opened/closed such as door/drawers...

and it was hard for me to handle these function calls since I'm not good enough at the New Input System.

Here is a snippet of the 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;
    }

This part from above:

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

was like this:

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

and the InteractiveObject class was something like this:

 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)) was changed to if (Open).

Here is the full IneractiveObject class after the change:

 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;
    }

}

Here is my Input Action: enter image description here

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


}

So the InputManager class is calling a function from playerInteractions which is also calling a function from InteractiveObjects for opening/closing feature. that didn't work for me but I don't know how to fix this. please help.

CodePudding user response:

The solution is here, you no longer need Open Boolean and you can call the function directly through the new input system. for this job; Enter only the contents of 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; 
    } 
}

This not only simplifies the structure of the code. Rather, it prevents the if condition from being repeated in the update. Now run OnOpen as you set it by pressing the B key:

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

How do conditions work continuously?

There are several ways to build functions that work continuously. This is an example that works by defining Func<bool> in the target object script:

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

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

And it is enough to set the function according to the result of key pressing:

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

Hope this answer is comprehensive and practical.

  • Related