I have a data struct which contains all the actors i need but i want better to say i need to get the static meshes they use as well. How can i do that ? I added default static mesh to the struct but that does not do the trick…
You want to drag off StaticMesh directly rather than trying to get the mesh of some character. Keep in mind what you have is a StaticMesh, not a StaticMeshComponent. The StaticMesh is the mesh a StaticMeshComponent would use- the StaticMesh itself is just an asset, it doesn’t have a location or transform or anything like that.
Keep in mind the value of a pin will absolutely never determine what you can do with it when creating blueprints. Don’t worry about setting defaults unless you actually need defaults.
The problem that i have tough is i’m creating a skill where all my enemies will be frozen. To make that do i really need to drag the mesh of any single enemy ? I plan to have at least 20+ enemies in my game more likely 30… So how could i do that all 1 by 1 ? Or can this works as an array somehow to get the mesh information of each of them… I have 1 freezing material which can be used on all meshes so is universal freezing material. I changed yestarday the static mesh on the array with character object reference and looks like i could plug that into to the mesh next but it has no effect and does not freeze the enemies meshes. It must be wrong then…
Here is how the skill looks like when i change the get all actors of class and choose a single enemy with just get actor of class and plug his mesh to it…
This would only work for one enemy at a time with one material as is. Unfortunately there isn’t a simple way to fix everything with your current solution- this’ll be a bit of a read. Feel free to respond with any questions you have.
I assume you have a sphere collision for testing whether enemies are inside the range of the ability. If you haven’t, you should. Add one and change the sphere radius until it matches your effect.
Here’s how I’ve fixed it:
Make a new struct. Blueprints can’t handle maps to arrays, so we need to create a wrapper struct that acts as one. I’ll name it WrapperStruct_MaterialArray. Inside, we simply have one parameter- a material interface array
In the TotemFreezeFunction, get all the overlapping actors that are enemies- meaning put the class all your enemies inherit from in the ClassFilter parameter. After that, loop over them. We’ll need to cast to the enemy base class in order to actually do anything with them, so do that.
We then do your pause anim set and then call a function we’ll create that applies the materials. This simply has two parameters- an EnemyBase object and a boolean. After this you can do whatever other freeze stuff you have.
For the unfreeze, we simply flip the boolean values and use the keys of EnemyBaseMaterials rather than the sphere overlap. We don’t need to use a cast here since keys are already EnemyBase.
Inside the loop, we add the material to the array of materials for this specific enemy. It’s a bit of a pain since map find doesn’t return by reference, but oh well. You’ll just need to create a local variable to hold it for a second.
We simply iterate through the stored array, set the materials on the enemy to match, and mark the enemy as unfrozen by removing their entry.
Here's the blueprint for the nodes in the function. BlueprintUE wouldn't recognize my function as a function, so that's the best I could do. Keep in mind this won't work well pasted since it's using the parameters of the function, so just use it as a reference.
wow thx that looks pretty awsome. I will try that shortly and will update what happend…
Yeah i have the sphere collision set up. When enemy gets in there it triggers the freeze or when the player character is in there then it heals him slowly…
If i follow all the instruction from above will this still work/freeze only 1 enemy even if lets say 5 enemy enter the sphere collision at the same time ? I am aiming to freeze any amount of enemies who get in the sphere collision range i hope it will work that way. If it’s aways only 1 enemy that freezes than maybe i should change the approach to make it work for all.
What is the enemy base variable refering to ? Is this “my” enemy struct that i previously had and right next to it you add somehow the new wrapper struct. On my side i cant choose on the enemy base variable the option “Map”
and here how my wrapper struct looks like when i add it in the totem BP as a variable. I’m not sure how to make it like on your screenshot and i dont have the option Map as well
Ok this might be a problem. How I’ve set it up is assuming FreezeEnemies is called by a timer of sorts- as of now, it will freeze everything in range whenever called.
It’s possible to individually freeze and unfreeze enemies after a certain amount of time with a number of modifications if that’s what you want.
Yeah that’s what I was referring to when I said your current solution would only work for one enemy with one material. This method will freeze every enemy in the sphere at the intervals set via FreezeDelay and FreezeTime.
Enemy Base is the character that all enemies inherit from. This is something you’ll have to implement. Ie your BP_SkeletonEnemy/BP_ZombieEnemy/BP_VampireEnemy should all inherit from a common class somewhere along the tree- ie BP_Enemy. Meaning it’s fine if BP_Zombie inherits from BP_Undead as long as the parent eventually is BP_Enemy (ie BP_TankerZombie → BP_Zombie → BP_Undead → BP_Enemy)
The “NewEnemies” struct you have is not used in this method and you can’t use structs as keys in maps. The wrapper struct is the value, not the key- the key is on the left, the value is on the right. You’ll need to use EnemyBase or some equivalent as the key- just a class all enemies inherit from.
We want the key to be EnemyBase and the value to be the wrapper struct
This one sounds perfect so i guess i should try to make it happen.
I do have a base enemy BP and all the other enemies are children of this base bp.
I got it now by adding this base enemy as a variable and then the new wrapper struct material. So now this is working…
I’m going to continue on the next steps and see how it goes thx for the help
Edit:
step 4 problem getting the sphere collision and “get overlapping actors” setting the base enemy class in there and then cast to the enemy class after a loop. So far so good but then i cant drag from a “cast to base enemy” node to the “Set Pause animation” like on your screenshot
The “Set” pause animation node wants a mesh… Do i maybe get the mesh from the base enemy BP and connect it like this ? It doesnt look like yours but i hope this works if i do it like it is now ? (it doesn’t work. or partially now with this set up as it is all enemy’s get frozen so yeah thats awsome but the part with the mesh dont work and do not change after i freeze them)
I finished all the steps from above but i think i screw something on step 4 and on step 5. I awso added “material instance” input pin to “ApplyMaterialsToEnemy” function and choose my freeze material but not sure if thats correct there as well ://
Anyway because of step 4 and 5 i think it isnt working as it should… Here is the end result now and i awso remade the “apply materials” function just like yours and replaced with my variables there (it shows no errors and i think i made exactly everything 1:1)
Final endresult now (except that step 4 and 5 are not 1:1 as in the steps above) any idea why i cant connect the base enemy node to the “set pause animation” one and plug them togheter like on your screenshots ? Awso for some reason the enemy’s do not “unfreeze” anymore and i have put them boolean to false and i have set movement to “walking” at the end of the unfreeze function…
Yup- just ignore what I’ve done with those. Slipped my mind.
I don’t really recommend that. The frozen material is only used if Frozen is true, so it’s best to not put it as a parameter. Maybe use a variable instead. Though, you don’t have it connected so you’ll need to do that first if you want it in variable form.
This is really odd. Notice how not only do they unfreeze, they don’t ever get the ice material in the first place. ApplyMaterialsToEnemy looks perfectly fine, so I’m a bit confused.
Could you show the entire freeze and unfreeze functions (also, I recommend these be events, not functions)?
And outside in the event graph i had it here (first it was connected to “on component beginn overlapp” node later i disconnected it and just plugged it directly on event beginn play but was pretty much the same only difference was the timing when the freeze fired with it.
Btw on the “ApplyMaterialsToEnemy” function i removed the pin at the start for the material and in the end where it apply the material i did made/promoted the freezing material to variable and hooked that in. But it didnt change. Dont know why the monster not only do not get the freeze material but they awso do not move back to normal which is odd. i have set it up in the unfreeze function to “walk” again (is at the very end there)
Edit:
I did had 1 anomaly tough at the start only 1 enemy get frozen and unfrozen so he moved again but all other ones were forever frozen. Not sure what happend but i cant replicate that anymore now all just freeze and do not move. Awso the 1 guy that did move he as well never get the freezing material just like the others :/. I will try now with the events and see if that does help.
Edit 2:
I moved the functions to events but nothing changed.
Hmmm. I don’t see anything wrong… it looks practically identical to my setup but doesn’t function… time for some debugging.
Make EnemyBaseMaterials visible (instance editable, the eyeball). Check it out at runtime and make sure stuff is properly being added and removed. An enemy should only be there if it’s frozen and should be removed when unfrozen. You may want to pause the game right when they freeze to make sure nothing changes in the meantime.
Add print statements just everywhere. Print any info you think may be relevant in them. Ie on TotemUnfreeze, print “Unfreezing” and print the names of the keys in the for loop. Things like that. Make sure you make the duration longer than the default 2 seconds- I always just do 222 since I can always easily reach 2. If two print nodes print out similar information (ie both print out the object name of something), but are different sections, change the colors.
You’ll want to do this in the freeze, unfreeze, and apply materials function. Of course, you don’t need to do this all at once- do it one function at a time. It would suck to spend 20 minutes setting up print statements when your first statement solves it.
i just started testing something else will be in a sec back and try it… I managed to fix the freeze material by just replacing the “ApplyMaterialsToEnemy” and i put simple “set materials” instead in the freezing function itself seems to fix this.
But for some reason i cant make them move at all anymore even if i completely remove the “disable movement” on the freeze itself. They only freeze and they do not get the normal materials back
Edit: acctually they do move lol but without moving the limbs like moving in frozen state so to say (only when i remove the “disable movement” in the freeze function if i let it there they are aways just frozen. I think the unfreeze function do not apply anymore)
They should be events for cleanliness/accuracy reasons, not technical.
You can’t do that. I didn’t make that function and variable for giggles.
You need to apply the frozen material to every material, not just the first one, a way to store the original materials, and a way to know which enemies are frozen. This is all done through the map. The map is filled out via the apply materials to enemy function.
The function does a bit too much unrelated to it’s name for my liking, so going back I’d change a few things, but it absolutely needs to be called.
They don’t move because you haven’t recorded any of the frozen enemies in the map. If you aren’t using the apply materials function, you aren’t recording. Since there are no enemies in the map, the unfreeze function won’t do anything- it doesn’t have any enemies to unfreeze. The for loop will never trigger, so pause anims will never be set to false.
I just fix it :D… I combined your loop array’s from the freeze function and reverse the exact same logic on the unfreeze. If i couldn’t appy the material from “ApplyMaterialsToEnemy” function then better to just manually apply the material on freeze and then on unfreeze function. The ApplyMaterialsToEnemy had a boolean there to check if they were frozen or not and then apply accordingly the material to that state they were in. But if that didnt work for some reason then its maybe better to remove this check if they are frozen and just make them frozen no matter what in the single freeze function and then 100% unfrozen using the unfreeze function. So i copy 1:1 the freeze function and i put the exact same logic on the unfreeze but revers the values there and in the end of it i set the movement mode back to walking… (I think now this is pretty good and working)
And here how it looks now. Just what i was looking to achieve…
Do you see any downsides to this method? I think thats a keeper now and this is solved i would say and pretty happy how simple the whole thing is and it just works…
It doesn’t work with multiple materials (you can see this happen with the bomb), knocking an enemy outsize while frozen will result in them always being frozen, and you can’t have anything that pauses anims other than freezing- meaning no petrification or stunning since if they come in after the ability has finished freezing but before it did the last unfreezing, they would almost instantly be un-stunned/un-petrified.
Ok i see the point when they are frozen and whitout the boolean check and i knock them out of there or an enemy just get later in the sphere collision just in time befor the totem expires, then he will stay frozen. So what can i change on this function when it is not working to me. if i go back to the function neither the materials apply nor they got unfrozen again…
Edit:
What if i set “on component end overlapp” to set it there to get back to walking unfrozen state ? Would that not work when i am knocking one out of the collision range and then he will get unfrozen again? As i set it up of now on the frozen function, they cannot freeze as last when the totem expire at the same time. The totem switch interval to unfrozen state befor it expire so i tested it with no matter how many enemy’s go over it they cannot freeze and stay frozen. The only thing that can happen is if i can knock one out in the frozen state but then would the end overlapp maybe work to get them back to unfrozen if i set it like i mentioned ? Was just an idea i had and maybe that is good enough. Even if all the materials don’t get the frozen material i can live with that.
Now trying to see if a big crowd of enemy’s can stay frozen after spawning many totems https://streamable.com/6wptne
To be honest that ain’t bad for now and i can’t make an enemy stay frozen. Looks like i cant push a frozen enemy tough. If there is some push ability it would then skip frozen enemy’s. Tbh good for now and if you know some fix for the “apply material” function would be for sure good, but in case not then i can work with this for now…
Hey man i finally found the problem how to “ApplyMaterialsToEnemy” Function.(Yes im still working on it) It seems that i had to replace the Enemy reference in there which fixed the whole function. I had to cast first to the “base enemy” and drag the info from it and replace all the single “Enemy” ref nodes with it. Like on the screenshots below i could apply the material just like on your previous posts. And this finally worked…
So now the material apply to all the mesh elements like on this bomb if you remember and now this is working on any enemy. There is still 1 problem tough when i put this on the timer by function or timer on event (i testet both) then this happens:
So if the timer is set to freeze just when the totem expire they stay forever frozen I was thinking if this “apply material function” its now working then shouldn’t the timer as well work because of the boolean there frozen and not frozen ?
I see what went wrong from your screenshot- everytime you see “Enemy” in my screenshot, that’s just a wireless way of getting that “Enemy” input parameter. In your case, you’ve made a variable and used that. That variable you’ve created is never getting set, so it makes sense that nothing would work.
I wrote that as a place to check in the debug post, but I guess I deleted it by the end of writing the reply.
As for your current issue, here’s how I’d suggest solving it:
Promote your freeze and unfreeze timers to variables. We want to be able to stop them before we destroy our actor.
Create a DestroyTotem event in your totem. This should be called instead of a DestroyActor call.
In this event, start off by deleting everything the player can see relating to the totem. In this phase you’d also want to make everything collision-less, but you don’t have any blocking collision or on collision events, so you don’t have to.
After that, we want to clear and invalidate the FREEZE timer. Note that we aren’t invalidating the Unfreeze timer yet.
Finally, we deal with the unfreezing. We get the remaining time for the unfreeze timer, plug that into a delay node, then clear that timer (we do this via sequence since we want to immediately clear the timer without waiting for the delay to finish). What we’re doing here is basically hijacking the unfreeze timer so we can have a bit more control without cluttering up our unfreeze event. Once that delay finishes, we simply call unfreeze and destroy the totem via DestroyActor.
For some reason they still stay frozen forever. I wish it could just work right away but as aways nothing works on the first try here…
Edit:
Wierd enough i made an extra freeze skill without the totem based on the exact same logic. First it didn’t work out just like on the totem the enemy needed to stay in the collision range to be unfrozen(If i freeze them and get away then they stay forever frozen). Now after fixing the apply materials i added that as well on the freeze and unfreeze again (on the character skill now) then i remade the timers as well with the newly added destroy freeze skill timer event and… It didn’t work… so i plugged it back to the functions on a delay Freeze/ 3 sec delay /Unfreeze 2 sec delay and loop it and all of a sudden this one works now. No timer nothing just this 2 functions in a row and the enemy get unfrozen even if i get out of the collision range. Which previously never worked… I try it now many times and this works with no issues… Only difference is that i use now the apply materials function correctly.