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

Unity2D仿元气骑士角色向左射击异常问题求助

问题描述

开发类《元气骑士》游戏,采用单摇杆控制角色与武器,参考原作操作逻辑。角色朝右时射击正常,朝左时出现以下异常:

  • shotPoint(子弹发射点)未随武器同步翻转,武器在左侧时视觉呈倒置状态;
  • 子弹仅在场景生成但无法正常飞行,疑似刚生成就触发碰撞;
  • 子弹发射后始终朝右飞行,未朝向武器指向方向。

相关代码

Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public Joystick joystick;
    public float speed;

    private Rigidbody2D rb;
    private Vector2 moveInput;
    private Vector2 moveVelocity;
    private Animator anim;

    private bool facingRight = true;

    void Start()
    {
        rb = GetComponent < Rigidbody2D>();
        anim = GetComponent<Animator>();
    }

    void Update()
    {
        moveInput = new Vector2(joystick.Horizontal, joystick.Vertical);
        moveVelocity = moveInput.normalized * speed;

        if (moveInput.x == 0)
        {
            anim.SetBool("isRunning", false);
        }
        else
        {
            anim.SetBool("isRunning", true);
        }

        if(!facingRight && moveInput.x > 0)
        {
            Flip();
        }
        else if(facingRight && moveInput.x < 0)
        {
            Flip();
        }
    }

    void FixedUpdate()
    {
        rb.MovePosition(rb.position + moveVelocity * Time.fixedDeltaTime);
    }

    public void Flip()
    {
        facingRight = !facingRight;
        transform.Rotate(0f, 180f, 0f);
    }
}

Gun.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Gun : MonoBehaviour
{
    public Joystick joystick;
    public float offset;

    public float rotZ;
    private SpriteRenderer spriteRender;
    public GameObject bullet;
    public Transform shotPoint;
    private float timeBtwShots;
    public float startTimeBtwShots;
    private Player player;

    void Start()
    {
        spriteRender = GetComponent<SpriteRenderer>();
        player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
    }

    void Update()
    {
        if (Mathf.Abs(joystick.Horizontal) > 0.001f || Mathf.Abs(joystick.Vertical) > 0.001f)
        {
            rotZ = Mathf.Atan2(joystick.Vertical, joystick.Horizontal) * Mathf.Rad2Deg;
        }

        transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);

        if (rotZ < 90 && rotZ > -90)
        {
            spriteRender.flipY = false;
        }
        else
        {
            spriteRender.flipY = true;

        }

        timeBtwShots -= Time.deltaTime;
    }

    public void ShootButton()
    {
        Instantiate(bullet, shotPoint.position, transform.rotation);
        timeBtwShots = startTimeBtwShots;
    }
}

Bullet.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    public float speed;
    public float lifetime;
    public float distance;
    public int damage;
    public LayerMask whatIsSolid;

    void Start()
    {
        
    }

    void Update()
    {
        RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, transform.right, distance, whatIsSolid);
        if (hitInfo.collider != null)
        {
            if (hitInfo.collider.CompareTag("Enemy"))
            {
                hitInfo.collider.GetComponent<Enemy>().TakeDamage(damage);
            }
            Destroy(gameObject);
        }

        transform.Translate(Vector2.right * speed * Time.deltaTime);
    }
}
问题排查与修复方案

问题1:shotPoint未同步翻转、武器视觉倒置

核心原因:角色翻转使用transform.Rotate(0f,180f,0f)会让武器子物体绕Y轴旋转,与Gun脚本中单独计算的Z轴旋转叠加,导致姿态混乱;同时武器精灵翻转逻辑未考虑角色朝向的影响。

修复代码:

  1. 修改Player的Flip方法,改用X轴缩放实现2D角色翻转(避免子物体旋转冲突):
public void Flip()
{
    facingRight = !facingRight;
    Vector3 scale = transform.localScale;
    scale.x *= -1;
    transform.localScale = scale;
}
  1. 调整Gun脚本的输入方向与翻转逻辑,结合角色朝向修正武器旋转:
void Update()
{
    // 根据角色朝向修正摇杆输入,确保武器方向与视觉一致
    float horizontalInput = joystick.Horizontal * (player.facingRight ? 1 : -1);
    float verticalInput = joystick.Vertical;

    if (Mathf.Abs(horizontalInput) > 0.001f || Mathf.Abs(verticalInput) > 0.001f)
    {
        rotZ = Mathf.Atan2(verticalInput, horizontalInput) * Mathf.Rad2Deg;
    }

    transform.rotation = Quaternion.Euler(0f, 0f, rotZ + offset);
    // 简化精灵翻转判断
    spriteRender.flipY = rotZ < -90 || rotZ > 90;

    timeBtwShots -= Time.deltaTime;
}

问题2:子弹刚生成就碰撞消失

核心原因:shotPoint位置与玩家碰撞体重叠,或Raycast检测范围过大,触发了玩家自身碰撞。

修复方案:

  1. 调整shotPoint在武器子物体中的位置,确保其完全处于玩家碰撞体外;
  2. 在Bullet脚本中跳过玩家自身碰撞检测:
void Update()
{
    RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, transform.right, distance, whatIsSolid);
    if (hitInfo.collider != null)
    {
        // 跳过玩家自身,避免刚生成就销毁
        if (hitInfo.collider.CompareTag("Player")) return;
        if (hitInfo.collider.CompareTag("Enemy"))
        {
            hitInfo.collider.GetComponent<Enemy>().TakeDamage(damage);
        }
        Destroy(gameObject);
    }

    transform.Translate(transform.right * speed * Time.deltaTime);
}

问题3:子弹始终朝右飞行

核心原因:Bullet脚本使用世界空间的Vector2.right作为移动方向,未跟随子弹自身的旋转朝向。

修复代码:
将Bullet的移动逻辑改为使用自身局部空间的右方向,确保与武器指向一致:

// 替换原Translate代码
transform.Translate(transform.right * speed * Time.deltaTime);

若追求更稳定的物理效果,可给子弹添加Rigidbody2D组件,在Gun脚本中直接设置速度:

public void ShootButton()
{
    GameObject bulletObj = Instantiate(bullet, shotPoint.position, transform.rotation);
    Rigidbody2D rb = bulletObj.GetComponent<Rigidbody2D>();
    if(rb != null)
    {
        rb.velocity = transform.right * speed;
    }
    timeBtwShots = startTimeBtwShots;
}

同时移除Bullet脚本Update中的Translate代码,由刚体控制移动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:12:03