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

Unity复刻Visage/Amnesia开门逻辑:半开后从另一侧关闭旋转重置问题求助

解决方案建议
  • 跟踪门的实时旋转基准
    原方案的核心问题是始终以初始0度作为旋转参考,而非门的当前实际角度。每次玩家触发门交互时,先记录门的当前Y轴旋转值作为新的基准点,后续所有鼠标拖动的旋转计算都基于这个实时基准,不再依赖固定初始值。
    示例代码:

    private float currentBaseRotation;
    
    void OnStartInteract()
    {
        // 记录当前门的旋转作为基准
        currentBaseRotation = transform.localEulerAngles.y;
    }
    
  • 判断玩家与门的相对侧
    必须明确玩家处于门的正面还是背面,才能保证拖动方向与门的运动逻辑匹配。通过计算玩家位置与门正面法线的点积判断:点积为正表示在正面,为负则在背面。根据这个结果反转鼠标拖动对应的旋转方向,确保无论在哪一侧,“拖向自己”都是开门、“拖离自己”都是关门。
    示例代码:

    bool IsPlayerOnFrontSide(Transform player)
    {
        Vector3 doorToPlayer = player.position - transform.position;
        float dot = Vector3.Dot(transform.forward, doorToPlayer.normalized);
        return dot > 0f;
    }
    
  • 基于当前角度设置旋转范围
    给门设置合理的旋转上下限时,要以实时基准为中心(比如基准±90度),而非固定的0度±90度。同时用平滑插值更新旋转,避免跳变:

    // 计算目标旋转(基于基准和鼠标输入)
    float targetRotation = currentBaseRotation + (mouseInput * rotationSpeed * (isFrontSide ? 1 : -1));
    // 限制在合理范围
    targetRotation = Mathf.Clamp(targetRotation, currentBaseRotation - 90f, currentBaseRotation + 90f);
    // 平滑应用旋转
    transform.localEulerAngles = Vector3.Lerp(transform.localEulerAngles, new Vector3(0, targetRotation, 0), Time.deltaTime * 5f);
    
  • 移除强制重置旋转的代码
    检查原方案中是否存在交互开始时将门旋转强制重置为0度的逻辑(比如transform.localEulerAngles = Vector3.zero;),直接删除这类语句,替换为记录当前旋转基准的代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:35:11