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

如何让2D箭头朝向3D物体?COD风格伤害指示器旋转偏移问题

解决伤害指示器旋转偏移(玩家转向后90度偏差)问题

问题描述

我正在制作类似《使命召唤》(Call of Duty)的伤害指示器:玩家受到攻击时,屏幕中央的箭头会指向攻击来源。目前遇到的问题是:当玩家朝向正前方(-Z轴)时,指示器旋转正常,左右移动也没问题,但玩家自身旋转后,指示器就会出现90度偏差,旋转逻辑失效。

原代码

func _physics_process(delta):
    if target_position == Vector3.ZERO: return
    
    rotate_to_target(target_position)

func set_target(target : Vector3) -> void:
    target_position = target

func rotate_to_target(target : Vector3) -> void:
    var player_position = PlayerProperties.player.global_position
    # Get the direction for the rotation
    var direction = (player_position - target).normalized()
    
    # Get the players rotation to influience the indicator
    direction = PlayerProperties.player.global_transform.basis * direction
    
    # Convert the direction into a angle that can be used
    # And offset the angle to follow the correct oritation
    var angle = atan2(direction.z,direction.x) - PI * 0.5
    
    # Apply rotation to the damage indicator
    damage_indicator.rotation = angle

问题分析与修正

问题出在三个核心逻辑上:

  1. 方向向量搞反了:你计算的player_position - target是玩家指向攻击来源的反方向,指示器应该指向攻击来源,所以要改成target - player_position。
  2. 空间转换方向错误:用global_transform.basis * direction是把局部空间方向转成世界空间,但我们需要把世界空间的攻击方向转成玩家局部空间,所以得用basis.inverse()来做反向转换。
  3. 角度计算参数不匹配:原代码的atan2参数和偏移量对应错误,导致玩家旋转后角度偏差。

修正后的代码

func _physics_process(delta):
    if target_position == Vector3.ZERO: return
    
    rotate_to_target(target_position)

func set_target(target : Vector3) -> void:
    target_position = target

func rotate_to_target(target : Vector3) -> void:
    var player_position = PlayerProperties.player.global_position
    # 获取攻击来源相对于玩家的世界空间方向
    var direction = (target - player_position).normalized()
    
    # 将世界方向转换为玩家局部空间,适配玩家自身旋转
    direction = PlayerProperties.player.global_transform.basis.inverse() * direction
    
    # 计算局部空间下的旋转角度(适配-Z为正前方的设定)
    var angle = atan2(direction.x, direction.z)
    
    # 应用旋转到伤害指示器
    damage_indicator.rotation = angle

关键修正点说明

  • 方向向量修正:target - player_position直接得到攻击来源在世界空间中相对于玩家的位置方向,确保指示器指向正确的来源。
  • 空间转换:basis.inverse()把世界空间的方向转换成玩家局部空间的方向,这样玩家无论怎么旋转,局部空间的正前方始终是玩家当前朝向,角度计算会以玩家自身为基准。
  • 角度计算:用atan2(direction.x, direction.z)计算局部空间内的角度,刚好匹配玩家-Z为正前方的设定,不需要额外的PI偏移。如果你的指示器初始朝向不对,可以根据UI布局微调偏移(比如加PI或PI/2)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:30:23