1

我有一个播放器控制器脚本。由于它每帧都会将rigidbody.velocity 重置为其他值,因此我无法使用AddForce 进行击退。我的击退方法通常有效,直到它击中玩家位置无法进一步进入击退位置的对撞机,因为有一个对撞机不允许它通过并且它只是卡在击退状态。这是一个自上而下的射击游戏。

这是代码:github链接:https ://github.com/fireWizard23/MFGJ-Summer-2021-ver-1

private Vector2 knockbackEndpoint; // Use to store where the endpoint position of the knockback will be

void Update()
{
    currentState = GetNewState();
    DoStateLogic();
  
}

private void FixedUpdate()
{
    if(currentState != States.Attacking && currentState != States.InKnockback)
    {
        velocity = Vector2.Lerp(velocity, inputVector * myMobInfo.MovementSpeed, myMobInfo.MovementLerpWeight);
    }
    else
    {
        velocity = Vector2.zero;
    }
    
}

private States GetNewState()
{
    switch (currentState)
    {
        default:
        case States.Idle:
            if (velocity != Vector2.zero)
                return States.Walking;
            return States.Idle;
        case States.Walking:
            if (velocity == Vector2.zero) return States.Idle;
            return States.Walking;
        case States.Attacking:
            if (isAttacking < 0) return States.Idle;
            return States.Attacking;
        case States.InKnockback:
            var dist = (knockbackEndpoint - ((Vector2)transform.position)).sqrMagnitude;
            if (dist <= 0.1f * 0.1f)
            {
                if (isAttacking > 0) return States.Attacking;
                knockbackEndpoint = Vector2.zero;
                return States.Idle;
            }
            return States.InKnockback;
    }
}

private void DoStateLogic()
{
    
    // MOVEMENT
    switch(currentState)
    {
        case States.Idle:
        case States.Walking:
            inputVector = GetInputVector();
            if(Input.GetMouseButton(0) && canAttack == 0)
            {
                Shoot();
            }

            break;
        case States.InKnockback:
            var half = (knockbackEndpoint - (Vector2)transform.position) / 3f;
            myRigidbody.MovePosition(transform.position + (Vector3)half);
            break;

    }
}
public void GetKnockback(Vector2 knockbackEndpoint)
{
    currentState = States.InKnockback;
    var end = knockbackEndpoint;

    this.knockbackEndpoint = end;

}
private void Shoot()
{
    currentState = States.Attacking;
    isAttacking = 0f;
    canAttack += Time.deltaTime;
    GameObject go = Pooler.Instance.Get("PlayerBullet");
    Vector2 dir = ((Vector2)(MyUtils.CameraUtils.MousePosition - transform.position)).normalized;
    go.GetComponent<IProjectile>()?.Setup(myMuzzlePos.position, dir );
    GetKnockback((-0.5f * dir) + (Vector2)transform.position);
}
4

1 回答 1

0

我使用了@Kyssel 的方法并制作了一个协程,几秒钟后将 currentState 恢复为空闲状态。还通过将 AddForce 增加 10 并缩短击退的持续时间来解决 AddForce 浮动和冗长的问题。完整代码在这里:https ://pastebin.com/KJVZJSwp

public void GetKnockback(Vector2 dir, float scale,float duration=0.1f)
{
    duration = Mathf.Clamp(duration, 0, 1);
    scale = Mathf.Clamp(scale, 0, 5);
    currentState = States.InKnockback;

    myRigidbody.AddForce(dir.normalized * scale * 10f, ForceMode2D.Impulse);
    MyUtils.Time.SetTimeout(() => {
        myRigidbody.velocity = Vector2.zero;
    }, duration, this);

}

如果您有任何改进这一点的提示,请发表评论。

于 2021-06-30T11:05:51.430 回答