Announcement

Collapse
No announcement yet.

Projectiles - which actor should destroy them?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Projectiles - which actor should destroy them?

    Hi,

    I've run into a slight problem where I am trying to determine the type of actor that has collided with another actor, but, because that actor is "pending kill" I am unable to.

    Example;

    * player fires, a projectile is spawned and moves in the direction the player was aiming
    * another actor is hit
    * the projectile implements Destroy Actor based on the collision
    * the other actor which was hit wants to check what has hit it, e.g. "was it a projectile", but now cannot because the projectile is being destroyed

    I was wondering whether my approach was wrong. It feels sensible for the projectile to destroy itself, it would seem a bit odd for other actors to say "ok, I'll destroy that thing that just hit me", e.g. the "other thing" is passive and the projectile is active.

    It occurred to me that I could create an event on the projectile, then, rather than just destroy the projectile on collision, the other actor could raise the event from the projectile, the projectile would respond to this and then destroy itself, this would offer the ability for other actors to say "ok, I'm done with you now, you can go ahead and destroy yourself".

    I feel like I may be missing something obvious.

    Could anyone share some suggestions for me please, thanks in advance

    #2
    RobMeade Perfect. Just use a blueprint interface to let the projectile tell the hit actor what has hit it before killing itself...
    Check out Zof ( puzzle game ) on Steam:

    https://store.steampowered.com/app/1414480/Zof/

    Comment


      #3
      Thanks for the reply ClockworkOcean, could you explain "blueprint interface" for me? I'm fairly new to Blueprint, might just be a term I'm not familiar with, or perhaps more like interfaces from C# - any clarification is appreciated

      Comment


        #4
        RobMeade It's a standard ( easy ) way to get various messages from one BP to another:

        https://www.youtube.com/watch?v=G_hLUkm7v44
        Check out Zof ( puzzle game ) on Steam:

        https://store.steampowered.com/app/1414480/Zof/

        Comment


          #5
          Hey ClockworkOcean, thanks for the link to the video, it was a bit hard to follow with the guy bouncing around but I'll try to watch it a couple more times until it sinks in.

          I'm guessing actors can implement more than one interface? Just saw in the video there was an "Add" option, so multiple can be implemented....


          I've got to a point in my current mini-project where I think using interfaces may be the solution but it would mean making some significant changes and I'd like to run something passed you first if I may..

          At the moment, my projectile is responsible for destroying itself once it makes contact with something else.

          I have a floor tile object (duplicated across the level to make a destructible floor), at the moment, this responds to the collision and checks to see if the "other actor" was a child of my projectiles base class. If it was, then I know that the floor tile was hit by a projectile, as opposed to say the player's vehicle moving across it. It responds to the projectile collision by setting simulate physics and the floor tile falls away. So far, so good!

          My problem is that I want these floor tiles to now only fall away if the strength of the projectile was greater than a certain value. I had assumed, being that I could determine that it was a projectile actor that had made the collision I would then be able to access one of the variable upon it to get the value. This seems to not be the case, on each approach so far I end up with the same result, a "None", and an error stating that the projectile is "pending kill". I understand this, in one sense, because I am destroying the projectile within the projectiles logic. What doesn't make sense to me is why I am able to determine the class of the "other actor", e.g. I don't get an error when I try to make that check.

          I come from a VB.Net/C# background, and am used to "seeing" the code, so Blueprint is a new experience. I'm also used to being able to pass object "by val" where-as from what I can tell, everything in Blueprint seems to be "by ref".

          So, can you think of a way that would allow me to gain access to the projectile's variable data on the other actor without the error about "pending kill"?

          I do appreciate that with the interface example above, this would allow me to do this, BUT, from what I can tell you would be passing a single data item in the even that is raised, e.g. "strength", whilst that would work for now, what if I had a really complex object with lots of values I needed to be passed through before it was destroyed, having them all as parameters for an event would be really messy, and just passing the actual object through (perhaps "by val") would at least allow for an easier container.

          Sorry if the above is a bit wordy and not clear, I can drop some screenshots if they are of use, my gut feeling is I'm missing something really simply/obvious here and with that snippet of wisdom I'll not need to re-engineer what I have extensively.

          I'm a mature student taking a uni course, this project is for that, and I don't think there is an expectation for interfaces as this stage, so I've probably either over engingeered my solution, or as I say, am missing something obvious!

          Thanks again for any further help
          Last edited by RobMeade; 11-25-2019, 07:51 AM.

          Comment


            #6
            RobMeade Yup, you're going about it the wrong way

            You'll never get access to the project var space because by the time you want it, it doesn't exist any more.

            That's why you need BP interfaces. With BP interfaces, anything that you want to be 'destructible' can implement you 'destruction interface'. All it means is that a BP can 'subscribe' to the implementation. What it does with that implementation is up to IT, that's the beauty of it. Every BP can respond differently, which is what you want.

            So, with the projectile... Your floor tile ( and anything else you want to bust up ) will implement the projectile / destruction interface. As you projectile heads towards your object ( ie, does a line trace ), it can check 'does this object I'm hitting implement the interface?'. ( In fact it doesn't matter if it doesn't - nothing bad will happen. ) The projectile sends a signal over the interface, which can contain parameters ( like damage values ), and the object implementing the interface can respond appropriately by exploding or whatevs...

            Tell me if that's not clear and I'll try again...

            PS: ( reading your text again ), you really can't do it by reading from the projectile, because that would mean the projectile would not be able to destroy itself until it's variables had been read. Which is a) messy and b) impossible because it would have to wait until everything had read it's params, and doesn't know how long to wait...
            Last edited by ClockworkOcean; 11-25-2019, 08:16 AM.
            Check out Zof ( puzzle game ) on Steam:

            https://store.steampowered.com/app/1414480/Zof/

            Comment


              #7
              Hi ClockworkOcean, thanks again for taking the time to respond.

              I read up on the UE4 documentation regarding Blueprint Communication and am fairly sold on the approach - bar two things;

              1) Doesn't this mean that a lot of my objects will have greater knowledge of other things than they should? Isn't this building bridges between objects which perhaps shouldn't know about each other.

              2) What about those complex objects/lots of variables situations, would you pile all of those as Input parameters into the event (is that the right term?) raised by the interface? In this scenario with just "Strength" perhaps its not an issue, but if I wanted to a more complex object and I needed 15 pieces of data from it, creating an event with those 15 parameters feels wrong. I guess I could create a custom object in that case, e.g. the thing that's no longer around to communicate off-loads data to a newly instantiated object and then pass that through as a container?

              Please issue any suitable quantities of virtual *SLAPS* if I'm getting this wrong

              I think where I've gone wrong with this is that I started using Event Dispatchers when I wanted to communicate from the Health component to the UI, that felt right, and then I've used the same approach with the Event Dispatchers to raise events for other situations (because it worked before etc). The main difference here of course is that the Health component perpetuates where-as these projectiles don't.

              I should add, I'm not currently using any line/ray tracing, it literally just spawns a sphere and then activates the ProjectileMovement component having set a velocity, it flies across the screen until it hits something (a floor tile).

              A final question with the interfaces... I'm "one of those" people who like to name things correctly... is there any guidance for the interfaces? In the video link above they used BPI_Damageable, I've been prefixing assets with BP_ and BPC_ so that feels "ok"... but internally, with the names of the events (is that the right word, or are these methods/functions?), should they be preceded perhaps with "On"... e.g. "OnCollisionWithProjectile", although that's a bit specific perhaps, maybe "OnTakesDamage"? I want these to read "right" when they are implemented within the Blueprint that is consuming them, and also with in the Blueprint interface.

              Have an example of something simple? (from a names perspective).

              Sorry to pester you, I've found this to be really helpful, so thanks again

              Comment


                #8
                RobMeade Some answers:

                1) The receiving BP only gets the knowledge you pass it in the params, it doesn't even know what kind of BP it was passed from so, much less knowledge flying around.

                2) I have a pretty complicated game I'm working on, I've NEVER had to pass more than one param. Even if you had to, you could put it in a structure, so it's still one param. I you have to pass it, it means to receiving actor needs it, so it's not unnecessary info. It's more a case of WHEN to use BP interfaces. This is a shining example. If, at another time you are passing the oxford english dictionary, BP interfaces are probably not the way to go. It's an appropriate use thing. I have a lot of BPs that do not use interfaces, they use references, and can see each other's internal systems. There's not just one way of tackling BP comms. Which brings me to:

                3) Dispatchers. Again, very specific use case. Basically when you want to broadcast to a lot of actors and don't want to have to find them and talk to them all. The use dispatchers, because you can just say 'My event!' and they all see it. You didn't have to send it to them, you didn't have to find them and tell them. It's a broadcast.

                4) Names. A single word is fine, you can use BP/ BPI etc if you like. But the interface is basically a 'postbox' which is only ( in this case ) used for damage. So 'Damage' or 'Damage interface' would be fine...

                Tell me if you need any more...
                Check out Zof ( puzzle game ) on Steam:

                https://store.steampowered.com/app/1414480/Zof/

                Comment


                  #9
                  That's great, thank you ClockworkOcean - muchly appreciated

                  I will check the video one more time, in my head I'm ok with the floor tile implementing the interface and thus having a specific event/method/function from it which it then does something specific with. The bit I've missed is how the initiating thing triggers it, in this case, the projectile.

                  By the way, I am using components on my actors, can they implement an interface, or only the main actor? I'm thinking ahead to my next headache where I find out its only actors and then I have to find another way to communicate to the component!

                  Comment


                    #10
                    RobMeade Not quite sure what you mean by components on actors. You can use BP interfaces to talk from one BP to another. Naturally, both BP can be full of components... If you think you need the interface on a component level, tell me what you mean, and I'll point you in the right direction.
                    Check out Zof ( puzzle game ) on Steam:

                    https://store.steampowered.com/app/1414480/Zof/

                    Comment


                      #11
                      Hi ClockworkOcean, sorry, I'm still learning the "lingo" with all of this stuff, I come from a Unity background, so probably mixing up my words a bit..

                      What I meant was, when I created my Blueprint for my projectile, I choose the parent class to be of an Actor type. In this specific case I have then added both collision and a static mesh to it. From here, I then created Blueprint Actor Components to add behaviour to this object, in the case of my player for example, I created and added a Health and Attack component.

                      My aim was to make these as generic as possible so that they could be added to other objects that could then use those behaviours. In the case of both Health and Attack I believe this is the case.

                      So, the above query was really whether the interface can be implemented as a component level, or only at the main Actor-based Blueprint level. In the case of taking damage via an iDamageable interface, I would want this to talk to my Health component, ideally from "within" that component, as opposed to having the Actor-based Blueprint say "Oh, I've been damaged by something, I better tell the Health component", I just wanted the Health component to say "Ouch!"

                      If the message has to come through from the Actor-based Blueprint and then get repeated to one of it's components that means that the Blueprint has to know more about stuff, and I'm not sure whether it should/I want it to. At the moment the Health component, for example, adds behaviour to that object, but the object itself doesn't interact with it, other than having it as an attached component.

                      I'm really sorry if I'm not getting this across very well, I don't think I'm familiar enough with all of the names of things yet to perhaps explain very well.

                      Update

                      So, I've had a go at implementing this and I've run into a little issue..

                      I have two types of floor tile, one is destructible, one is indestructible. These are represented by individual child blueprint classes of a main parent Blueprint class.

                      Initially I added the interface implementation to the destructible child blueprint, added a check to the projectile to see if the "other actor" implemented the interface and just added some print nodes to output some text.. nothing happened... I wondered whether this might related to the parent/child nature of these Blueprint classes, so I removed the interface implementation from the child and added it to the parent blueprint class. Ran the same test, this time I got output to the screen.

                      Initially the child blueprints didn't show that they were inheriting this, I had to close the tab and then re-open it, at which point it was visible in the class settings.

                      Whilst I appreciate my indestructible child blueprint doesn't need to do anything with the node, and thus nothing will happen, it will remain indestructible, it seems a bit odd that I'd have a "destructible" interface on the parent which may go on to spawn others which are not... I think I'd prefer to have just the child blueprint that is going to be destructible have this implementation - but the collision detected on the projectile seems to be basis the "other actor" on the parent class.

                      Surely I don't need to then iterate through the parent classes children and look to see if any of them have the interface?

                      Getting closer but still I'm still missing something
                      Last edited by RobMeade; 11-25-2019, 01:30 PM.

                      Comment


                        #12
                        RobMeade I get you, it's ok. As far as I know, the interface has to be on the parent, I don't think other BPs can look 'down into' the class hierarchy and see the implementation, it has to be at the 'top'.

                        It's ok to have it on the parent, even if the child doesn't use it. The child just doesn't use it, that's all. It's still derived.

                        But, like I say, I'm not sure if the BP interface will be visible once you start inheriting or incorporating children. You will have to experiment there.

                        To be quite honest, I tried getting into class inheritance / child BPs and found it a very difficult way to work. I know everyone thinks it's a great idea, but unless I'm missing something I always find I end up with really messy code because I'm always casting in and out of children to get at things that aren't resident in my current scope.

                        It's probably me missing something

                        BTW, Answerhub is a much better place for questions like this. It's in the community menu. Also, with AH, you get automatically mailed when someone posts, you don't have to keep '@'ing people...

                        Check out Zof ( puzzle game ) on Steam:

                        https://store.steampowered.com/app/1414480/Zof/

                        Comment


                          #13
                          Hi ClockworkOcean, thanks for the reply and info, appreciated.

                          I've not run into the issue with the messy code with the parent/child approach so far, but then the project is fairly simplistic so I've probably not got to that issue - yet - I'm sure I will

                          Thanks for the info about AnswerHub, I didn't know there was something else other than the forum, I'll check it out and see what's what. Thank you for all of your replies and information, it's been really appreciated and I was able to implement an interface and move forward passed the problem I was having because of it.

                          Comment


                            #14
                            ClockworkOcean, would you mind if I run something passed you, I think I've managed to tie myself up in knots, with several late nights working on various assignments I'm losing the ability to think clearly.

                            Currently, I have the floor tiles (parent) implementing the Destructible interface, that seems to be working well and it make sense to me. The "thing" which will be affected by that functionality is implementing it.

                            I have looked over other functionality to see whether their design can also be changed. I have a player HUD which displays ammo and health. I've given this some thought and cannot think of a good way to adopt the same approach, so currently that remains using the Event Dispatchers, OnHealthChanged and OnAmmoChanged events are raised when their respective values are changed, the UI updates.

                            One area which is really causing me a headache though are the pickups. These use the same approach as I had in place for both the projectiles (originally) and the HUD currently, e.g. event dispatchers. It occurs to me that these would be a good candidate for using interfaces as well, but having spent some time mulling it over I just cant quite see where to apply changes.

                            My pickups have a parent class, BP_Pickup_Parent. There are only two different types of pickups at the moment, health and ammo, BP_Pickup_Child_Health and BP_Pickup_Child_Ammo respectively. There functionality is very similar, the only significant difference is the component on the player which they communicate with.

                            I was thinking that creating an interface, perhaps BPI_Collectible would be a good starting place, and then I got really confused In the same way the floor tiles had the destructible interface, I would expect the pickups to have the collectable interface, but it isn't really the pickups I'm trying to affect, it would be the components on the player controller. In order to achieve that, I would need to set the class of the parent controller to implement BPI_Collectible, and to me, that doesn't make any sense, because the "player" isn't a "collectible"... I appreciate some of this is perhaps symantics with naming but I tried to think it through a little more...

                            Assuming the interface went onto the individual pickups, e.g. they implement BPI_Collectible, what would they actually do... the parent pickup class is the one which currently detects a collision, currently it then fires off the event through the event dispatcher which the child pickup receives and acts upon. As such, the parent could call the function for the interface, "Collected". The child pickups would then implement what that function needs to do... and this is really weird now... because they will need to get a specific reference to the player, and to the components in order to then increase the values of ammo or health... I had wanted to keep the pickups separate, e.g. no direct ties to the player. Also, in the case of the floor tiles, it was the "projectile" that made the function call, and wasn't itself implementing the interface.. but if I have the parent pickup calling it, this is quite different, and feels unnecessary.

                            I am now lost in a quad mire of my own making

                            Fully appreciate without being able to see the project all of my "crazy" above is probably hard to read/take in... so, more generally, how would you approach the pickups in this scenario?

                            Comment


                              #15
                              RobMeade Typically, you would bind variables in the HUD to your player ( or whatever BP ). That way, whenever the variables change, the HUD updates, no need to dispatchers. NB: Do you know how to do the bind? Also, maybe you can't bind the HUD to player variables, haven't tried it yet ( maybe that's why you ended up using dispatchers ).

                              Pickups: BP interface is a message from one BP to another. In the case of pickups, the message needs to go from the pickup to the player, so the player implements the interface. That way, the pickup can send a message over the interface ( what it is, how much of it ) and dissapear. The player BP responds to the information by updating variables. So, I think you had it back to front. Name would be something like 'Collect' and it's on the player.

                              Make sense?...



                              Check out Zof ( puzzle game ) on Steam:

                              https://store.steampowered.com/app/1414480/Zof/

                              Comment

                              Working...
                              X