我有一个播放器控制器脚本。由于它在每帧中都会将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, 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);
}
如果你有任何改进的建议,请这样评论。