#Weird Material null thing

1 messages ยท Page 1 of 1 (latest)

drowsy wharf
#

I can't follow the replies because of so many replies, going to start a thread

daring perch
#

Fair

drowsy wharf
#

๐Ÿ‘

daring perch
#

Try this:
Let's log the ID in the following places:

  1. On startup, on particlePrefab
  2. On the objects that are initialized from ParticlePrefab the first time they are spawned
  3. When Preload is called
  4. When Use is called
drowsy wharf
#

okay "So, where do you actually call Instantiate on the ParticlePrefab?" let me track this down

drowsy wharf
#

I just renamed all particlePrefabs into particleInstances because that is what the component is and its confusing me that I named them differently

#

the five preloaded particles do not match the use ID

#

but the game object the use is being run on, is one of those five

daring perch
#

So, Preload is 3 Use is 4 I'm assuming On Startup is 1. What are the results of 2?

#

When they're first instantiated

drowsy wharf
#

"On the objects that are initialized from ParticlePrefab the first time they are spawned"

daring perch
#

When the five objects are first created

#

Unless they're in the scene at start?

drowsy wharf
#

My brain is getting rigid, I'm struggling to understand that

#

they are spawned by the pool at start

#

the five preloads are they

#

this never gets called though for some reason

#

or wait it is, once, at the end

#

it should be being called 5 times I think?

#

Im going to set it to not make 5 but I was getting even weirder behaviour when I did that before

#

which was only making it harder to dialognose

#

there is only a single one in the entire scene

#

sceratch that there's two for some reason

#

let me see if I can see why

#

I think its because my pool is only 1 big, and it always tries to have extras when being used

#

so that it never has nothing to spawn from the pool

#

okay

#

I removed the code that widens the pool

#

there is only one instance of the particle

#

@daring perch

#

the reason i asked if different components can have different IDs

#

is because when I click the error ID, it takes me to this component

#

which is a component separate from the particle instance, but on the same game object

#

aw fuck maybe this is a Reference vs Value problem

#

im getting it from my global game manager

#

I want to instantiate unique ones though

#

could that be whats wrong??

daring perch
#

Sorry, I had to step away for a bit. I'll read through this real quick

daring perch
daring perch
# drowsy wharf

Is this genericDamageParticle a Prefab or an object in the scene?

drowsy wharf
#

its a prefab in project

daring perch
#

Okay, so, somewhere you're calling Instantiate on that, right?

drowsy wharf
#

Yes

daring perch
#

Can you show that snippet?

drowsy wharf
#

    private void Start()
    {
        InitializePool(itemPoolCount);
        ParticlePoolInstanceManager.Instance.CreateDamageInstance(1, genericDamageParticle); //temp just one instance. 
    }
#

global game manager's start

#

right, sorry

#

the global game manager is making the POOL manager, who then makes the instances within the pool

#

let me find that part

daring perch
#

Yeah, the actual call to Unity's Instantiate

#

We're gonna work our way outward

drowsy wharf
#

    public ParticlePool CreateInstance(int poolsize, ParticleInstance particleInstance)
    {
        if (FindInstance(particleInstance) == null)
        {
            ParticlePool thisInstance = Pool.ExpandPool(this.transform, instanceList, basePrefab); // make one instance of the list.
            thisInstance.gameObject.SetActive(true);
            thisInstance.Initialize(poolsize, particleInstance);
            return thisInstance;
        }
        else
        {
            Debug.LogWarning("Attempted to create particle pool and failed. Did you forget to set a particle instance?");
            return null;
        }
    }
#

I wish the thread screen wasnt so narrow, making it hard to read code

daring perch
#

You can click the thread on the left side in the channel index to open it in the main window

drowsy wharf
#

Oh, thanks, that worked

daring perch
#

I still don't see an Instantiate there

drowsy wharf
#

oh sorry you're right I was misreading initialize

#

