Forum Discussion

FreakyChest's avatar
5 months ago
Solved

Best Strategy for Detecting If a Component Has Been Shot

Trying to find best way to detect if a certain component/components have been shot

My assumption would be to ignore all static objects, and only send event to server if not static entity, then server can do checks like seeing if it is Target (Component we want to shoot). Does this sound about right or is there some other features I don't know about to group entities in some way for projectile detection? 

If both launcher and Target are client/local then I understand we can just use getComponents to see if it is what we want.

  • When an entity or player is hit by a projectile, the projectile launcher gizmo fires a related event. These events give you the entity or player that was hit. Then you can send an event to the entity or player if it needs to do a thing upon being hit.

    OnProjectileLaunched: CodeBlockEvent<[launcher: Entity]>;
    OnProjectileHitPlayer: CodeBlockEvent<[playerHit: Player, position: Vec3, normal: Vec3, headshot: boolean]>;
    OnProjectileHitEntity: CodeBlockEvent<[entityHit: Entity, position: Vec3, normal: Vec3, isStaticHit: boolean]>;
    OnProjectileHitObject: CodeBlockEvent<[objectHit: Entity, position: Vec3, normal: Vec3]>;
    OnProjectileHitWorld: CodeBlockEvent<[position: Vec3, normal: Vec3]>;
    OnProjectileExpired: CodeBlockEvent<[position: Vec3, rotation: Quaternion, velocity: Vec3]>;


    https://developers.meta.com/horizon-worlds/learn/documentation/mhcp-program/community-tutorials/creator-manual#projectile-launcher-gizmo

    https://developers.meta.com/horizon-worlds/reference/2.0.0/core_codeblockevents

     

  • Detecting if Correct Component

    The best way to find if a certain component/script has been shot (like trying to detect if the players Gun shot a Target) depends on if Gun (which will listen for OnProjectileHitEntity on projectile launcher gizmo) is running in same context or not (both server or both local, or one is server and one is local).
     

    Same Context

    If both are either server or both local, then we can use getComponent and check if the component exists on the entity that is returned from OnProjectileHitEntity. This is the easiest scenario, and no messaging between scripts is needed.
     

    Different Context

    If the scripts are not in the same context, then when OnProjectileHitEntity is triggered on Gun component/script it will have to send an event with the entity that was shot (only if is not static, if your shootables are non-static) and ref to self or player (what or who shot it) using broadcastEvent to a server/default script/component like GameManager so that it can then check if the component exists on the entity (Target) and then the GameManager script can send an event back to Gun component/script to say if it hit the Target or not (little more challenging scenario) or if the gun doesn't need to know GameManager can deal with the logic sense it has all the information. 

    Alternative - Use tags

    Another way for detecting if its the correct component, is we can add tags on entities, and then all we need to do is check if that tag exists on the entity and we can assume the component is likely on it (unless we did something wrong). This allows us to use tags like "Shootable" and then when we shoot an entity, we check if this tag and if it exists we can trigger our logic. With shootable components, just add the tag on start.

     

7 Replies

  • When an entity or player is hit by a projectile, the projectile launcher gizmo fires a related event. These events give you the entity or player that was hit. Then you can send an event to the entity or player if it needs to do a thing upon being hit.

    OnProjectileLaunched: CodeBlockEvent<[launcher: Entity]>;
    OnProjectileHitPlayer: CodeBlockEvent<[playerHit: Player, position: Vec3, normal: Vec3, headshot: boolean]>;
    OnProjectileHitEntity: CodeBlockEvent<[entityHit: Entity, position: Vec3, normal: Vec3, isStaticHit: boolean]>;
    OnProjectileHitObject: CodeBlockEvent<[objectHit: Entity, position: Vec3, normal: Vec3]>;
    OnProjectileHitWorld: CodeBlockEvent<[position: Vec3, normal: Vec3]>;
    OnProjectileExpired: CodeBlockEvent<[position: Vec3, rotation: Quaternion, velocity: Vec3]>;


    https://developers.meta.com/horizon-worlds/learn/documentation/mhcp-program/community-tutorials/creator-manual#projectile-launcher-gizmo

    https://developers.meta.com/horizon-worlds/reference/2.0.0/core_codeblockevents

     

    • FreakyChest's avatar
      FreakyChest
      Member

      Ya, I get that, my question was more on detecting hits of a specific component, and not just detecting projectile hit events, then I went further to talk about two different scenarios and checking if my approach makes sense or if there are better methods. Where I know we can get the component when both are on client and then for when gun is client and Target is on server, we can optimize checks by checking if entity is static before sending to server to see if correct component.

      I find it very odd you accepted your own answer, it did not provide more information regarding my question. Apologize I thought you accepted it, just realized it was Ben.SH. Still find that odd.

      • SeeingBlue's avatar
        SeeingBlue
        Mentor

        I am having a little trouble understanding your approach here so I tried to explain a typical scenario we use. Are you wanting entity and player collision events too? Cause you can get those also.

        So from what I can gather you're in a server/client environment(using Local scripts being transferred to a player's headset) and you want to get a component for comparison?

  • Detecting if Correct Component

    The best way to find if a certain component/script has been shot (like trying to detect if the players Gun shot a Target) depends on if Gun (which will listen for OnProjectileHitEntity on projectile launcher gizmo) is running in same context or not (both server or both local, or one is server and one is local).
     

    Same Context

    If both are either server or both local, then we can use getComponent and check if the component exists on the entity that is returned from OnProjectileHitEntity. This is the easiest scenario, and no messaging between scripts is needed.
     

    Different Context

    If the scripts are not in the same context, then when OnProjectileHitEntity is triggered on Gun component/script it will have to send an event with the entity that was shot (only if is not static, if your shootables are non-static) and ref to self or player (what or who shot it) using broadcastEvent to a server/default script/component like GameManager so that it can then check if the component exists on the entity (Target) and then the GameManager script can send an event back to Gun component/script to say if it hit the Target or not (little more challenging scenario) or if the gun doesn't need to know GameManager can deal with the logic sense it has all the information. 

    Alternative - Use tags

    Another way for detecting if its the correct component, is we can add tags on entities, and then all we need to do is check if that tag exists on the entity and we can assume the component is likely on it (unless we did something wrong). This allows us to use tags like "Shootable" and then when we shoot an entity, we check if this tag and if it exists we can trigger our logic. With shootable components, just add the tag on start.

     
    • SeeingBlue's avatar
      SeeingBlue
      Mentor

      I think typically you want your weapons/guns to be locally scripted and owned by the player holding it.
      Generally the player won't own the object they are shooting, so it is probably pretty rare that you'll get to use getComponent() in this scenario.

      It sounds like you could just send the event to the gameManager with all the data you need. I think this approach is fine as long as it isn't happening too often/rapidly, because it is a network call.

      • FreakyChest's avatar
        FreakyChest
        Member

        Agree on gun tends to work much better locally (currently updating my other Fractured (party games) to do that).

        getComponent can be called on default/server script for checking if it is a target Component (or any other shootable component that is also on the default/server).

        I think this is relatively common, guessing any shooting game is usual going to detect the hit and then tell a manager script, this thing was hit. I do agree for my shooting range that has many lanes, I may find issues with this approach (may have more checks then free for all shooter games). I think I will try it first and if I run into issues from too many network calls that I may have to put the targets on local too. I only want to do gun on local and target on default/server because that is what I need to do for my free for Fractured game (that way I can make a good system for both worlds).