Click here to Skip to main content
15,887,248 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
I have this code here that displays a game object when I press E on the keyboard the only issue is it works with the host and nothing happens when the client interacts with it when he presses E. what is the solution or what I'm doing wrong and thx for taking time.

What I have tried:

C#
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

public class InteractiveComputer : NetworkBehaviour
{
    public GameObject computerScreen;
    public float interactionRange = 3f; // Adjust the interaction range as needed
    private float displayDuration = 5f; // Duration to display the computer screen

    private bool isComputerScreenVisible = false;
    private bool isInteracting = false; // Flag to prevent multiple interactions

    private void Start()
    {
        if (IsServer)
        {
            isComputerScreenVisible = false;
            computerScreen.SetActive(false);
        }
    }

    bool IsPlayerInRange()
    {
        foreach (var player in NetworkManager.Singleton.ConnectedClientsList)
        {
            if (player != null && Vector3.Distance(transform.position, player.PlayerObject.transform.position) <= interactionRange)
            {
                return true;
            }
        }
        return false;
    }

    void Update()
    {
        if (!IsServer)
            return;

        // Check if the player is nearby
        if (IsPlayerInRange())
        {
            // Check if the 'e' key is pressed
            if (Input.GetKeyDown(KeyCode.E) && !isInteracting)
            {
                InteractWithComputerServerRpc();
            }

            // Check if the 'A' button on the gamepad is pressed
            if (Gamepad.current != null && Gamepad.current.buttonSouth.isPressed && !isInteracting)
            {
                InteractWithComputerServerRpc();
            }
        }
    }

    [ServerRpc]
    private void InteractWithComputerServerRpc()
    {
        isComputerScreenVisible = true;
        RpcUpdateComputerScreenVisibilityClientRpc(isComputerScreenVisible);

        // Set a timer to hide the computer screen after the specified duration
        Invoke(nameof(HideComputerScreenClientRpc), displayDuration);

        // Set interacting flag to prevent multiple interactions
        isInteracting = true;
    }

    [ClientRpc]
    private void RpcUpdateComputerScreenVisibilityClientRpc(bool isVisible)
    {
        isComputerScreenVisible = isVisible;
        computerScreen.SetActive(isVisible);

        // If the computer screen is shown on the client, set the interacting flag to true
        if (isVisible)
        {
            isInteracting = true;
        }
    }
[ClientRpc]
    private void HideComputerScreenClientRpc()
    {
        isComputerScreenVisible = false;
        computerScreen.SetActive(false);

        // Reset interacting flag after hiding the computer screen
        isInteracting = false;
    }
}

//works well but for the server can only interact but client no
Posted
Updated 12-Feb-24 21:43pm
v3
Comments
[no name] 13-Feb-24 19:40pm    
I don't know how you expect to handle "key input" when you don't appear to be recognizing "key events".
https://docs.unity3d.com/Manual/UIE-Keyboard-Events.html

1 solution

Your script looks good for the most part. However, there are a few things to consider and potentially improve:

Input System Integration: You're currently using the legacy Input.GetKeyDown(KeyCode.E) and Gamepad.current to detect input. It's recommended to fully utilize Unity's new Input System for a more robust and flexible input handling solution.

Network Synced Variables: Ensure that any variables affecting gameplay logic, such as isComputerScreenVisible and isInteracting, are properly synchronized across the network. This ensures consistency between the client and server.

Interaction Range Check: Make sure that the interaction range check (IsPlayerInRange()) accurately represents the intended behavior. You may want to use a sphere cast or other methods to check for obstacles between the player and the interactive computer.

Input Handling: Consider handling input detection on the client side and then sending commands to the server to perform interactions. This helps reduce latency and ensures a smoother player experience.

Error Handling: Implement error handling to handle edge cases, such as when there are no connected players or when the gamepad is disconnected.

C#
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

public class InteractiveComputer : NetworkBehaviour
{
    public GameObject computerScreen;
    public float interactionRange = 3f; // Adjust the interaction range as needed
    private float displayDuration = 5f; // Duration to display the computer screen

    private bool isComputerScreenVisible = false;
    private bool isInteracting = false; // Flag to prevent multiple interactions

    void Update()
    {
        if (!IsClient)
            return;

        // Check if the player is nearby
        if (IsPlayerInRange())
        {
            // Check for interaction input
            if (Keyboard.current != null && Keyboard.current.eKey.wasPressedThisFrame && !isInteracting)
            {
                InteractWithComputerClientRpc();
            }

            if (Gamepad.current != null && Gamepad.current.buttonSouth.wasPressedThisFrame && !isInteracting)
            {
                InteractWithComputerClientRpc();
            }
        }
    }

    [ClientRpc]
    private void InteractWithComputerClientRpc()
    {
        isComputerScreenVisible = true;
        computerScreen.SetActive(true);

        // Set a timer to hide the computer screen after the specified duration
        Invoke(nameof(HideComputerScreenClientRpc), displayDuration);

        // Set interacting flag to prevent multiple interactions
        isInteracting = true;
    }

    [ClientRpc]
    private void HideComputerScreenClientRpc()
    {
        isComputerScreenVisible = false;
        computerScreen.SetActive(false);

        // Reset interacting flag after hiding the computer screen
        isInteracting = false;
    }

    bool IsPlayerInRange()
    {
        foreach (var player in NetworkManager.Singleton.ConnectedClientsList)
        {
            if (player != null && Vector3.Distance(transform.position, player.PlayerObject.transform.position) <= interactionRange)
            {
                return true;
            }
        }
        return false;
    }
}


Please remember to thoroughly test your implementation to ensure it behaves as expected in both single-player and multiplayer scenarios. Additionally, consider adding error handling and edge case checks to make your script more robust.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900