Search Unity

Is this too expensive? Are there better ways of doing this?

Discussion in 'Scripting' started by Not_Sure, Jul 14, 2022.

  1. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    I I’m trying to implement footsteps sounds and particle effects for bullets and I’m kind of reaching the point where I just want to throw my hands up and to save myself a lot of trouble simply prefix The name of each material with a type, then every time I am making a particle effects from shooting it or walking on it it will look at the name of the material and send out the appropriate sound or effect.

    would it be better to make a script that changes the tag based on the material name?

    And this is kind of embarrassing, but how would I do that inside the editor so I don’t have to do it playtime?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Why not just put a MonoBehaviour on the colliders you want that specifies what sound they make?

    Perhaps have a little pick list with GRAVEL, WOOD, METAL, GRASS enums, then you can select all the grass and make them GRASS, etc.

    Your steps would raycast down, see what collider they hit, see if it has such a MonoBehaviour, if it does, then it would read what type of noise to make??

    That keeps it completely separate from any Material naming issue. I hate naming mechanisms because you're going to cross channels at some point in the future and be very sad panda, or, I suppose sad teddy bear in your case.
     
  3. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Because making a math that way would be a nightmare. If not out right impossible.

    Right now it looks like I will most likely be using Pro builder, and I really don’t wanna try to be making a new object for every single surface.
     
  4. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Performance is going to be a huge deal for me because I will be having as many enemies on screen at once, but I am wondering if this is something worth sacrificing.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    I'll go out on a limb and say one extra raycast down per frame (or even per footstep event, which is perhaps 4 to 5 times per second?) isn't gonna break the bank.

    I'll assume the word "math" was meant to mean "map" and say, "Really?" Because you already should be organizing your level so it's easy to get at the parts you make, and thus easy to select all the grass and drop a "SurfaceAudioProperties" script on them.

    I use the same approach for Damage Properties all the time, such has this one for my Jetpack Kurt game:

    (In this case I just check the collider I hit from the OnCollisionEnter-ish type callbacks)

    Code (csharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. // @kurtdekker - part of Jetpack Kurt
    6. //
    7. // Stick these on environmental objects to modify how much
    8. // they damage you on impact.
    9. //
    10. public class DamageProperties : MonoBehaviour
    11. {
    12.    [Tooltip( "Any contact is deadly.")]
    13.    public    bool    Deadly = false;
    14.  
    15.    [Tooltip( "How does this kill you?")]
    16.    public    DeadlinessType    Deadliness;
    17.  
    18.    [Tooltip( "Added to speed before check against to-damage.")]
    19.    public    float    DamageAdditivePreadjust;
    20.  
    21.    [Tooltip( "After damage is translated into speed, it is multiplied by this.")]
    22.    public    float    DamageMultiplier;
    23.  
    24.    void Reset()
    25.    {
    26.        Deadly = false;
    27.        Deadliness = DeadlinessType.SINK;
    28.        DamageAdditivePreadjust = 0.0f;
    29.        DamageMultiplier = 1.0f;
    30.    }
    31. }
    and

    Code (csharp):
    1. public enum DeadlinessType
    2. {
    3.    SINK,
    4.    BLOOD,
    5.    FIRE,
    6.    SHAKING,
    7.    ELECTROCUTION,
    8.  
    9.    // NEVER MODIFY ABOVE, only ADD new entries, otherwise serialization breaks!
    10.  
    11.    // TODO: some future ideas to implement
    12. //    SINK_IN_WATER,            // make a splash
    13. //    SINK_IN_LAVA,            // make a sizzle
    14. //    EXPLODE,                // an enormous explosion and fire around you
    15. }
     
  6. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Lol, yes maps.

    Maybe I misunderstand what you’re saying, but what I’m getting at is that when I am making a map with pro builder if I want different surfaces using a mono behavior I am going to have to make different objects for each surface.

    But if I am using the material name to determine how it interacts then I can just paint the different materials I want with no extra steps.

    my concern isn’t that a raycast is expensive, in fact I will be using a raycast regardless, it would be looking up the material name Time I shoot a surface or make a foot step.

    And correct me if I’m wrong, but isn’t looking up part of a string really expensive?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Fair enough... I just always find that binding two things together (name of a Material and audio of a footstep) seems to always end up painting me into some kind of corner.

    I get that it is reasonable for a grass material to be bound to a grass footstep sound, but yet, in practice on often needs to diverge from the other for either future or currently unforeseen reasons.
     
  8. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    My thought on the matter was I would use something simple like name each material starting with a code to determine the material type.

    as an example:
    GRV_ smallRocks
    GRV_largeRocks
    MTL_shipHull
    WOD_oldPlank

    Then just make a script where it looks of the three first letters and decides what to do with it in each situation.

    and when I use that in Pro builder I don’t have to do anything at all to the models.

    but again, it just seems really expensive and I’m wondering if there’s a better way.
     
  9. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    And I know what you’re gonna tell me, and I should’ve thought of this before hand, I need to do a stress test and just prototype it.
     
    Kurt-Dekker likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    We humans are bad judges of this. Make it and see, and if you start to see issues, check the profiler to make sure this is actually the issue. I'm going to guess it never will be.

    If it turns out to by very expensive, one trivial optimization is to study the scene at load time, look at all those Material string names ONCE, and inject appropriate "I am grass when you walk on me" marker MonoBehaviours.
     
  11. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    OK, this is where I guess I’m getting lost.

    so let’s say I make a map and pro builder.

    I will probably sketch it out and save an instance of it As one object.

    that object is going to have several materials on it.

    how is it going to be possible to put a script on these individual materials, while the map is one object?
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    That is an EXCELLENT question... and I thought you had me! I was really ready to just throw my keyboard away and walk away from every opinion I could ever have about game programming again.

    But then I realized, nah, could still easily do it at scene load time, with some more code. :)

    At start of level we have:

    MeshRenderer with multi-submesh Mesh in MeshFilter, using many materials, and MeshCollider with that mesh.

    On load we do:

    Destroy the MeshCollider
    For each submesh in the mesh:
    - add a child GameObject with MeshCollider
    - create a new Mesh containing ONLY that mesh (two array copies, verts and tris)
    - feed this Mesh to your new MeshCollider child
    - add an appropriate FootstepSoundProperties MonoBehaviour to it
    - decide what this is by string compare (or whatever) on the Material in the MeshRenderer
    - fill out the FootstepSoundProperties with info based on what the material name was
     
    Not_Sure likes this.
  13. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Would that leave seams?

    Originally I was going to use doom builder to make my maps and export them as an obj, but the model it generated left seams everywhere causing light to go haywire and allowing the player to slip between them at high speeds (the player can go ~Mach 1 under the right circumstances :D) or if they get pushed through them by an enemy.

    And I have attempted to make a script that will help stop this but it still happened enough to give up on having seams.
     
  14. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Then keep the original collider, put the new colliders in a new layer that collides with nothing (physics matrix), then raycast explicitly at the new layer.

    Next? :)
     
    Not_Sure likes this.
  15. Not_Sure

    Not_Sure

    Joined:
    Dec 13, 2011
    Posts:
    3,546
    Nice!

    Thanks again!