here we go

#
    public static T ExpandPool<T>(Transform parent, List<T> pool, T poolObject) where T : UnityEngine.Component
    {
        T instance = Instantiate(poolObject, Vector3.zero, Quaternion.identity);
        instance.gameObject.SetActive(false);
        instance.transform.SetParent(parent);
        pool.Add(instance);
        return instance;
    }
#

actually come to think of it I think you helped me write this function originally

#

like a few months ago, when I was learning about <T>

daring perch
#

Okay, so, this is the single most core bit of code. The closest to Unity's nervous system. Let's start here. Add this right before the return statement:

Debug.Log($"Spawing a copy of {nameof(T)} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");
#

Oh, hang on

#

Let's make this more useful. Editing.

drowsy wharf
#

Okay ๐Ÿ‘

daring perch
#

I think that'll print out what type T is

#

so we can see what class it's instantiating as

drowsy wharf
#

run it after instantiate?

daring perch
#

Yeah, that'll do

drowsy wharf
#

... why does that ID not match the other ones ๐Ÿค”

daring perch
# drowsy wharf

Dang. It didn't give us the actual type. Well, we can still see the values. Is this the only place that line runs in your console?

drowsy wharf
#

oh right ExpandPool has overload methods

daring perch
#

It might be a wholly different pool object. I was hoping nameof(T) would get us what T actually was, but I don't know the syntax for that

drowsy wharf
#

Ill add it to the overload thats probably getting used

#

    public static void ExpandPool<T>(Transform parent, List<T> pool, T poolObject, int size) where T : UnityEngine.Component
    {
        for (int i = 0; i < size; i++)
        {
            T instance = Instantiate(poolObject, Vector3.zero, Quaternion.identity);
            Debug.Log($"Spawing a copy of {nameof(T)} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");
            instance.gameObject.SetActive(false);
            instance.transform.SetParent(parent);           
            pool.Add(instance);
        }
    }

    public static T ExpandPool<T>(Transform parent, List<T> pool, T poolObject) where T : UnityEngine.Component
    {
        T instance = Instantiate(poolObject, Vector3.zero, Quaternion.identity);
        Debug.Log($"Spawing a copy of {nameof(T)} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");
        instance.gameObject.SetActive(false);
        instance.transform.SetParent(parent);
        pool.Add(instance);
        return instance;
    }
#

I dont remember why the overload exists

#

hm it appears to return a value and takes different arguments

#

thats probably a stupid mistake on my part ill make a note to make it not two functions

#

or at least clarify why the same thing is there mostly twice

daring perch
#

It looks like one is for expanding it by many, which is fair, but you should probably just call the second overload inside the loop of the first

drowsy wharf
#

oh right one is a single

#

Riiiiiight its all coming back now

#

the lower one makes the single Pool

#

the upper one makes all the Pool's child instances

#

Ill make a note to clarify that

#

Ah yeah I see what you mean, run the lower one within the loop of the upper one

#

yeah that is smart

#

Ill do it right now

#

well it looks slightly non-trivial so I wont

#

    public static void ExpandPool<T>(Transform parent, List<T> pool, T poolObject, int size) where T : UnityEngine.Component
    {
        for (int i = 0; i < size; i++)
        {
            T instance = Instantiate(poolObject, Vector3.zero, Quaternion.identity);
            Debug.Log($"Spawing a copy of {nameof(T)} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");
            instance.gameObject.SetActive(false);
            instance.transform.SetParent(parent);           
            pool.Add(instance);
        }
    }

    public static T ExpandPool<T>(Transform parent, List<T> pool, T poolObject) where T : UnityEngine.Component
    {
        T instance = Instantiate(poolObject, Vector3.zero, Quaternion.identity);
        Debug.Log($"Spawing a copy of {nameof(T)} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");
        instance.gameObject.SetActive(false);
        instance.transform.SetParent(parent);
        pool.Add(instance);
        return instance;
    }

