问题描述
我有一个播放器控制器脚本。由于它在每一帧都将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);
}
解决方法
我用了@Kyssel的方法,做了一个协程,几秒后把currentState恢复到空闲状态。还通过将 AddForce 增加 10 并缩短击退持续时间来修复 AddForce 浮动且冗长的问题。完整代码在这里:https://pastebin.com/KJVZJSwp
public void GetKnockback(Vector2 dir,float scale,float duration=0.1f)
{
duration = Mathf.Clamp(duration,1);
scale = Mathf.Clamp(scale,5);
currentState = States.InKnockback;
myRigidbody.AddForce(dir.normalized * scale * 10f,ForceMode2D.Impulse);
MyUtils.Time.SetTimeout(() => {
myRigidbody.velocity = Vector2.zero;
},duration,this);
}
如果您有任何改进建议,请发表评论。