Little Help please

Not sure what is going on here but my code doesn’t seem to be instantiating my damage effect on impact after fixing the null ref.

Here is what I’m seeing

Here is what I expect to see

Relevant Code

  • Spell (scriptable object)
public void CastSpell(Transform[] hands, Transform target, int level)
        {
            if (spellLevel < level) { return; }
            Vector3 startLoc = hands[0].position;
            GameObject spellObject = Instantiate(effectPrefab, startLoc, Quaternion.identity);
            CastSpell spellInstance = spellObject.GetComponent<CastSpell>();
            spellObject.transform.parent = tempObject;
            spellInstance.SetTarget(target.GetComponent<Health>(), cantMiss);
            spellInstance.SetArea(areaOfEffect);
            spellInstance.SetRange(GetRange(level));
            spellInstance.SetSpeed(speed);
            spellInstance.SetDamage(CalculateDamage(level));
            spellInstance.SetType(attackType.ToString(), numberOfTargets);
            // TODO decrease mana/magical energy count in inventory
  • CastSpell (spell effects)
using System.Collections.Generic;
using RPG.Core;
using UnityEngine;

namespace RPG.Magic
{
    public class CastSpell : MonoBehaviour
    {
        [SerializeField] ParticleSystem castingEffect = null;
        [SerializeField] ParticleSystem damageEffect = null;

        float areaOfEffct = 0f;
        string attackType = "";
        int damage = 0;
        float distanceTraveled = 0;
        bool isHoming = false;
        int numberOfTarges = 0;
        float range = 0f;
        float speed = 0f;
        Health target = null;
        Transform tempObject = null;


    // Basic Methods
        private void Awake()
        {
            tempObject = FindObjectOfType<TempObject>().transform;
        }

        void Start()
        {
            if (target) { transform.LookAt(GetPosition()); }
        }

        void Update()
        {
            if (isHoming) { transform.LookAt(GetPosition()); }
            Vector3 pos1 = transform.position;
            transform.Translate(Vector3.forward * speed * Time.deltaTime);
            Vector3 pos2 = transform.position;
            distanceTraveled += Vector3.Distance(pos2, pos1);
            if (distanceTraveled > range)
            {
                if(attackType != "area") {Destroy(gameObject); }
                else { DealAreaDamage(); }
            }
        }
        
        
    // Setter Methods
        public void SetArea(float area) { areaOfEffct = area; }

        public void SetDamage(int dmg) { damage = dmg; }

        public void SetRange(float rng)
        {
            range = rng;;
        }

        public void SetTarget(Health health, bool homing)
        {
            target = health;
            isHoming = homing;
        }

        public void SetType(string attack, int targets)
        {
            attackType = attack;
            numberOfTarges = targets;
        }
        
        public void SetSpeed(float spd) { speed = spd; }

    
    // Private Methods
        private Vector3 GetPosition()
        {
            // TODO Allow for targeting AoE spells without specifying an opponent
            CapsuleCollider collider = target.GetComponent<CapsuleCollider>();
            Vector3 offset;
            if (collider) { offset = Vector3.up * collider.height * 0.66f; }
            else { offset = new Vector3(0f, 1f, 0f); }
            return target.transform.position + offset;
        }

        private void OnTriggerEnter(Collider other)
        {
            Health candidate = other.GetComponent<Health>();
            if (candidate != target || candidate.GetIsDead()) { return; }
            castingEffect.Stop();
            if (attackType == "area") { DealAreaDamage(); }
            else
            {
                InstantiateDamageEffect();
                candidate.TakeDamage(damage);
            }
            Destroy(gameObject);
        }

        private void DealAreaDamage()
        {
            // TODO add method to choose a number of random targets up to the numberOfTargets
            foreach(Health target in GetTargets())
            {
                Vector3 pos1 = transform.position;
                Vector3 pos2 = target.transform.position;
                float damageModifier = 1 - (Vector3.Distance(pos1, pos2)/areaOfEffct);
                target.TakeDamage((int)(damageModifier * damage));
            }
        }

        private List<Health> GetTargets()
        {
            InstantiateDamageEffect();
            List<Health> targets = new List<Health>();
            foreach (Health candidate in FindObjectsOfType<Health>())
            {
                float rangeToTarget = Vector3.Distance(candidate.transform.position, transform.position);
                if (rangeToTarget <= areaOfEffct)
                {
                    targets.Add(candidate);
                }
            }
            return targets;
        }

        private void InstantiateDamageEffect()
        {
            Debug.Log("Instantiating damageEffect.");
            ParticleSystem fx = Instantiate(damageEffect, transform);
            //fx.transform.parent = tempObject;
        }
    }
}

What I’ve tried:

  • was originally starting with the effect built into the fireball prefab with ‘play on awake’ ticked off. have since switched to instantiating as a separate object
  • was parenting the explosion to an empty game object and commented that line out.
  • tried using particlesystem.emmission.enabled but kept getting errors in the code (even with a direct copy and paste from Unity docs)
  • tried using different shaders
  • tried using bursts
  • prior to switching the targets from an array to a list it worked fine so moved the call for the effect from after declaring the targets variable to before doing so

Just from skimming through this: I could be wrong obviously, but this may be your problem:
You’re instantiating a component, but a component can’t exist without a game object. Not sure if this works and the engine is automatically creating an empty game object for this or not!?

If that’s not the problem:
What does happen?
Is your effect game object spawning but the effect doesn’t play? Is anything being spawned at all?

Also: Have you tried putting in simple Debug.Log()/print() statements all ofver the code to check which part is actually being called and to confirm the validity of some of your references in the code?

Chris

thanks for your reply Chris,

It took me a couple of days to realize but it was indeed the instantiation itself that was failing without throwing any kind of warning or message. Not because it lacked a game object, but because I was trying to use the transform of the instantiating object without getting the position and rotation separately.

here is what I had:

ParticleSystem fx = Instantiate(damageEffect, transform);

here is how I changed it:

ParticleSystem fx = Instantiate(damageEffect, transform.position, Quaternion.identity);

The first version actually does instantiate the object, but it doesn’t do it at a specific location. It does, however, parent itself to the given transform.
So it should’ve been instantiated, but when you (probably?) destroyed your actual skill effect and the damage effect was parented to that, it was destroyed as well.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.