Проблема Raycast с точным определением хит-пойнта в игре Unity 2DC#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Проблема Raycast с точным определением хит-пойнта в игре Unity 2D

Сообщение Anonymous »

В настоящее время я разрабатываю 2D-шутер с видом сверху в Unity, где я использую рейкастинг для механики стрельбы. Моя цель — создать визуальные эффекты точно в той точке, где луч попадает в коллайдер противника. Однако у меня возникли проблемы с точностью обнаружения попаданий, и я надеюсь получить некоторую информацию от сообщества.
  • Тип игры: 2D-шутер с видом сверху.
  • Цель: создавать эффекты именно в той точке, где луч попадает в коллайдер противника.
  • Настройка:

    Код: Выделить всё

      1. Enemies have 2D colliders.
    
    2. The player shoots rays using Physics2D.Raycast.
    
    3. Effects are spawned using an ObjectPool.
    
Текущие наблюдения:

Проблемы с обнаружением попаданий: Рейкаст не регистрирует попадание в том месте, где оно должно. Я проверил, что вражеский слой назначен правильно и что у врагов есть соответствующие 2D-коллайдеры.
Эффект создания: Функция InstantiateHitEffect помещает эффект удара в неправильную позицию (всегда создается в центре врага). Точка попадания теоретически должна быть точной точкой контакта на коллайдере, но кажется, что это не так.
Отладка и журналы: Я добавил журналы, чтобы проверить hit.point, вектор направления и маска слоя. Результат соответствует ожиданиям, но проблема остается.
Пул объектов: Настройка пула объектов проверена и работает, и я могу подтвердить, что все правильно. префабы создаются.
Рассмотрены потенциальные проблемы:
Проблемы с точностью: Интересно если есть проблема с точностью чисел с плавающей запятой, но расстояния довольно малы, поэтому это кажется маловероятным.
Настройка коллайдера: Может ли проблема быть связана с тем, как на врагов установлены коллайдеры? Это стандартные 2D-коллайдеры, и проблем с их обнаружением быть не должно.
Маска слоя: Вражеский слой настроен так, чтобы включать только вражеские коллайдеры, и Я проверял эту настройку несколько раз.
Скриншоты:
Я включил скриншоты, показывающие настройку сцены, настройки инспектора для соответствующих игровых объектов. и консоль регистрируется во время проблемы. Это обеспечит визуальный контекст, позволяющий лучше понять проблему.
Зеленая линия — это то место, куда я целюсь, а синяя линия — то место, где движок обнаруживает попадание и активирует эффекты частиц.
Пример установки вражеского коллайдера

Код: Выделить всё

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