running this those logs

#

I dont understand why the ID's dont match

daring perch
#

Ah, I figured out something, instead of nameof(T) do typeof(T).FullName

#

That'll let us know what object these are the IDs of

drowsy wharf
#

pool, then instance

daring perch
drowsy wharf
#

wait so how is a particle instance running on awake, let me move to a scene with NOTHING in it

drowsy wharf
#

the selected log is where scene-start ends

#

let me change the code that is returning 18832 to output the name

daring perch
#

Okay, a few things leap out at me:

  1. I have no idea why none of those match -131854
  2. 18832 is still the same even on a new scene. I'm pretty sure that means this is not in the scene
#

I think you're calling Use on a prefab somewhere

drowsy wharf
#

I don't know how to update your code

#

it was based on T before

#

    public void Use(Texture texture)
    {
        //Debug.Log("Use Instance ID is " + this.gameObject.GetInstanceID());
        Debug.Log($"Use Function called on {nameof(T)} prefab");

        internalMat.SetTexture("_MainTex", texture);
    }
daring perch
# drowsy wharf

You wouldn't need to do that bit. That was just to tell us what T was. In this case, we know what type it is since it's in a script with a name

#

So we could see what class it was instantiating

drowsy wharf
#

okay

daring perch
#

You'd want Use Function Called on {this.GetInstanceID()}

drowsy wharf
#

I didn't actually make a new scene, I just cleaned out the existing scene and made a copy of the old scene

daring perch
#

Which, now that I think about it, we were calling that on the gameObject, right?

drowsy wharf
#

so I will try to make an actual new scene?

daring perch
#

Maybe that's why the numbers don't match

daring perch
#

No, try running it with that new updated string

drowsy wharf
#

Okay

daring perch
#

Change out that one debug, and change the other one to use this. instead of gameObject.

drowsy wharf
#

Run what with what updated string, Use?

#

Gotcha

daring perch
#

Change both the use and Preload, then run it

drowsy wharf
#

it changed, but it still doesnt match anything

#
    public void PreloadMaterials()
    {
        internalMat = new Material(matTemplate);
        for (int i = 0; i < systems.Length; i++)
        {
            systems[i].material = internalMat;
        }
        Debug.Log("Preload Instance ID is " + this.GetInstanceID());
    }

    public void Use(Texture texture)
    {
        //Debug.Log("Use Instance ID is " + this.gameObject.GetInstanceID());
        Debug.Log("Use Instance ID is " + this.GetInstanceID());

        //Debug.Log($"Spawing a copy of {typeof(T).FullName} prefab {poolObject.GetInstanceID()} as new instance {instance.GetInstanceID()}");


        internalMat.SetTexture("_MainTex", texture);
    }
daring perch
#

So, where are you calling Use again?

drowsy wharf
#

from it's parent Pool

#

which is in turn being called from..

daring perch
#

Show the snippet

drowsy wharf
#

okay

#

    public static void InstantiateDamageEffect(ITargetable target, DynamicParticleDamageSprite particle, int ammount)
    {
        InstantiateEffect(target, particle.myInstance, ammount);
        if (particle != null && target.gameObject.TryGetComponent(out ItemComponent itemComponent))
        {
            Texture2D tex = Utils.textureFromSprite(itemComponent.sprite.sprite);
            particle.Use(tex);
        }
    }```
#
    public static void InstantiateEffect(ITargetable target, ParticleInstance particle, int ammount)
    {
        if (particle != null)
        {
            //REFACTOR: create already runs findInstance inside of itself. 
            ParticlePool pool = ParticlePoolInstanceManager.Instance.FindInstance(particle);
            if (pool == null)
            {
                pool = ParticlePoolInstanceManager.Instance.CreateInstance(ammount, particle); // MAGIC NUMBER: 5 is random arbitary atm. 
            }
            pool.InstantiateEffect(target);
        }
    }```
