Search code examples
unity-game-enginepositionuniquemultiplayer

Unity Multiplayer: Reset player position when Y axis is less then -2


i'm having this issue with resetting the players position when the players Y axis is less then the threshold value which is -2.

using UnityEngine;
using UnityEngine.Networking;

public class ResetPlayerPosition : NetworkManager {

    public float threshold = -2f;

    NetworkIdentity UniquePlayer;

    // On button click, it checks the players position and resets the position if values are true
    public void ResetPosition () {

        UniquePlayer = GameObject.Find("Player").GetComponent<NetworkIdentity>();
        var Player = GameObject.FindWithTag("Player");

        // Reset player position if the players Y axis is less than -2
        if (Player.transform.position.y < threshold) {
            Debug.Log("player position has been reset");
            Player.transform.position = new Vector3(0, 1, 0);
        } else {
            Debug.Log("Player position Y is currently at: " + Player.transform.position.y);
        }   
    }
}

My goal is to catch the unique players y position and reset that to 1 if its less then -2. I got it working when you're in the match alone, but as soon as you're more than 1 player in the match, it does weird things because its not pointing to the specific player.

I'm using NetworkManager and its running on localhost. I've attempted my way around this with getting the netID of the player which is unique but can't figure out how to combine this information.

Hope someone is able to point me in the right direction.


Solution

  • First I would recommend doing some more testing to narrow down how the weird behavior differs on the host system and the client system. This might give some insight into what exactly is going wrong.

    Second, I agree with Sebastian that putting a MonoBehaviour on the player prefab could be a better way to go. Something like this should be a surefire solution:

    using UnityEngine;
    
    public class PositionReset : MonoBehaviour {
        public float threshold = -2;
        public float resetHeight = 1;
    
        private void Update() {
            if (transform.position.y < threshold) {
                // Note, I keep the x and z position the same, as it sounds like that's what you were looking for. Change as needed
                transform.position = new Vector3(transform.position.x, resetHeight, transform.position.z);
            }
        }
    }
    

    If putting the behavior on the player prefab itself isn't acceptable for some reason, here is a modified version of your code snippet that might solve the issue:

    using UnityEngine;
    using UnityEngine.Networking;
    
    public class ResetPlayerPosition : NetworkManager {
    
        public float threshold = -2f;
    
        // On button click, it checks the players position and resets the position if values are true
        public void ResetPosition () {
            var Players = GameObject.FindGameObjectsWithTag("Player");
    
            foreach(GameObject Player in Players) {
                // Reset player position if the players Y axis is less than -2
                if (Player.transform.position.y < threshold) {
                    Debug.Log("player position has been reset");
                    Player.transform.position = new Vector3(0, 1, 0);
                } else {
                    Debug.Log("Player position Y is currently at: " + Player.transform.position.y);
                }
            }
        }
    }
    

    You'll note that instead of retrieving one game object with the player tag, we retrieve all of them, and perform the evaluation against all of them with the foreach loop. This should yield more consistent behavior.

    Beyond this, I would look into using a NetworkTransform, which will help keep the positions of players synced across the network for all movements; an essential tool for almost all networked games.