【问题标题】:Changing Y position of player (code runs like the player has two position simultaneously)改变播放器的 Y 位置(代码运行就像播放器同时有两个位置)
【发布时间】:2022-07-07 23:47:50
【问题描述】:

我正在制作一个可以爬上无限楼梯的游戏。

首先,我编写了可以通过操纵玩家的 Z 位置运行无限走廊的原型代码,它可以工作。

然后,我更改该代码以操纵玩家的 Y 位置。

    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;
    }

使用此代码,游戏会发生故障,就像玩家同时拥有两个 Y 位置一样。

我发现了什么:

  1. 如果我使用FixedUpdate(),玩家在游戏视图中的位置不会改变,但debug.Log 表示玩家Y 位置已经改变。如果玩家到达Y_Boundif(this.isPlayterOutOfBounds()) 中的代码将无限执行。
  2. 如果我使用Update() 而不是FixedUpdate(),玩家的位置在游戏视图和debug.Log 中会发生变化,但有时玩家会在原始位置和重新定位的位置之间来回闪烁。如果玩家到达Y_Boundif(this.isPlayterOutOfBounds()) 中的代码将无限执行。

这是链接到玩家游戏对象的Player Controller 脚本

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);
        }
    }
}

【问题讨论】:

  • 您的this.player 指的是什么? GameObjecttransform附加到游戏对象?
  • 我相信它是附加到游戏对象的变换。 public Transform player;
  • 是的,它可能是。 GameObject 没有位置属性,所以会报错。

标签: unity3d


【解决方案1】:

嗯,我想我想知道这里有什么问题。查看我添加的 cmets

// 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;
    }

如果您调用 FixedUpdate 方法,它每帧运行两次,因此位置在一帧期间来回移动。更新方法将被调用每个帧播放器在边界之间跳转。

【讨论】:

  • 我试过你的代码,但它有同样的问题。它一直在原始位置和新位置之间来回闪烁。我发现即使我的位置似乎改变了一个新的位置,它也会受到原始位置的碰撞网格的影响。所以看起来角色在天空中穿过看不见的楼梯。
  • 您记录您的播放器 y 位置。日志有变化吗?
  • 而且你的代码都没有对碰撞做任何事情。
  • 我认为这不是一个界值问题。 MAX_Y_BOUND = 58fMIN_Y_BOUND = 0fHALLWAY_HEIGHT = 49f。播放器在 Y 值 58.50249.5024 之间闪烁。
  • 日志显示我的位置已更改为 9.5024。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-08
  • 2017-12-15
  • 1970-01-01
  • 1970-01-01
  • 2021-01-25
相关资源
最近更新 更多