You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity 2021.3.25f1中玩家设为触发器对象子对象后位置异常

问题:玩家设置为堆垛机子对象后出现浮空/被推出触发器现象

环境

Unity 2021.3.25f1

现象描述

堆垛机左右两侧设有触发器,玩家进入触发器前处于地面,状态正常:
玩家与堆垛机的示意图,可见两侧的两个盒碰撞体,它们是触发器

执行设置父对象操作后,玩家浮空:
与上图相同,但玩家处于浮空状态

俯视图可见,无任何移动操作的情况下,玩家已脱离触发器范围:
上图的俯视图,可见没有碰撞体或触发器相互接触

现有代码

设置父对象函数

public void AttachPlayerToSelf()
{
    Debug.Log("position before attach : " + FirstPersonMovement.S.transform.position);
    FirstPersonMovement.S.rigidbody.isKinematic = true;
    joueurPCGO.GetComponent<FirstPersonMovement>().enabled = false;
    joueurPCGO.transform.SetParent(transform);
    Debug.Log("position after attach : " + FirstPersonMovement.S.transform.position);
}

注:joueurPCGO为包含玩家的GameObject

调用逻辑

if (gerbeur.isPlayerOnSide)
{
    if (!isPlayerAttachedToSelf)
    {
        AttachPlayerToSelf();
        isPlayerAttachedToSelf = true;
    }
}

注:Gerbeur即堆垛机对应的GameObject

触发器检测函数

private void OnTriggerStay(Collider other)
{
    isPlayerOnSide = true;
}

已尝试的无效方案

  • 将玩家Rigidbody设为运动学,无变化
  • 缩小玩家碰撞体范围,无效果
  • 设置父对象时不修改Rigidbody运动学状态,问题依旧

解决方案

核心原因

  1. 父对象变换时的坐标计算异常,导致玩家位置偏移
  2. 触发器状态未及时重置,存在逻辑误判风险
  3. 玩家与堆垛机的碰撞体产生物理分离力,导致被推出

具体修复步骤

1. 修正父对象设置时的坐标保持

强制保持玩家世界坐标不变,避免局部坐标系转换导致的偏移:

public void AttachPlayerToSelf()
{
    // 记录玩家当前世界坐标和旋转
    Vector3 playerWorldPos = FirstPersonMovement.S.transform.position;
    Quaternion playerWorldRot = FirstPersonMovement.S.transform.rotation;
    
    // 先禁用玩家移动组件
    joueurPCGO.GetComponent<FirstPersonMovement>().enabled = false;
    
    // 清空刚体速度,避免残留物理力影响
    Rigidbody playerRb = FirstPersonMovement.S.rigidbody;
    playerRb.isKinematic = true;
    playerRb.velocity = Vector3.zero;
    playerRb.angularVelocity = Vector3.zero;
    
    // 设置父对象,保持世界坐标不变
    joueurPCGO.transform.SetParent(transform, worldPositionStays: true);
    
    // 手动同步位置(防止自动计算出错)
    joueurPCGO.transform.SetPositionAndRotation(playerWorldPos, playerWorldRot);
    
    Debug.Log("position after attach : " + FirstPersonMovement.S.transform.position);
}

2. 完善触发器状态逻辑

添加OnTriggerExit重置状态,避免状态一直为true:

private void OnTriggerStay(Collider other)
{
    // 增加标签判断,确保仅玩家触发
    if (other.CompareTag("Player"))
        isPlayerOnSide = true;
}

private void OnTriggerExit(Collider other)
{
    if (other.CompareTag("Player"))
        isPlayerOnSide = false;
}

3. 避免碰撞体物理分离

设置父对象前临时关闭玩家碰撞体,防止物理引擎强制分离重叠碰撞体:

public void AttachPlayerToSelf()
{
    Vector3 playerWorldPos = FirstPersonMovement.S.transform.position;
    Quaternion playerWorldRot = FirstPersonMovement.S.transform.rotation;
    
    joueurPCGO.GetComponent<FirstPersonMovement>().enabled = false;
    
    // 临时关闭玩家碰撞体
    Collider playerCol = joueurPCGO.GetComponent<Collider>();
    playerCol.enabled = false;
    
    Rigidbody playerRb = FirstPersonMovement.S.rigidbody;
    playerRb.isKinematic = true;
    playerRb.velocity = Vector3.zero;
    
    joueurPCGO.transform.SetParent(transform, true);
    joueurPCGO.transform.SetPositionAndRotation(playerWorldPos, playerWorldRot);
    
    // 延迟一帧开启碰撞体,避开当前帧物理计算
    Invoke(nameof(EnablePlayerCollider), 0.01f);
}

private void EnablePlayerCollider()
{
    joueurPCGO.GetComponent<Collider>().enabled = true;
}

4. 检查堆垛机物理设置

  • 确认堆垛机的非触发碰撞体(如机身)与玩家碰撞体无重叠
  • 若堆垛机带有刚体,设置其为运动学,避免父对象物理状态影响玩家

内容的提问来源于stack exchange,提问作者Aikkyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 23:45:43