Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Error when trying to invoke an event

Discussion in 'Multiplayer' started by nb070507, Aug 3, 2023.

  1. nb070507

    nb070507

    Joined:
    Jul 16, 2023
    Posts:
    4
    So I'm making a turn-based multiplayer game, and I'm trying to make a public event happen every time a turn is switched, so the player look frozen if it's not their turn, but this error happens every time I try to invoke it.

    This is the code for my GameManager object.
    Code (CSharp):
    1. using UnityEngine;
    2. using TMPro;
    3. using Unity.Netcode;
    4. using UnityEngine.Events;
    5.  
    6. public class GameLogic : NetworkBehaviour
    7. {
    8.     public int redLives = 4;
    9.     public int blueLives = 4;
    10.     public NetworkVariable<bool> redTurn = new NetworkVariable<bool>(true);
    11.     public NetworkVariable<bool> blueTurn = new NetworkVariable<bool>(true);
    12.     public NetworkVariable<float> turnTimer = new NetworkVariable<float>();
    13.     public NetworkVariable<int> turnCount = new NetworkVariable<int>();
    14.  
    15.     public int eventRNG;
    16.     public TMP_Text text;
    17.     public TeamDistribution mp;
    18.     private int turnTimerDisplay;
    19.  
    20.     public UnityEvent TSEvent;
    21.  
    22.     private void Awake()
    23.     {
    24.         QualitySettings.vSyncCount = 0;
    25.         Application.targetFrameRate = 60;
    26.     }
    27.     void Update()
    28.     {
    29.         turnTimerDisplay = Mathf.RoundToInt(turnTimer.Value);
    30.         text.text = "Round " + turnCount.Value + "\r\nNext round in " + (20 - turnTimerDisplay) + "\r\nRed players: " + mp.redTeamPlayers.Value + "\r\nBlue players: " + mp.blueTeamPlayers.Value + "\r\nRed turn: " + redTurn.Value + "\r\nBlue turn: " + blueTurn.Value;
    31.         turnTimer.Value += Time.deltaTime;
    32.         if (turnTimer.Value >= 20)
    33.         {
    34.             TurnSwitch(); //this function does not get called at all unless i remove the invoke event line, the timer goes above 20
    35.         }
    36.     }
    37.  
    38.     public void TurnSwitch()
    39.     {
    40.         TSEvent?.Invoke();   //if i deactivate this line no error happens
    41.  
    42.         if (redTurn.Value == true && blueTurn.Value == true)
    43.         {
    44.             bool turnRNG = Random.Range(0, 2) == 0;
    45.             if (turnRNG)
    46.             {
    47.                 blueTurn.Value = true;
    48.                 redTurn.Value = false;
    49.             }
    50.             else
    51.             {
    52.                 redTurn.Value = true;
    53.                 blueTurn.Value = false;
    54.             }
    55.             turnTimer.Value = 0;
    56.             turnCount.Value += 1;
    57.         }
    58.         else if (redTurn.Value == true)
    59.         {
    60.             redTurn.Value = false;
    61.             blueTurn.Value = true;
    62.             turnTimer.Value = 0;
    63.             turnCount.Value += 1;
    64.         }
    65.         else if (blueTurn.Value == true)
    66.         {
    67.             redTurn.Value = true;
    68.             blueTurn.Value = false;
    69.             turnTimer.Value = 0;
    70.             turnCount.Value += 1;
    71.         }
    72.     }
    73. }
    This is the code for my player prefab.
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using Unity.Netcode;
    4. using TMPro;
    5.  
    6. public class Movement : NetworkBehaviour
    7. {
    8.     public Vector3 velocity;
    9.     public float acceleration = 8;
    10.     public float deceleration = 60;
    11.     public float maxSpeed = 15;
    12.     public float jumpHeight = 2;
    13.  
    14.     float distanceToCheck = 1.5f;
    15.     float horizontalDistanceToCheck = 1f;
    16.     public bool isGrounded;
    17.     public RaycastHit hit;
    18.     public ParticleSystem hermesBoots;
    19.     public float highJumpTimer = 0;
    20.     public float highJumpTimerMax = 12;
    21.     private float speen;
    22.     public float maxHealth = 400;
    23.     public float currentHealth = 400;
    24.     public float currentMana = 25;
    25.     public float maxMana = 25;
    26.     public float manaCounter = 0;
    27.     public float manaRegenRate = 1;
    28.     public float terminalVelocity = -20;
    29.     public float gravity = 0.7f;
    30.  
    31.  
    32.     public int kills = 0;
    33.     public int score = 1;
    34.     public float environmentIFrames;
    35.     public GameLogic gameLogic;
    36.     public GameObject ice;
    37.     public bool blueTeam = false;
    38.     public bool redTeam = false;
    39.     private Vector3 startPos;
    40.     public TeamDistribution mp;
    41.     private GameObject clone;
    42.     public GameObject healthBar;
    43.     public GameObject healthText;
    44.     public Camera cam;
    45.  
    46.     void Awake()
    47.     {
    48.         gameLogic = FindObjectOfType<GameLogic>();
    49.         mp = FindObjectOfType<TeamDistribution>();
    50.         healthBar = GameObject.Find("HealthBarInner");
    51.         healthText = GameObject.Find("HealthText");
    52.         cam = FindObjectOfType<Camera>();
    53.     }
    54.  
    55.     private void Start()
    56.     {
    57.         CameraSetup();
    58.         if (mp.blueTeamPlayers.Value == mp.redTeamPlayers.Value)
    59.         {
    60.             redTeam = Random.Range(0, 2) == 0;
    61.             if (redTeam)
    62.             {
    63.                 blueTeam = false;
    64.                 mp.redTeamPlayers.Value += 1;
    65.             }
    66.             else
    67.             {
    68.                 blueTeam = true;
    69.                 mp.blueTeamPlayers.Value += 1;
    70.             }
    71.         }
    72.  
    73.         else if (mp.blueTeamPlayers.Value > mp.redTeamPlayers.Value)
    74.         {
    75.             redTeam = true;
    76.             blueTeam = false;
    77.             mp.redTeamPlayers.Value += 1;
    78.         }
    79.  
    80.         else if (mp.blueTeamPlayers.Value < mp.redTeamPlayers.Value)
    81.         {
    82.             redTeam = false;
    83.             blueTeam = true;
    84.             mp.blueTeamPlayers.Value += 1;
    85.         }
    86.  
    87.  
    88.         if (blueTeam)
    89.         {
    90.             startPos = new Vector3(-66, 80, 0);
    91.         }
    92.         if (redTeam)
    93.         {
    94.             startPos = new Vector3(66, 80, 0);
    95.         }
    96.         transform.position = startPos;
    97.     }
    98.  
    99.     private void CameraSetup()
    100.     {
    101.         if (!IsOwner) return;
    102.         cam.GetComponent<PlayerFollow>().setTarget(gameObject.transform);
    103.     }
    104.  
    105.     private void Update()
    106.     {
    107.         if (!IsOwner) return;
    108.         healthBar.GetComponent<Image>().fillAmount = currentHealth / maxHealth;
    109.         healthText.GetComponent<TMP_Text>().text = "Life: " + currentHealth + "/" + maxHealth;
    110.  
    111.         float velocityAbsolute = Mathf.Abs(velocity.x);
    112.         Vector3 stepupBottomPosition = new Vector3(transform.position.x, transform.position.y - 1.3f, transform.position.z);
    113.         Vector3 groundPositionL = new Vector3(transform.position.x - 0.7f, transform.position.y, transform.position.z);
    114.         Vector3 groundPositionR = new Vector3(transform.position.x + 0.7f, transform.position.y, transform.position.z);
    115.         Ray groundCheck = new Ray(transform.position, Vector3.down);
    116.         Ray groundCheckL = new Ray(groundPositionL, Vector3.down);
    117.         Ray groundCheckR = new Ray(groundPositionR, Vector3.down);
    118.         if (Physics.Raycast(groundCheck, out hit, distanceToCheck) || Physics.Raycast(groundCheckL, out hit, distanceToCheck) || Physics.Raycast(groundCheckR, out hit, distanceToCheck))
    119.         {
    120.             isGrounded = true;
    121.         }
    122.         else
    123.         {
    124.             isGrounded = false;
    125.         }
    126.  
    127.         Ray stepupTop = new Ray(transform.position, Vector3.right * Input.GetAxisRaw("Horizontal"));
    128.         Ray stepupBottom = new Ray(stepupBottomPosition, Vector3.right * Input.GetAxisRaw("Horizontal"));
    129.         bool topCheck = Physics.Raycast(stepupTop, out hit, horizontalDistanceToCheck);
    130.         bool bottomCheck = Physics.Raycast(stepupBottom, out hit, horizontalDistanceToCheck);
    131.  
    132.  
    133.         if (gameLogic.blueTurn.Value == true && blueTeam || gameLogic.redTurn.Value == true && redTeam)
    134.         {
    135.             if (!topCheck && bottomCheck)
    136.             {
    137.                 if (isGrounded)
    138.                 {
    139.                     transform.position = new Vector3(transform.position.x, transform.position.y + 1, transform.position.z);
    140.                 }
    141.                 else
    142.                 {
    143.                     transform.position = new Vector3(transform.position.x + Input.GetAxisRaw("Horizontal"), transform.position.y + 1, transform.position.z);
    144.                     velocity.x = 0;
    145.                 }
    146.             }
    147.             if (topCheck)
    148.             {
    149.                 velocity.x = 0 * Input.GetAxisRaw("Horizontal");
    150.             }
    151.  
    152.  
    153.             if (Input.GetAxisRaw("Horizontal") == 1 && isGrounded || Input.GetAxisRaw("Horizontal") == -1 && isGrounded)
    154.             {
    155.                 velocity.x = Mathf.MoveTowards(velocity.x, Input.GetAxisRaw("Horizontal") * maxSpeed, acceleration * Time.deltaTime);
    156.             }
    157.             else
    158.             {
    159.                 if (Input.GetAxisRaw("Horizontal") == 1 && !isGrounded || Input.GetAxisRaw("Horizontal") == -1 && !isGrounded)
    160.                     if (velocityAbsolute < 4)
    161.                     {
    162.                         velocity.x = Mathf.MoveTowards(velocity.x, Input.GetAxisRaw("Horizontal") * 4, acceleration * Time.deltaTime);
    163.                     }
    164.                     else
    165.                     {
    166.  
    167.                     }
    168.                 else if (Input.GetAxisRaw("Horizontal") == 0)
    169.                 {
    170.                     velocity.x = Mathf.MoveTowards(velocity.x, 0, deceleration * Time.deltaTime);
    171.                 }
    172.             }
    173.  
    174.  
    175.             if (isGrounded && !Input.GetKeyDown(KeyCode.Space))
    176.             {
    177.                 highJumpTimer = 0;
    178.             }
    179.             if (Input.GetKeyDown(KeyCode.Space) && isGrounded || highJumpTimer > 0 && Input.GetKey(KeyCode.Space) && highJumpTimer < highJumpTimerMax)
    180.             {
    181.                 velocity.y = jumpHeight;
    182.                 highJumpTimer += 1;
    183.             }
    184.             if (Input.GetKeyUp(KeyCode.Space))
    185.             {
    186.                 highJumpTimer = 0;
    187.             }
    188.  
    189.             if (isGrounded && highJumpTimer == 0)
    190.             {
    191.                 velocity.y = 0;
    192.             }
    193.             else
    194.             {
    195.                 if (velocity.y >= terminalVelocity && gameLogic.blueTurn.Value == true && blueTeam || velocity.y >= terminalVelocity && gameLogic.redTurn.Value == true && redTeam)
    196.                 {
    197.                     velocity.y -= gravity;
    198.                 }
    199.  
    200.             }
    201.             transform.position += velocity * Time.deltaTime;
    202.             transform.rotation = Quaternion.Euler(0, speen, 0);
    203.         }
    204.  
    205.         if (gameLogic.redTurn.Value == true && gameLogic.blueTurn.Value == false && blueTeam || gameLogic.blueTurn.Value == true && gameLogic.redTurn.Value == false && redTeam)
    206.         {
    207.             velocity.x = 0;
    208.             velocity.y = 0;
    209.         }
    210.  
    211.  
    212.         if (Input.GetAxisRaw("Horizontal") == 1)
    213.         {
    214.             speen = 0;
    215.         }
    216.         else if (Input.GetAxisRaw("Horizontal") == -1)
    217.         {
    218.             speen = 180;
    219.         }
    220.  
    221.  
    222.         if (currentHealth <= 0)
    223.         {
    224.             gameLogic.blueLives -= 1;
    225.             score -= 1;
    226.             transform.position = startPos;
    227.             currentHealth = maxHealth;
    228.         }
    229.         if (environmentIFrames > 0)
    230.         {
    231.             environmentIFrames -= Time.deltaTime;
    232.         }
    233.  
    234.  
    235.         if (velocity.x == 0 && isGrounded)
    236.         {
    237.             manaRegenRate = (maxMana / 7 + 1 + maxMana / 2) * (currentMana / maxMana * 0.8f + 0.2f) * 1.15f;
    238.         }
    239.         else
    240.         {
    241.             manaRegenRate = (maxMana / 7 + 1) * (currentMana / maxMana * 0.8f + 0.2f) * 1.15f;
    242.         }
    243.  
    244.         if (currentMana < maxMana)
    245.         {
    246.             manaCounter += manaRegenRate;
    247.         }
    248.         if (manaCounter >= 120 && currentMana < maxMana)
    249.         {
    250.             currentMana += 1;
    251.             manaCounter = 0;
    252.         }  
    253.     }
    254.  
    255.     private void OnTriggerStay(Collider collider)
    256.     {
    257.         if (environmentIFrames <= 0)
    258.         {
    259.                 if (collider.tag == "Lava")
    260.                 {
    261.                     currentHealth -= 80;
    262.                     environmentIFrames = 0.66f;
    263.                 }
    264.                 if (collider.tag == "Tornado")
    265.                 {
    266.                     currentHealth -= 10;
    267.                     environmentIFrames = 0.66f;
    268.                 }
    269.                 if (collider.tag == "Geyser")
    270.                 {
    271.                     currentHealth -= 30;
    272.                     environmentIFrames = 0.66f;
    273.                 }
    274.                 if (collider.tag == "Fireball")
    275.                 {
    276.                     currentHealth -= 40;
    277.                     environmentIFrames = 0.66f;
    278.                 }
    279.                 if (collider.tag == "Lightning")
    280.                 {
    281.                     currentHealth -= 60;
    282.                     environmentIFrames = 0.66f;
    283.                 }
    284.         }
    285.     }
    286.  
    287.     [ServerRpc]
    288.     public void IceRenderServerRpc()
    289.     {
    290.         if (gameLogic.redTurn.Value == true && gameLogic.blueTurn.Value == false && blueTeam || gameLogic.blueTurn.Value == true && gameLogic.redTurn.Value == false && redTeam)
    291.         {
    292.             clone = Instantiate(ice, transform.position, transform.rotation);
    293.             clone.GetComponent<NetworkObject>().Spawn(true);
    294.             clone.transform.rotation = Quaternion.Euler(-90, 90, 90);
    295.             clone.transform.position = transform.position + new Vector3(0, 1, 0);
    296.         }
    297.         else
    298.         {
    299.             Destroy(clone.gameObject);
    300.         }
    301.     }
    302. }
    P.s. sorry for the bad code, I'm only getting started with unity.
     

    Attached Files:

  2. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    48
    @nb070507

    Could you include the Movement.cs script as well? This is where the exception is actually happening.
    My guess, looking at the code provided, is that the NetworkObject associated with Movement.IceRenderServerRpc is possibly not spawned yet?
    Really, it might be easier to do something like this:

    Code (CSharp):
    1.     public class MyTeamTurnSystem : NetworkBehaviour
    2.     {
    3.         public enum TeamTypes
    4.         {
    5.             Red,
    6.             Blue
    7.         }
    8.  
    9.         public int TurnTimeOut = 20;
    10.  
    11.         private Coroutine m_TurnTimeoutCoroutine;
    12.         private NetworkVariable<bool> m_TeamsCanStart= new NetworkVariable<bool>();
    13.  
    14.         // Server-host assigns this or perhaps you could pre-assign it depending upon your design
    15.         private NetworkVariable<TeamTypes> m_AssignedTeam = new NetworkVariable<TeamTypes>();
    16.  
    17.  
    18.         private NetworkVariable<TeamTypes> m_CurrentTeamTurn = new NetworkVariable<TeamTypes>();  
    19.         private List<string> m_TeamTypesNames;
    20.  
    21.         public override void OnNetworkSpawn()
    22.         {
    23.             if(IsServer)
    24.             {
    25.                 m_TeamsCanStart.Value = false;
    26.                 // Get the types
    27.                 m_TeamTypesNames = Enum.GetNames(typeof(TeamTypes)).ToList();
    28.                 // Alternate assignment
    29.                 m_AssignedTeam.Value = (TeamTypes)Enum.Parse(typeof(TeamTypes), m_TeamTypesNames[m_TeamTypesNames.Count % NetworkManager.ConnectedClientsIds.Count]);
    30.             }
    31.  
    32.             base.OnNetworkSpawn();
    33.         }
    34.  
    35.         // invoke this when you want the 1st team turn to start.
    36.         // most likely controlled by some other game state/condition (i.e. both sides are ready)
    37.         public void StartTeamTurns(TeamTypes teamToStart)
    38.         {
    39.             // Only server/host should invoke this
    40.             if (!IsServer)
    41.             {
    42.                 return;
    43.             }
    44.             m_TeamsCanStart.Value = true;
    45.             m_CurrentTeamTurn.Value = teamToStart;
    46.  
    47.             NextTeamTurn(teamToStart, true);
    48.         }
    49.  
    50.         private IEnumerator TeamTurnTimeout(float timeoutPeriod)
    51.         {
    52.             var timeoutWait = new WaitForSeconds(0.5f);
    53.             var turnTimedOut = Time.realtimeSinceStartup + timeoutPeriod;
    54.             var currentTeam = m_CurrentTeamTurn.Value;
    55.             while (currentTeam == m_CurrentTeamTurn.Value)
    56.             {
    57.                 yield return timeoutWait;
    58.                 if (timeoutPeriod < Time.realtimeSinceStartup)
    59.                 {
    60.                     NextTeamTurn(m_CurrentTeamTurn.Value);
    61.                     break;
    62.                 }
    63.             }
    64.             yield break;
    65.         }
    66.  
    67.         private void NextTeamTurn(TeamTypes currentTeam, bool keepCurrentTeam = false)
    68.         {
    69.             if (m_TurnTimeoutCoroutine != null)
    70.             {
    71.                 StopCoroutine(m_TurnTimeoutCoroutine);
    72.             }
    73.             if (!keepCurrentTeam)
    74.             {
    75.                 var teamIndex = m_TeamTypesNames.IndexOf(m_CurrentTeamTurn.Value.ToString());
    76.                 teamIndex++;
    77.                 m_CurrentTeamTurn.Value = (TeamTypes)Enum.Parse(typeof(TeamTypes), m_TeamTypesNames[teamIndex % m_TeamTypesNames.Count]);
    78.             }
    79.             m_TurnTimeoutCoroutine = StartCoroutine(TeamTurnTimeout(TurnTimeOut));
    80.         }
    81.  
    82.         // Invoke this when the team has finished their turn
    83.         public void TeamTurnFinished()
    84.         {
    85.             if (IsServer)
    86.             {
    87.                 NextTeamTurn(m_CurrentTeamTurn.Value);
    88.             }
    89.             else
    90.             {
    91.                 TeamTurnFinishedServerRpc();
    92.             }      
    93.         }
    94.  
    95.  
    96.         [ServerRpc(RequireOwnership = false)]
    97.         private void TeamTurnFinishedServerRpc()
    98.         {
    99.             NextTeamTurn(m_CurrentTeamTurn.Value);
    100.         }
    101.  
    102.         private void Update()
    103.         {
    104.             // Don't do anything if not spawned or teams cannot have a turn yet
    105.             if (!IsSpawned || !m_TeamsCanStart.Value)
    106.             {
    107.                 return;
    108.             }
    109.  
    110.             // Exit early if it isn't your teams turn
    111.             if (m_AssignedTeam.Value != m_CurrentTeamTurn.Value)
    112.             {
    113.                 return;
    114.             }
    115.  
    116.             // Update Team Turn action or the like for the players or what have you
    117.             // i.e.
    118.             // UpdateTeamAction();
    119.         }
    120.     }
    Where you are only updating if it is your team's turn... the above is a general pseudo code approach... and is just another way to handle it... depending on whether you want a global team turn management system or the like depends on how you want to use the above code... but gives you the general idea.
     
    Last edited: Sep 1, 2023
  3. nb070507

    nb070507

    Joined:
    Jul 16, 2023
    Posts:
    4
    I did include the Movement script lower, but thank you for the reply.
    IceRenderServerRpc is a function I used to spawn the ice object to make the players look frozen, but now that I learned animation I will just get rid of it. Will keep you updated.