daring perch
#

Where do you call InstantiateDamageEffect?

drowsy wharf
#

    private static void DoExecuteAction(ScriptableActionPackage package)
    {
        bool succeeded = package.action.ExecuteAction(package.target, package.activator);
        if (succeeded)
        {
            ParticlePool.InstantiateEffect(package.target, package.action.OnActionVFX, package.action.OnActionPoolCount);
        }
        else if (!succeeded && package.target != null && package.target.gameObject.TryGetComponent(out Actor actor) && package.activator.gameObject.TryGetComponent(out ItemComponent itemComponent))
        {
            ParticlePool.InstantiateDamageEffect(package.target, GameGlobalManager.Instance.genericDamageParticle, 5);
            actor.TakeDamage(itemComponent.useAction.damage);
        }
    }```
daring perch
#

There!

#
ParticlePool.InstantiateDamageEffect(package.target, GameGlobalManager.Instance.genericDamageParticle, 5);
#

That second parameter

drowsy wharf
#

I should probably rename Instantiate because it's not actually instantiating it

daring perch
#

That's a prefab

#

You showed that earlier

drowsy wharf
#

its just using from the pool

daring perch
#

No, it's using the prefab

drowsy wharf
#

uhh

#

So I take it "GameGlobalManager.Instance.genericDamageParticle" was afuckup, because of some unity internal reason I failed to grasp

daring perch
#

Follow the thread, let's swap in the values in the code:

 public static void InstantiateDamageEffect(ITargetable target, DynamicParticleDamageSprite particle, int ammount)
    {
        InstantiateEffect(package.target, GameGlobalManager.Instance.genericDamageParticle.myInstance, ammount);
        if (GameGlobalManager.Instance.genericDamageParticle!= null && target.gameObject.TryGetComponent(out ItemComponent itemComponent))
        {
            Texture2D tex = Utils.textureFromSprite(itemComponent.sprite.sprite);
            GameGlobalManager.Instance.genericDamageParticle.Use(tex);
        }
    }
#

See how in InstantiateEffect you're getting GameGlobalManager.Instance.genericDamageParticle.myInstance

#

but you're calling Use directly on GameGlobalManager.Instance.genericDamageParticle?

drowsy wharf
#

which is a prefab in project, and not in the scene

#

shit

daring perch
#

Yep

drowsy wharf
#

why did I do that, what did I think I was doing

#

I think what I thought I was doing was looking in the pool for that prefab, and if its not present, make more of it

daring perch
#

Oh wait this is a thread not a DM I should probably remove that gif

drowsy wharf
#

hhrmm okay so why did that not work, but the copy paste version does work

#

haha

#

so this entire mess happened because I couldnt use my existing method

#

because I needed to run code in the thing

#

that line is the line I copied over

#

which does work (maybe?)

#

and that thing is using "package.action.OnActionVFX"

#

which is just a reference to a prefab in the project

#

so why is my reference to a prefab now not working but that one is working

#

right you sent me a code snippet let me look at that

daring perch
#

to demonstrate what was happening

#

I think you just need to change particle.use to particle.myInstance.use

drowsy wharf
#

Im getting lost now

daring perch
#

What type is myInstance?

drowsy wharf
#

What is that block of code

drowsy wharf
#

ParticleInstance doesnt run Use

daring perch
daring perch
drowsy wharf
#

DynamicParticleDamageSprite, which is a component on the instantiated ParticleInstance prefab

daring perch
#

So, you might need to do another getcomponent

drowsy wharf
#

they arent the same component because I dont want this code to exist on every single particle instance

daring perch
#

particle.myInstance.GetComponent<DynamicParticleDamageSprite>().Use

drowsy wharf
#

I'm getting really confused now

#

particle is already a DynamicParticleDamageSprite

#

why would I have to get itself?

#

oh wait because its not itself, its the prefab from project?

daring perch
#

If it is, then your problems go very deep

drowsy wharf
#

    public static void InstantiateDamageEffect(ITargetable target, DynamicParticleDamageSprite particle, int ammount)
    {
        InstantiateEffect(target, particle.myInstance, ammount);
        if (particle != null && target.gameObject.TryGetComponent(out ItemComponent itemComponent))
        {
            Texture2D tex = Utils.textureFromSprite(itemComponent.sprite.sprite);
            particle.Use(tex);
        }
    }
#

particle is "DynamicParticleDamageSprite particle"

#

thats how Im able to run use on it

daring perch
#

Basically, right now, particle is the exact instance you have in GameGlobalManager

#

You want it to be one of the pooled thingies spawned from it

drowsy wharf
#

Yes ๐Ÿค”

#

I am utterly lost as to why this is happening but doesnt happen every other time I do the exact same thing

daring perch
#

Well, you seem to be doing something right in InstantiateEffect

#

which uses the myInstance property of the thing in GameGlobalManager

#

Hence why I suggested using that for this one instead

#

Let me see InstantiateEffect again?

drowsy wharf
#

I only made the GlobalGameManager thing as a hack

#

the instance that is

#

because i didnt know how to tell it THIS PREFAB

#

let me get that code for you

#
    public void InstantiateEffect(ITargetable target) // wont do effect without target.
    {
        if (target != null)
        {
            ParticleInstance thing = Pool.Use(effectPool); // pool.use is the culprit for weird clone issue. 
            thing.transform.position = target.gameObject.transform.position;
        }
        
        if (effectPool.Count == 0)
        {
            Pool.ExpandPool(this.transform, effectPool, particleInstance, poolIteration);
            poolIteration += 1;
            for (int i = 0; i < effectPool.Count; i++)
            {
                effectPool[i].parentPool = this;
            }
        }        
    }
daring perch
#

Do you have an overload for that with 3 arguments?

drowsy wharf
#

oh, yes

#
   public static void InstantiateEffect(ITargetable target, ParticleInstance particle, int ammount)
    {
        if (particle != null)
        {
            //REFACTOR: create already runs findInstance inside of itself. 
            ParticlePool pool = ParticlePoolInstanceManager.Instance.FindInstance(particle);
            if (pool == null)
            {
                pool = ParticlePoolInstanceManager.Instance.CreateInstance(ammount, particle); // MAGIC NUMBER: 5 is random arbitary atm. 
            }
            pool.InstantiateEffect(target);
        }
    }
daring perch
#

Aha, I see

#

ParticlePool pool = ParticlePoolInstanceManager.Instance.FindInstance(particle);

#

Right here, particle is the prefab in the game manager

#

And you're getting an instance of it from the pool

drowsy wharf
#

๐Ÿ‘€

daring perch
#

But you're not doing that step in InstantiateDamageEffect before calling Use

#

You need to make an instance of particle like you did here, and call Use on that

drowsy wharf
#

okay so...

#

Im calling the working one, and then I tried to run the extra new code after it

#

but.. right

#

right the working one is changing what "Particle" when it does its thing

#

but the code outside of that is still using the prefab and not the instance

#

I think I understand it but I would never have solved this on my own

#

You have been invaluable ๐Ÿ’ฆ

#

right it stops using particle and starts using pool

daring perch
#

Pools are tricky to keep straight. You really want to make sure you have a good system in place before using it ever, retroactively adding one to code that already exists is a fine tightrope act

#

You run into weird edge cases like this one

drowsy wharf
#

Yeah up until this moment the pool was ship shape, it only broke because I tried to expand on it for a SPECIFIC edge case

#

and also didnt understand how it worked obviously

#

or I did once, and forgort

#

Okay so the fix is particle.Use(tex); needs to be run on ParticlePoolInstanceManager.Instance.FindInstance(particle); finding an instance matching that prefab