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

Unity 6中Transform.InverseTransformPoint返回异常值问题排查

Unity中Transform.InverseTransformPoint异常波动问题解答

问题背景

在Unity 6000.0.32f1版本开发2D Game Jam游戏时,尝试通过每帧更新敌人旋转使其朝向玩家,玩家通过鼠标位移夹角跟随鼠标移动。使用Transform.InverseTransformPoint计算玩家相对敌人的本地位置时,返回值在预期值与异常值(x轴为0,y轴接近预期x轴数值)之间交替波动,相关代码如下:

using System;
using UnityEngine;

public class Enemy : MonoBehaviour {
    Player player;

    void Start () {
        player = FindFirstObjectByType<Player>();
    }

    void Update () {
        EnemyAI();
    }

    void EnemyAI () {
        if (player == null) return;
        Vector3 playerPos = player.gameObject.transform.position;
        
        // Look at Player
        Debug.Log("Enemy Player Position: " + playerPos);
        Vector3 playerPosRel = transform.InverseTransformPoint(playerPos);
        Debug.Log("Enemy Player Position Relative: " + playerPosRel);
        float rotationAngle = playerPosRel.x < Mathf.Epsilon ? 0 :
        Mathf.Atan(playerPosRel.y/playerPosRel.x) * Mathf.Rad2Deg;
        Debug.Log("Enemy Rotation Degrees: " + rotationAngle);
        
       
        transform.rotation = Quaternion.Euler(
            0,
            0,
            Mathf.Sign(playerPosRel.x) < 0 ?
            90 + rotationAngle : 
            -90 + rotationAngle
        );
        
        
        // Approach Player
        transform.position = Vector3.Lerp(
            transform.position, 
            playerPos, 
            Time.deltaTime
        );
    }
}

1. 为什么InverseTransformPoint会返回异常值?

核心原因是同一帧内连续修改敌人的旋转与位置,导致Transform状态不稳定:

  • 先通过InverseTransformPoint计算相对位置,接着修改敌人的rotation,直接改变了敌人的本地坐标系方向;
  • 随后用Vector3.Lerp移动敌人位置,导致下一帧计算时,敌人的Transform(位置+旋转)已发生非预期的连续变化;
  • 加上用Mathf.Atan计算角度时未处理象限问题,旋转逻辑本身存在误差,进一步加剧了坐标系波动,最终导致InverseTransformPoint的结果交替出现异常。

2. InverseTransformPoint的工作原理

Transform.InverseTransformPoint的作用是将世界空间中的点转换为当前物体本地空间下的坐标,计算流程为:

  1. 计算世界点与物体世界位置的偏移向量:worldOffset = worldPoint - transform.position;
  2. 用物体世界旋转的逆矩阵旋转该偏移向量,抵消物体自身旋转的影响;
  3. 如果物体有缩放,将旋转后的向量除以物体的缩放因子;
  4. 最终得到以物体自身为原点、以物体旋转后的坐标轴为方向的本地空间坐标。

3. 不依赖InverseTransformPoint的相对位置计算方法

方法1:直接计算世界空间相对偏移

如果不需要本地空间坐标,仅用于计算朝向或移动,直接用世界坐标相减即可:

Vector3 playerPosRel = playerPos - transform.position;

这得到的是敌人世界空间下,玩家相对于敌人的位置偏移向量。

方法2:手动转换到本地空间(无需InverseTransformPoint)

如果确实需要本地空间的相对位置,可通过逆旋转实现(无缩放场景下等价于InverseTransformPoint):

Vector3 worldOffset = playerPos - transform.position;
Vector3 localOffset = Quaternion.Inverse(transform.rotation) * worldOffset;

优化后的朝向逻辑(无需InverseTransformPoint)

针对敌人朝向玩家的需求,直接用世界空间偏移计算角度更简单可靠,推荐使用Mathf.Atan2处理所有象限的角度计算:

void EnemyAI () {
    if (player == null) return;
    Vector3 playerPos = player.gameObject.transform.position;
    
    // 计算世界空间下的方向向量
    Vector3 direction = playerPos - transform.position;
    // 计算朝向角度(Atan2自动处理象限)
    float targetAngle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    // 设置旋转
    transform.rotation = Quaternion.Euler(0, 0, targetAngle);
    
    // 靠近玩家
    transform.position = Vector3.Lerp(transform.position, playerPos, Time.deltaTime);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:05:14