启用相关C#脚本进入Play Mode时Unity冻结无响应问题排查
问题根因
你的脚本触发无限循环的核心原因是C#整数除法陷阱,直接导致外层for循环的步长计算结果为0,循环永远无法终止,持续实例化立方体吃满内存,最终锁死Unity主线程。
具体错误点定位
- 外层循环步长写为
(2/8) * radius:字面量2和8在C#中默认是int整数类型,整数除法会直接截断小数部分取整,因此2/8的计算结果为0,等价于每轮循环给vertheight加0,循环变量值永远不变,永远满足循环判定条件 - 循环初始值逻辑矛盾:进入循环前你给
vertheight赋值为负的球体半径(下半球最低点),但for循环初始化语句又把vertheight重置为0,实际只会遍历上半球范围,和沿整个球体摆放立方体的预期不符 - 无限循环运行时,每轮都会执行内层的水平角度循环、不断调用
Instantiate生成立方体,内存占用会无限制上涨,直接导致Unity无响应。
修复后代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CubeAnimManager : MonoBehaviour { public Transform Sphere; public GameObject CubePrefab; public float radius; float radius_at_height = 0; float horiangle = 0f; float vertheight; float xpos; float ypos; float zpos; Vector3 spawnpos; void Start() { radius = Sphere.localScale.x / 2; // 修复1:步长改用浮点数除法,给数值加f后缀标记为float类型,避免整数除法得到0 // 修复2:循环初始值设为-radius,从球体最低点开始遍历,覆盖整个球面 for (vertheight = -radius; vertheight <= radius; vertheight += (2f/8f) * radius) { radius_at_height = Mathf.Sqrt( Mathf.Abs((radius * radius) - (vertheight * vertheight))); for (horiangle = 0; horiangle <= 2 * Mathf.PI; horiangle += (Mathf.PI / 5)) { xpos = Mathf.Cos(horiangle) * radius_at_height; zpos = Mathf.Sin(horiangle) * radius_at_height; ypos = vertheight; spawnpos = new Vector3(Sphere.position.x + xpos, Sphere.position.y + ypos, Sphere.position.z + zpos); Instantiate(CubePrefab, spawnpos, Quaternion.identity); } } } void Update() { } }
额外优化提示
如果生成的立方体和球体穿模,可以给最终的spawnpos加一个沿球面法线方向的小偏移,也就是把位置相对于球心的方向归一化后,乘radius + 立方体边长/2,就能让立方体刚好贴在球体外表面。
内容的提问来源于stack exchange,提问作者Mdl 4848
相关产品推荐
相关产品推荐

