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:
- If I use
FixedUpdate(), the player's position doesn't change on game play view, butdebug.Logsays player Y Position has changed. And if player ever reachedY_Bound, code insideif(this.isPlayterOutOfBounds())infinitely executes. - If I use
Update()instead ofFixedUpdate(), the player's position does change in game play view anddebug.Log, but sometimes the player flashes back and forth between the original position and repositioned position. And if player ever reachedY_Boundcode insideif(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.
