Понимание Unity's GameObject.Find (), GetComponent () и переработка объектов - PullRequest
0 голосов
/ 15 октября 2018

Новое в единице.

Итак, я создал простую анимацию мгновенных частиц, которая должна отображаться на оружии противника, когда игрок приближается к нему, имитируя выстрел без фактической пули.Однако в этой части я получаю исключение нулевой ссылки muzzleFlash.Play(); Я полагаю, это потому, что на самом деле я не получаю флэш-компонент дульной части в функции запуска с кодом, который у меня есть, на самом деле я знаю, что это после перехода в режим отладки Iвыяснил.Мне действительно трудно понять, как получить доступ к этому компоненту.Ниже мой код, и я также публикую изображение моей иерархии.Заранее спасибо.

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

public class StaticShootingEnemy : MonoBehaviour
{

    [SerializeField] private float _range = 12f;
    private Transform _player;

    private bool _alive;
    private float _distance;
    private ParticleSystem muzzleFlash;

    // Use this for initialization
    void Start()
    {
        _player = GameObject.Find("Player").transform;
        _alive = true;
        muzzleFlash = (ParticleSystem)this.gameObject.GetComponent("muzzleFLash");

    }

    // Update is called once per frame
    void Update()
    {
        _distance = Vector3.Distance(this.transform.position, _player.transform.position);
        if (_alive && _distance < _range)
            AttackPlayer();
    }


    private void AttackPlayer()
    {
        //Turning enemy to look at player
        transform.LookAt(_player);
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;
        if (Physics.SphereCast(ray, 0.75f, out hit))
        {
            //TODO: Fix enemy shooting fast when gettting close to him.
            GameObject hitObject = hit.transform.gameObject;
            if (hitObject.GetComponent<PlayerController>())
            {
                muzzleFlash.Play();
                Debug.Log("Player Hit!");
            }
            else
                muzzleFlash.Stop();
        }
    }

    public void SetAlive(bool alive)
    {
        _alive = alive;
    }

}

Hierarchy

Ответы [ 3 ]

0 голосов
/ 15 октября 2018

На каком компоненте находится скрипт staticshootingenemy?если он не находится в том же компоненте, что и система частиц, то он не найдет его, потому что this.gameObject.GetComponent ("muzzleFLash") не существует в этом компоненте.Вы можете использовать GameObject.Find ("muzzleFLash") для поиска системы частиц.

0 голосов
/ 17 октября 2018

Итак, вернемся к вашему комментарию, вы могли бы реализовать что-то вроде пула для ваших мордочек.

public class MuzzleFlashEffect : MonoBehaviour
{
    [SerializeField] private ParticleSystem particleEffect;
    private Queue<MuzzleFlashEffect> poolQueue;

    public void SetPoolQueue(Queue<MuzzleFlashEffect> queue)
    {
        poolQueue = queue;
    }

    public void Play()
    {
        StartCoroutine(Playing());
    }

    private IEnumerator Playing()
    {
        particleEffect.Play();

        while (particleEffect.isPlaying)
        {
            yield return null; // wait until particle animation is done, then recycle effect
        }

        particleEffect.Stop();
        poolQueue.Enqueue(this);  // recycle this effect
    }

    // you can do the same thing for Animation as well, or even write some abstract PoolableVFX class that would be usefull for Animation , ParticleSystems etc.. 
}

//assume you have some game controller that manage what is going on in the scene
public class GameController : MonoBehaviour
{
    [SerializeField] private MuzzleFlashEffect muzzleFlashPrefab;
    private Queue<MuzzleFlashEffect> poolQueue = new Queue<MuzzleFlashEffect>(10); // 10 is enough i guess and it's good to set it at instantiation to avoid memory fragmentation

    private MuzzleFlashEffect GetMuzzleFlash(Vector3 pos, Quaternion rot)
    {
        MuzzleFlashEffect muzzleFlash;

        // if we already have some effects, then play them, otherwise make a new one and recycle it then
        if (poolQueue.Count > 0)
        {
            muzzleFlash = poolQueue.Dequeue();
        }
        else
        {
            muzzleFlash = Instantiate(muzzleFlashPrefab);
            muzzleFlash.SetPoolQueue(poolQueue);
        }

        muzzleFlash.transform.position = pos;
        muzzleFlash.transform.rotation = rot;

        return muzzleFlash;
    }

    void Update()
    {
        // your fancy logic ...


        GameObject mutantGunEnd = new GameObject("mutant");
        //assume that here you want your muzzle flash effect, so you do:

        var muzzleFlash = GetMuzzleFlash(mutantGunEnd.transform.position, mutantGunEnd.transform.rotation); // or you might want to pass mutantGunEnd.transform.forward instead, it depends... 
        muzzleFlash.Play();


        // your fancy logic ...
    }
}

Итак, в этом случае у вас есть только столько экземпляров ParticleEffect, сколько вам нужно, и экономия некоторых ресурсов.Вы также можете создать универсальный общий пул для любого типа объекта, который вы хотите переработать.(вы хотите перерабатывать вместо создания экземпляра, потому что создание экземпляра стоит очень дорого).Мб, это немного излишне, но я просто хотел поделиться с вами, как бы я подумал об этом здесь

0 голосов
/ 15 октября 2018

Возможно, у вас есть объект "muzzleFlash" в качестве дочернего объекта, к которому прикреплен ваш скрипт.Итак, в этом случае вам лучше иметь ссылку на ваш объект ParticleSystem, который называется muzzleFlash.

[SerializeField] private ParticleSystem muzzleFlash; // drag and drop your ParticleSystem muzzleFlash in inspector

или, по крайней мере, вы можете найти этот muzzleFlash, например,

GameObject muzzleFlashObj = GameObject.Find("muzzleFlash"); ParticleSystem muzzleFlash = muzzleFlashObj.GetComponent<ParticleSystem>();

В вашем случае это null, потому что, вероятно, нет компонента, который называется MuzzleFlash для этого объекта.Компонент, который вы хотите получить, - ParticleSystem.

...