Unity中转移Rigidbody运动属性后禁用原对象致新对象停动
Unity刚体替换后运动状态丢失问题解决
嘿,这个问题我之前在做Unity刚体替换的时候也踩过坑,咱们一步步拆解解决:
问题根源
- 运动状态复制方式错误:你现在用
AddForce和AddTorque并乘以Time.deltaTime是完全不对的——velocity是刚体的瞬时速度,你要的是直接继承这个状态,而不是给新刚体施加一个持续力。AddForce是用来模拟外力作用的,不是复制瞬时运动。 - 原对象禁用时机干扰物理系统:当你在
LateUpdate里调用active.SetActive(false)时,Unity会立即销毁该对象的物理状态(包括Rigidbody的velocity、angularVelocity)。而LateUpdate是在所有Update和物理帧之后执行的,这会导致你刚复制的状态还没被新刚体的物理系统完全接收,就因为原对象被禁用而出现异常。
修正后的代码方案
直接赋值刚体的核心运动属性,同时换一种方式隐藏原对象(不直接禁用整个对象):
void LateUpdate() { // 激活新的刚体对象 inactive.SetActive(true); // 简洁地复制位置和旋转 inactive.transform.position = active.transform.position + new Vector3(7.9f, 0, 0); inactive.transform.rotation = active.transform.rotation; // 提前缓存刚体组件,避免重复GetComponent损耗性能 Rigidbody activeRb = active.GetComponent<Rigidbody>(); Rigidbody inactiveRb = inactive.GetComponent<Rigidbody>(); // 直接赋值瞬时运动状态,这才是继承运动的正确姿势 inactiveRb.velocity = activeRb.velocity; inactiveRb.angularVelocity = activeRb.angularVelocity; // 不要直接SetActive(false),换两种隐藏方式: // 方案1:仅禁用所有渲染组件(保留物理状态,避免干扰新对象) foreach (Renderer renderer in active.GetComponentsInChildren<Renderer>()) { renderer.enabled = false; } // 方案2:把原对象移到视野外(适合之后要销毁的情况) // active.transform.position = new Vector3(-1000f, -1000f, -1000f); // 之后可以延迟销毁:Destroy(active, 0.2f); }
额外优化建议
- 缓存组件:最好在
Start方法里就缓存好两个对象的Rigidbody和Renderer组件,不要每次LateUpdate都调用GetComponent,提升运行效率。 - 延迟销毁原对象:如果原对象后续不再需要,可以用协程延迟一帧再销毁,给物理系统足够时间处理状态复制:
// 在复制完状态后调用 StartCoroutine(DestroyActiveObject(active)); // 协程方法 IEnumerator DestroyActiveObject(GameObject target) { yield return null; // 等待一帧,让物理系统完成状态同步 Destroy(target); }
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

