【问题标题】:Choppy Player Movement不稳定的球员运动
【发布时间】:2020-06-28 17:01:32
【问题描述】:

无论出于何种原因,我的玩家移动每秒或每隔一秒都会卡顿,我确信这与我的玩家移动代码使用错误的更新方法有关。

这是我的玩家移动代码

  [SerializeField] private LayerMask groundLayerMask;
public float speed;
public float Jump;
public sword swordScript;
public GameObject swordSprite;
private float move;
private Rigidbody2D rb;
private BoxCollider2D boxCollider2d;
private bool facingRight;
public SpriteRenderer spr;
public Animator PlayerAnims;
public bool movementAllowed;
public float knockback;


void Awake()
{
    boxCollider2d = GetComponent<BoxCollider2D>();
    rb = GetComponent<Rigidbody2D>();
    facingRight = true;
    spr = GetComponent<SpriteRenderer>();
}
// Start is called before the first frame update
void Start()
{
    boxCollider2d = GetComponent<BoxCollider2D>();
    rb = GetComponent<Rigidbody2D>();
    facingRight = true;
    spr = GetComponent<SpriteRenderer>();
}



// Update is called once per frame

void FixedUpdate()
{
    if(movementAllowed == true)
    {
        rb.velocity = new Vector2(move * speed, rb.velocity.y);
        move = Input.GetAxisRaw("Horizontal");
        rb.velocity = new Vector2(move * speed, rb.velocity.y);
        if (isGrounded() && Input.GetButtonDown("Jump"))
        {
            rb.AddForce(new Vector2(rb.velocity.x, Jump));
        }
    }
}


void Update()
{
    if (movementAllowed == true)
    {
        Flip(move);

        if (move == 0)
        {
            PlayerAnims.SetBool("isRunning", false);
        }
        else
        {
            PlayerAnims.SetBool("isRunning", true);
        }
    }


}


private bool isGrounded()
{
    float extraHeightText = .1f;
    RaycastHit2D raycasthit2d = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down,  extraHeightText, groundLayerMask);
    Color rayColour;
    if (raycasthit2d.collider != null)
    {
        rayColour = Color.green;
        PlayerAnims.SetBool("isJumping", false);
    }
    else
    {
        rayColour = Color.red;
        PlayerAnims.SetBool("isJumping", true);

    }
    Debug.DrawRay(boxCollider2d.bounds.center + new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
    Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
    Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, boxCollider2d.bounds.extents.y + extraHeightText), Vector2.right * (boxCollider2d.bounds.extents.x), rayColour);

    return raycasthit2d.collider != null;
}
private void Flip(float move)
{
    if (move > 0 && !facingRight || move < 0 && facingRight)
    {
        facingRight = !facingRight;

        Vector3 theScale = transform.localScale;

        theScale.x *= -1;

        transform.localScale = theScale;

        if (swordScript.isFollowing == true)
        {
            Vector3 swordScale = swordSprite.transform.localScale;

            swordScale.x *= -1;

            swordSprite.transform.localScale = swordScale;
        }
    }
}

【问题讨论】:

    标签: c# unity3d game-development


    【解决方案1】:

    我试用了你的脚本,我想我几乎看不到那种口吃,但有一件事似乎可以解决它。

    您在代码中无缘无故地出现了两次这一特定行

    rb.velocity = new Vector2(move * speed, rb.velocity.y);
    

    只需删除第一个。

    【讨论】:

    • 谢谢,我不敢相信我以前没有注意到这一点。我仍然有这个问题,但我相信我会解决的
    【解决方案2】:

    根据经验:

    调用rb.AddForce:这与物理交互 - 将其置于FixedUpdate

    设置rb.velocity:这只设置一个值。您不会触发与此的物理交互 - 将其放在 Update

    因此,首先您应该将设置速度的代码移动到更新函数。您还设置了两次速度。只需删除第一行。

    作为一个示例,这里是 Update 和 FixedUpdate 函数:

    void FixedUpdate()
    {
        if(movementAllowed == true)
        {
            if (isGrounded() && Input.GetButtonDown("Jump"))
            {
                rb.AddForce(new Vector2(rb.velocity.x, Jump));
            }
        }
    }
    
    
    void Update()
    {
        if (movementAllowed == true)
        {
            float move = Input.GetAxisRaw("Horizontal");
            rb.velocity = new Vector2(move * speed, rb.velocity.y);
    
            Flip(move);
    
            if (move == 0)
            {
                PlayerAnims.SetBool("isRunning", false);
            }
            else
            {
                PlayerAnims.SetBool("isRunning", true);
            }
        }
    }
    

    由于您没有在除Update 之外的任何地方使用move,因此您可以将其声明为局部变量并删除脚本顶部的private float move;

    最后应该提到的事情: 您在 Start 或 Awake 中都获得了组件引用。通常,您应该在 Start 中获取您的引用,并且仅在需要时才在 Awake 中获取它们。

    【讨论】:

    • 谢谢。这并没有解决我的问题,我现在不知所措,但我感谢您的帮助!
    • 使用我的答案中的代码,我没有遇到任何波动。我认为问题出在你代码中的其他地方
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 2015-12-19
    相关资源
    最近更新 更多