Как можно замедлить только пулю при стрельбе? - PullRequest
0 голосов
/ 29 апреля 2019
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Shooting : MonoBehaviour
{
    [SerializeField]
    private Transform[] firePoints;
    [SerializeField]
    private Rigidbody projectilePrefab;
    [SerializeField]
    private float launchForce = 700f;
    [SerializeField]
    private Animator anim;
    [SerializeField]
    private bool automaticFire = false;
    [SerializeField]
    private bool slowDownEffect = false;

    private bool coroutineEnded = false;

    private void Start()
    {
        anim.SetBool("Shooting", true);
    }

    public void Update()
    {
        if (isAnimationStatePlaying(anim, 0, "AIMING") == true)
        {
            if (Input.GetButtonDown("Fire1") && automaticFire == false)
            {
                if (anim.GetBool("Shooting") == true)
                {
                    anim.Play("SHOOTING");
                    LaunchProjectile();
                }
            }
            else if (Input.GetButtonDown("Fire1") && automaticFire == true)
            {
                automaticFire = false;
            }
            else
            {
                if (Input.GetButtonDown("Fire2"))
                {
                    automaticFire = true;
                }
                if (automaticFire == true)
                {
                    anim.Play("SHOOTING");
                    LaunchProjectile();
                }
            }
        }
    }

    private void LaunchProjectile()
    {
        foreach (var firePoint in firePoints)
        {
            Rigidbody projectileInstance = Instantiate(
                projectilePrefab,
                firePoint.position,
                firePoint.rotation);

            projectileInstance.AddForce(new Vector3(0, 0, 1) * launchForce);
            StartCoroutine(AddDrag(5, 5, projectileInstance));

            if (coroutineEnded == true)
            {
                projectileInstance.gameObject.AddComponent<BulletDestruction>().Init();
            }
        }
    }

    IEnumerator AddDrag(float maxDrag, float mul, Rigidbody rb)
    {

        float current_drag = 0;

        while (current_drag < maxDrag)
        {
            current_drag += Time.deltaTime * mul;
            rb.drag = current_drag;
            yield return null;
        }

        rb.velocity = Vector3.zero;
        rb.angularVelocity = Vector3.zero;
        rb.drag = 0;

        coroutineEnded = true;
    }

    bool isAnimationStatePlaying(Animator anim, int animLayer, string stateName)
    {
        if (anim.GetCurrentAnimatorStateInfo(animLayer).IsName(stateName))
            return true;
        else
            return false;
    }
}

Я пытался использовать StartCoroutine для добавления Drag.Проблема в том, что он стреляет в первый булет и первый тип замедления и останавливается в конце, а затем при попытке запустить следующую пулю я получаю исключение:

MissingReferenceException: объект типа 'Rigidbody'был уничтожен, но вы все еще пытаетесь получить к нему доступ.

На линии:

rb.drag = current_drag;

И я не уверен, является ли добавление перетаскивания правильным способом и какие значения мне следуетЯ сдался. Я пробовал 5 и 5.

Идея состоит в том, чтобы замедлять только пули, как эффект замедления.

Я сделал скрипт для замедлений:

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

public class SlowDown : MonoBehaviour
{
    [Header("Overall Slowdown")]
    [Range(0,1f)]
    public float overallSlowdown = 1f;
    [Space(5)]
    [Header("Bullet Time")]
    [Range(0, 50)]
    public float bulletTime = 0.25f;

    private void Update()
    {
        Time.timeScale = overallSlowdown;
    }
}

Но TimeScale замедляет всю игру, и я хочу также иметь возможность замедлять только пули.

1 Ответ

1 голос
/ 29 апреля 2019

Если вы хотите, чтобы что-то случилось в конце сопрограммы, поместите это в конец сопрограммы

private void LaunchProjectile()
{
    foreach (var firePoint in firePoints)
    {
        Rigidbody projectileInstance = Instantiate(
            projectilePrefab,
            firePoint.position,
            firePoint.rotation);

        projectileInstance.AddForce(new Vector3(0, 0, 1) * launchForce);
        StartCoroutine(AddDrag(5, 5, projectileInstance));
    }
}

IEnumerator AddDrag(float maxDrag, float mul, Rigidbody rb)
{
    float current_drag = 0;

    while (current_drag < maxDrag)
    {
        current_drag += Time.deltaTime * mul;
        rb.drag = current_drag;
        yield return null;
    }

    rb.velocity = Vector3.zero;
    rb.angularVelocity = Vector3.zero;
    rb.drag = 0;

    rb.gameObject.AddComponent<BulletDestruction>().Init();
}

Вызов StartCoroutine() не останавливает выполнение метода, в котором он находится, поэтому«ожидание завершения сопрограммы» вне этого метода сопрограммы не имеет смысла (поскольку может быть несколько копий этой сопрограммы!)

Единственное логичное место, чтобы дождаться завершения сопрограммы, - либо внутри другой сопрограммыили внутри метода, который вы ждете.Поскольку объект, который вы хотите изменить, передается в сопрограмму, вставка нужной логики в метод сопрограммы является логическим выбором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...