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

Unity 2D中Shoot函数内Transform.position返回(0,0,0),子弹生成异常

问题:子弹生成在场景中心而非角色位置

点击按钮调用Shoot()函数时,本该在角色位置生成子弹,结果生成在场景中心。在PlayerShooter脚本的Start()方法中能获取到正确的transform.position值,但点击按钮触发Shoot()时,该值返回(0,0,0)。发现子弹是在预制体的位置生成,而非实例化角色对象的位置,求修复方法。


PlayerShooter脚本

using Photon.Pun;
using UnityEngine;

public class PlayerShooter : MonoBehaviour
{
    [SerializeField] private GameObject _bullet;
    [SerializeField] private float _distanceMultiplier;
    public void Shoot()
    {
        if (PhotonNetwork.PlayerList.Length > 1)
        {
            PhotonNetwork.Instantiate(_bullet.name, transform.position, transform.rotation);
        }
    }
}

角色移动脚本(PlayerMover)

using UnityEngine;
using Photon.Pun;

[RequireComponent(typeof(Rigidbody2D), typeof(CapsuleCollider2D))]
public class PlayerMover : MonoBehaviour
{
    [SerializeField] private float _speepMoving, _speedRotation;
    private Rigidbody2D _rigidbody;
    private Vector2 _direction;
    private PhotonView _view;
    [HideInInspector] public FixedJoystick joystick;
    private void Start()
    {
        _view = GetComponent<PhotonView>();
        _rigidbody = GetComponent<Rigidbody2D>();
    }
    private void FixedUpdate()
    {
        if (_view.IsMine && PhotonNetwork.PlayerList.Length > 1)
        {
            _rigidbody.velocity = new Vector2(joystick.Horizontal * _speepMoving, joystick.Vertical * _speepMoving);
            RotatePlayer();
        }
    }
    private void RotatePlayer()
    {
        _direction = new Vector2(joystick.Horizontal, joystick.Vertical);
        if (_direction != Vector2.zero)
        {
            Quaternion toRotation = Quaternion.LookRotation(Vector3.forward, _direction);
            _rigidbody.MoveRotation(Quaternion.Lerp(transform.rotation, toRotation, _speedRotation * Time.deltaTime));
        }
    }
}

修复方案

问题根源

核心原因是按钮绑定的是预制体上的Shoot()方法,而非场景中实例化后的角色对象。点击按钮时调用的是预制体(默认位置为(0,0,0))的方法,自然会在场景中心生成子弹。另外缺少本地玩家权限校验,可能引发跨客户端的同步问题。

具体修复步骤

  1. 修正按钮事件绑定

    • 不要在Project面板的预制体Inspector中绑定按钮事件,而是在运行时找到场景中的角色实例,将按钮的OnClick事件拖拽绑定到该实例的PlayerShooter -> Shoot()方法上。
    • 或者通过代码动态绑定:在角色的Start()方法中,找到UI按钮组件,添加点击事件监听:
      // 在PlayerShooter的Start方法中添加
      void Start()
      {
          var shootButton = GameObject.Find("ShootButton").GetComponent<UnityEngine.UI.Button>();
          if(shootButton != null)
          {
              shootButton.onClick.AddListener(Shoot);
          }
      }
      
  2. 添加本地玩家权限校验
    修改Shoot()方法,确保只有当前玩家控制的角色才能触发射击:

    public void Shoot()
    {
        var photonView = GetComponent<PhotonView>();
        // 仅本地玩家且房间内玩家数大于1时执行射击
        if (photonView != null && photonView.IsMine && PhotonNetwork.PlayerList.Length > 1)
        {
            PhotonNetwork.Instantiate(_bullet.name, transform.position, transform.rotation);
        }
    }
    
  3. 检查子弹预制体配置

    • 确保子弹预制体已添加到PhotonServerSettings的Registered Prefabs列表中,否则PhotonNetwork.Instantiate会出现异常。
    • 将子弹预制体的Transform初始位置设为(0,0,0),避免实例化时自带偏移。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 20:17:45