Home > Enterprise >  Changing Y position of player (code runs like the player has two position simultaneously)
Changing Y position of player (code runs like the player has two position simultaneously)

Time:07-08

I am making a game that runs up infinite stairs.

First, I coded prototype code that can run infinite hallway by manipulating the player's Z position and it works.

Then, I change that code to manipulate the player's Y position. This is HallWayController script

    void FixedUpdate()
    {
        this.handleInfiniteHallway();
    }

    private void handleInfiniteHallway()
    {
        if (this.isPlayerOutOfBounds())
        {
            float posYmod = HALLWAY_HEIGHT;
            if (this.player.position.y > MAX_Y_BOUND)
            {
                posYmod *= -1;
            }
            this.player.position = new Vector3(this.player.position.x, this.player.position.y   posYmod, this.player.position.z);
            Debug.Log("Player Y position: "   this.player.position.y);
        }

    }

    private bool isPlayerOutOfBounds()
    {
        return this.player.position.y > MAX_Y_BOUND || this.player.position.y < MIN_Y_BOUND;
    }

With this code, the game malfunctions just like the player have two Y position simultaneously.

What I found:

  1. If I use FixedUpdate(), the player's position doesn't change on game play view, but debug.Log says player Y Position has changed. And if player ever reached Y_Bound, code inside if(this.isPlayterOutOfBounds()) infinitely executes.
  2. If I use Update() instead of FixedUpdate(), the player's position does change in game play view and debug.Log, but sometimes the player flashes back and forth between the original position and repositioned position. And if player ever reached Y_Bound code inside if(this.isPlayterOutOfBounds()) infinitely executes.

This is Player Controller script that linked to the player game object

using UnityEngine;

[RequireComponent(typeof(CharacterController))]
public class PlayerController : MonoBehaviour
{
    [SerializeField] private float playerSpeed = 10.0f;
    [SerializeField] private float jumpHeight = 1.0f;
    [SerializeField] private float gravityValue = -9.81f;

    private bool isFlashLightOn = true;
    public GameObject lightSource;

    private CharacterController controller;
    private Vector3 playerVelocity;
    private bool groundedPlayer;
    private InputManager inputManager;
    private Transform cameraTransform;


    private void Start()
    {
        controller = gameObject.GetComponent<CharacterController>();
        inputManager = InputManager.Instance;
        cameraTransform = Camera.main.transform;

        lightSource.gameObject.SetActive(true);
        isFlashLightOn = true;
    }

    void FixedUpdate()
    {
        groundedPlayer = controller.isGrounded;
        if (groundedPlayer && playerVelocity.y < 0)
        {
            playerVelocity.y = 0f;
        }

        Vector2 movement = inputManager.GetPlayerMovement();
        Vector3 move = new Vector3(movement.x, 0, movement.y);
        move = cameraTransform.forward * move.z   cameraTransform.right * move.x;
        move.y = 0f;
        controller.Move(move * Time.deltaTime * playerSpeed);

        // Changes the height position of the player..
        if (inputManager.PlayerJumped() && groundedPlayer)
        {
            playerVelocity.y  = Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
        }

        playerVelocity.y  = gravityValue * Time.deltaTime;
        controller.Move(playerVelocity * Time.deltaTime);
    }

    void Update()
    {
        if (inputManager.PlayerFlashLightOn())
        {
            isFlashLightOn = !isFlashLightOn;
            lightSource.gameObject.SetActive(isFlashLightOn);
        }
    }
}

CodePudding user response:

Hmm, I think I quess what is the problem here. See comments I added

// You may call this twice on each frame, depending on your frame rate
void FixedUpdate()
    {
        this.handleInfiniteHallway();
    }

    private void handleInfiniteHallway()
    {
        if (this.isPlayerOutOfBounds())
        {
            // Problem is probably here. When your object hits another limit, you move it all HALLWAY_HEIGHT, so it hits another limit  
            // If you move just half of the height, your character returns to the middle.
            // Original float posYmod = HALLWAY_HEIGHT;
            float posYmod = HALLWAY_HEIGHT / 2;
            if (this.player.position.y > MAX_Y_BOUND)
            {
                posYmod *= -1;
            }
            this.player.position = new Vector3(this.player.position.x, this.player.position.y   posYmod, this.player.position.z);
            Debug.Log("Player Y position: "   this.player.position.y);
        }

    }

    private bool isPlayerOutOfBounds()
    {
        return this.player.position.y > MAX_Y_BOUND || this.player.position.y < MIN_Y_BOUND;
    }

If you call FixedUpdate method, it is run twice a frame so position is moved back and forth during one frame. Update method would be called each frame player is jumping between borders.

  • Related