Unity开发Planets game新增第二行星时玩家被排斥问题求解
问题背景
开发行星类游戏Planets game时,单行星场景引力效果符合预期,添加第二颗行星后,玩家会被第二颗行星排斥,无法正常被吸引。
原有实现代码
GameObject[] Planets; // maxDist、speed为预先定义的全局变量 void Start() { Planets = GameObject.FindGameObjectsWithTag("Planet"); } void FixedUpdate() { foreach (GameObject planet in Planets) { if (Vector2.Distance(transform.position, planet.transform.position) <= maxDist) { maxDist = planet.GetComponent<CircleCollider2D>().radius + planet.transform.localScale.x; Vector3 desiredPosition = planet.transform.position; Vector3 smoothedPosition = Vector3.MoveTowards(transform.position, desiredPosition, speed); GetComponent<Rigidbody2D>().AddForce(smoothedPosition * -1); smoothedPosition = Vector3.zero; } } }
代码核心问题
maxDist逻辑完全混乱:该变量在循环过程中被动态修改为当前遍历行星的半径+缩放值,既没有固定初始阈值,也无法作为多行星场景下的引力范围判断依据。单行星场景下因为遍历对象只有一个,变量修改后的逻辑冲突没有暴露,多行星场景下会出现判断阈值随机跳变的问题,导致不该触发引力的行星触发了力的计算。- 引力方向计算完全错误:
Vector3.MoveTowards返回的是玩家当前位置朝目标行星移动speed步长后的世界坐标点,根本不是指向行星的方向向量。当被遍历的行星刚好位于世界坐标原点附近时,返回值乘-1的方向碰巧朝向行星,这也是单行星(大概率被放在原点)看起来正常的原因;一旦行星不在原点位置,计算出的力方向完全随机,第二颗行星不在原点时就会出现反向的排斥力。 - 引力叠加逻辑错误:遍历过程中每遇到一个符合条件的行星就直接施加一次力,没有按照向量叠加规则计算多颗行星对玩家的合力,且每次计算后将
smoothedPosition清零的操作没有任何实际意义。
修正参考方案
- 给每个行星单独配置引力范围、引力质量参数,不要用全局变量
maxDist在循环里动态修改。 - 正确计算引力向量:对每颗行星,先算出从玩家指向行星的单位方向向量,再根据距离、行星质量计算对应引力大小,将所有行星的引力向量累加得到最终合力。
- 不要用
Vector3.MoveTowards做引力计算,该API仅用于位置缓动,和力的计算逻辑无关。
参考修正后的核心逻辑:
public float gravityStrength = 10f; // 全局引力系数 void FixedUpdate() { Vector2 totalForce = Vector2.zero; Rigidbody2D rb = GetComponent<Rigidbody2D>(); foreach (GameObject planet in Planets) { Vector2 planetPos = planet.transform.position; Vector2 playerPos = transform.position; float distance = Vector2.Distance(playerPos, planetPos); // 读取行星自身配置的引力范围,可给行星挂单独的配置脚本存储 float planetGravityRange = planet.GetComponent<PlanetConfig>().gravityRange; if (distance <= planetGravityRange && distance > 0.1f) { // 计算指向行星的方向 Vector2 dir = (planetPos - playerPos).normalized; // 引力大小和距离平方成反比,可按需调整公式 float forceMagnitude = gravityStrength * planet.GetComponent<PlanetConfig>().mass / (distance * distance); totalForce += dir * forceMagnitude; } } rb.AddForce(totalForce); }
内容的提问来源于stack exchange,提问作者Jerry
相关产品推荐
相关产品推荐

