Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Which is the "lightest" way to create a shooting effect?

Discussion in 'Scripting' started by Chiefmastoras1, Mar 29, 2020.

  1. Chiefmastoras1

    Chiefmastoras1

    Joined:
    Jan 14, 2019
    Posts:
    12
    Hello, this is my first post in forum, I hope this is the right place for this question/discussion.

    Hypothesis:
    Suppose I want to make a very light game that involves some shooting between the player and the enemies. I am already using raycasting to determine whether targets are in range and visible.

    Question:
    What would be the best way to create the effect of bullet, instantiate a bullet prefab or fire a linerenderer? (assuming that I can get the visual effect from both).
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Depends. If your bullets are projectile-based, you will want to instantiate the actual bullet prefab. This bullet would then fly in the direction you were pointing when firing it off, and would potentially (if required) handle some kind of trail itself as well. If, on the other hand, you are going for a more hitscan approach (ie, you just check if the target was in front of the crosshair, if so deal damage), you basically just need to visualize the bullet trail. In this case, all options are fine, from using a linerenderer, to spawning some particles, or even writing your own shader.

    Also as a rule of thumb, with how popular shooters are, you will always find tons of tutorials on this kind of stuff :)
     
    eses likes this.
  3. Chiefmastoras1

    Chiefmastoras1

    Joined:
    Jan 14, 2019
    Posts:
    12
    Thank you for your reply.

    I have seen many approaches to that. The question was more about which way is more performant?
    1. Initiate a projectile, move it, destroy it?
    2. Use a line renderer?
     
  4. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    These are entirely different topics you are talking about. If you instantiate a projectile for a weapon that is supposed to be hitscan, your visuals may miss while the shot hits - or even vice versa.

    This depends on what effect you desire, but i'd say the most performant solution would be a custom shader.
    Followed by using a line render, and then followed by.. if you want to do something like that, using a projectile.

    If performance is your main concern here, you will need to implement object pooling for both approaches where you use a line renderer or a projectile (or any other instantated object). This way you can skip the instantiating and destroying part alltogether.

    That said, you shouldnt really pick your approach based on what performs best. You probably have a specific effect in mind. Pick the tool which is best fit to achieve this effect. If you already know that you will shoot like 4000 bullets (projectiles) per second, you will have to use a more specific solution anyways. A good example here would be DOTS, but i wouldnt generally recomment it to beginners, or say it's worth learning, unless your game absolutely required tens of thousands of units or tons of instantiating and destroying of objects.
     
    Chiefmastoras1 likes this.
  5. Chiefmastoras1

    Chiefmastoras1

    Joined:
    Jan 14, 2019
    Posts:
    12
    Thanks again, this is very helpful. Now you are directly on the point: I am planning to implement (and learn in the process) object pooling, so I am trying to pick up which effect is more performant.

    For me both having a gray line (using a linerenderer) or a projectile could work as desired effect. They both come with a sound effect, a light and some particles effects for smoke. I tried to shoot with both versions 1000 in 5 secs but I did not get much from the comparison in my Profiler. I guess they way to go - as I get it from your answer - is to to try both in a later stage of development.

    PS. If you have sometime to answer the above, drop me a hint on how a custom shader would help me here, Just a few lines or link so I can start searching.
     
  6. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    I'm really not a shader expert.
    Or at least not in a way most people use shaders since so far i only worked on raymarching :rolleyes:

    However, if an effect is purely visual, ie does not have to interact with the world again, a shader is always the most efficient thing you can do. This is because the GPU was build for visuals and, for easily paralelizable tasks like that, is orders of magnitude faster than your CPU.

    It doesnt have to be a custom shader either. You could experiment with the new VFX graph (if you use a recent version of Unity). Unity now basically offers two particle systems. The normal particle system which you are used to using, and the VFX graph. The normal particle system is CPU simulated, which also enabled particles to interact with the environment / physics / game logic and so on. The VFX graph is basically a particle shader and made for efficient visual effects. It's also graph based, like the (also new) shader graph they introduced. So you dont even have to be able to write shaders in order to use it (even tho, you will need the same conceptual understanding of how to create what effect).

    As a quick comparison, the normal particle system can handle a couple thousand at max, while the VFX graph can handle millions of particles. However, other than visually the VFX particles cannot interact with the gameworld anymore.

    Going for a purely cosmetic effect like drawing a line and maybe adding a bit of smoke is childs play for your GPU. I'm not sure how easy it would be to implement using the VFX graph, since sadly i did not yet find the time to play around with it.

    Not exactly what you are looking for but probably a decent place to start:
    https://blogs.unity3d.com/2019/04/10/upgrading-vfx-in-the-fps-sample-with-visual-effect-graph/

    Also a nice showcase. Basically all visuals other than models here are made in the VFX graph:
     
    Linux567 and Chiefmastoras1 like this.
  7. Chiefmastoras1

    Chiefmastoras1

    Joined:
    Jan 14, 2019
    Posts:
    12
    Hey thanks for the time to explain this! My background is mostly on designing large spaces (I am constructing models of music venues), I am very new to graphics. Only now I understand that neither a whole prefab or a linerenderer is not worth it just to create a visual effect (since I am already raycasting to see weather the target is visible) and thank you very much for this!
     
  8. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,590
    Not the most efficient way, no. However, it's still viable. Modern computers are pretty powerful. 'Wasting' a bit of performance here and there is not a huge deal - and you probably already did without knowing (like most of us).
    That the GPU is way, way faster for these kinds of things, doesnt mean that using the CPU for some visual effects will slow down your game. Unless you overuse it, you probably wont notice a difference. The only thing really worth mentioning is to use object pooling. Or rather.. you generally should use object pooling whenever you instantiate (and destroy) objects. This is because instantiating is rather expensive, and destroying creates garbage which eventually needs to be collected in a process called garbage collection. You want to avoid this as far as possible at runtime, since garbage collection can be an expensive process and can thus create spikes in frametimes and as such make the game feel less fluid. Unity has some tools to compensate this (like the also new incremental garbage collection), but it's generally a good idea to just not create garbage in the first place. Just to make this clear, when we say 'garbage' we really mean 'lose references', ie objects that were once used and are now not referenced anywhere anymore, thus need to be 'collected' in order to free the memory they take up. In 'older' languages like C++ you were responsible for memory management yourself, while here it's an automated process - but as such it takes up time.
     
    Chiefmastoras1 likes this.
  9. Chiefmastoras1

    Chiefmastoras1

    Joined:
    Jan 14, 2019
    Posts:
    12
    Yes I have come to understand how crucial this is, it is the next thing in my list!