public class PlayerShooting : MonoBehaviour
{
public GameObject hitEffectPrefab;
public GameObject bulletEffectPrefab;
public Transform particleSpawnPoint;
public float shootingRange = 5f;
public LayerMask enemyLayer;
public float fireRate = 1f;
public int damage = 10;

private Transform targetEnemy;
private float nextFireTime = 0f;
private ObjectPool objectPool;

private void Start()
{
objectPool = FindObjectOfType();
if (objectPool == null)
{
Debug.LogError("ObjectPool not found in the scene.  Ensure an ObjectPool component is present and active.");
}
}

private void Update()
{
DetectEnemies();
if (targetEnemy != null)
{
if (Time.time >= nextFireTime)
{
ShootAtTarget();
nextFireTime = Time.time + 1f / fireRate;
}
}
}

private void DetectEnemies()
{
RaycastHit2D hit = Physics2D.Raycast(particleSpawnPoint.position, particleSpawnPoint.up, shootingRange, enemyLayer);
if (hit.collider != null)
{
targetEnemy = hit.collider.transform;
}
else
{
targetEnemy = null;
}
}

private void ShootAtTarget()
{
if (targetEnemy == null)
{
Debug.LogError("targetEnemy is null");
return;
}

Vector3 direction = (targetEnemy.position - particleSpawnPoint.position).normalized;
Debug.Log($"Shooting direction: {direction}");

RaycastHit2D hit = Physics2D.Raycast(particleSpawnPoint.position, direction, shootingRange, enemyLayer);
if (hit.collider != null)
{
BaseEnemy enemy = hit.collider.GetComponent();
if (enemy != null)
{
enemy.TakeDamage(damage);
}

// Debug log to check hit point
Debug.Log($"Hit point: {hit.point}, Enemy: {hit.collider.name}");

// Visual effect for bullet movement
InstantiateBulletEffect("BulletEffect", particleSpawnPoint.position, hit.point);

// Visual effect at point of impact
InstantiateHitEffect("HitEffect", hit.point);
}
else
{
Debug.Log("Missed shot.");
}
}

private void InstantiateBulletEffect(string tag, Vector3 start, Vector3 end)
{
GameObject bulletEffect = objectPool.GetObject(tag);
if (bulletEffect != null)
{
bulletEffect.transform.position = start;

TrailRenderer trail = bulletEffect.GetComponent();
if (trail != null)
{
trail.Clear(); // Clear the trail data to prevent old trail artifacts
}

bulletEffect.SetActive(true);
StartCoroutine(MoveBulletEffect(bulletEffect, start, end));
}
else
{
Debug.LogError($"{tag} effect is null. Check ObjectPool settings and prefab assignment.");
}
}

private void InstantiateHitEffect(string tag, Vector3 position)
{
GameObject hitEffect = objectPool.GetObject(tag);
if (hitEffect != null)
{
Debug.Log($"Setting hit effect position to: {position}");

hitEffect.transform.position = position;
hitEffect.SetActive(true);
}
else
{
Debug.LogError($"{tag} effect is null.  Check ObjectPool settings and prefab assignment.");
}
}

private IEnumerator MoveBulletEffect(GameObject bulletEffect, Vector3 start, Vector3 end)
{
float duration = 0.1f; // Adjust this to match the speed of your bullet visual effect
float time = 0;

while (time < duration)
{
bulletEffect.transform.position = Vector3.Lerp(start, end, time / duration);
time += Time.deltaTime;
yield return null;
}

bulletEffect.transform.position = end;
bulletEffect.SetActive(false);
}

private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(transform.position, shootingRange);

Gizmos.color = Color.green;
Gizmos.DrawLine(particleSpawnPoint.position, particleSpawnPoint.position + particleSpawnPoint.up * shootingRange);
}

public void IncreaseDamage(int amount)
{
damage += amount;
}

public void IncreaseFireRate(float amount)
{
fireRate += amount;
}

public void IncreaseBulletRange(float amount)
{
shootingRange += amount;
}
}

Проблемы с обнаружением попаданий: Рейкаст не регистрирует попадание в том месте, где оно должно. Я проверил, что вражеский слой назначен правильно и что у врагов есть соответствующие 2D-коллайдеры.
Эффект создания: Функция InstantiateHitEffect помещает эффект удара в неправильную позицию (всегда создается в центре врага). Точка попадания теоретически должна быть точной точкой контакта на коллайдере, но кажется, что это не так.
Отладка и журналы: Я добавил журналы, чтобы проверить hit.point, вектор направления и маска слоя. Результат соответствует ожиданиям, но проблема остается.
Пул объектов: Настройка пула объектов проверена и работает, и я могу подтвердить, что все правильно. префабы создаются.

Подробнее здесь: https://stackoverflow.com/questions/788 ... ty-2d-game
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение
  • При вращении объекта вокруг целевого объекта радиус не выглядит очень точным на 100%. как сделать радиус точным?
    Anonymous » » в форуме C#
    0 Ответы
    91 Просмотры
    Последнее сообщение Anonymous
  • Unity Raycast проходит сквозь стены
    Anonymous » » в форуме C#
    0 Ответы
    68 Просмотры
    Последнее сообщение Anonymous
  • Unity Raycast не распознает столкновение
    Anonymous » » в форуме C#
    0 Ответы
    9 Просмотры
    Последнее сообщение Anonymous
  • Unity Raycast не распознает столкновение
    Anonymous » » в форуме C#
    0 Ответы
    19 Просмотры
    Последнее сообщение Anonymous
  • Unity Raycast не распознает столкновение
    Anonymous » » в форуме C#
    0 Ответы
    10 Просмотры
    Последнее сообщение Anonymous

Вернуться в «C#»