Unity 2D传送门系统:玩家移动脚本覆盖速度转换AddForce的问题求解
解决方案:处理传送门与玩家移动的速度冲突
方案1:添加传送门后的短暂移动锁定
给玩家脚本加一个锁定计时器,在传送门生效后的短时间内禁用移动逻辑,避免覆盖传送门赋予的速度:
// 玩家脚本新增变量 private float portalLockTimer = 0f; [SerializeField] private float portalLockDuration = 0.15f; // 可根据手感调整 private void FixedUpdate() { isGreenActivated = outPortal.GetComponent<Portal>().activated; // 处理传送门锁定倒计时 if (portalLockTimer > 0) { portalLockTimer -= Time.fixedDeltaTime; return; // 跳过移动逻辑 } if (isGreenActivated) { Vector2 newVelocity = ConvertVelocity(rb.velocity); rb.velocity = newVelocity; // 直接设置速度比AddForce更稳定 portalLockTimer = portalLockDuration; // 启动锁定 } else { Vector2 playerMovement = new Vector2(horizontal * speed, rb.velocity.y); rb.velocity = playerMovement; } }
方案2:调整逻辑执行顺序,避免状态冲突
修改条件判断逻辑,确保传送门生效时完全跳过移动赋值逻辑,同时直接设置速度而非依赖AddForce:
private void FixedUpdate() { isGreenActivated = outPortal.GetComponent<Portal>().activated; if (isGreenActivated) { Vector2 newVelocity = ConvertVelocity(rb.velocity); rb.velocity = newVelocity; // 重置传送门激活状态(根据你的Portal组件逻辑调整) outPortal.GetComponent<Portal>().activated = false; } else { Vector2 playerMovement = new Vector2(horizontal * speed, rb.velocity.y); rb.velocity = playerMovement; } }
方案3:优化移动的力控制逻辑
如果坚持用AddForce实现移动,需要区分传送门生效状态,避免移动力覆盖传送门速度:
private void FixedUpdate() { isGreenActivated = outPortal.GetComponent<Portal>().activated; if (isGreenActivated) { Vector2 newVelocity = ConvertVelocity(rb.velocity); rb.velocity = newVelocity; } else { // 计算目标水平速度,垂直速度保留物理模拟结果 float targetHorizontalSpeed = horizontal * speed; // 施加力让水平速度趋近目标值,避免速度无限增长 Vector2 force = new Vector2(targetHorizontalSpeed - rb.velocity.x, 0); rb.AddForce(force, ForceMode2D.Force); } }
额外优化:简化速度转换逻辑
2D场景下可以直接用向量夹角旋转替代四元数,更高效:
public Vector2 ConvertVelocity(Vector2 initialVelocity) { // 计算两个传送门方向的夹角 float angle = Vector2.SignedAngle(inPortal.transform.right, -outPortal.transform.right); // 旋转初始速度向量 return Quaternion.Euler(0, 0, angle) * initialVelocity; }
内容的提问来源于stack exchange,提问作者Harmonical
相关产品推荐
相关产品推荐

