Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

specific collsion detection

Discussion in 'Scripting' started by azabug, Aug 27, 2007.

  1. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Hello unity3D gurus
    Simple q for ya
    I want to call up a particle effect when a collision with one object occurs ..
    how do I determine whether it's the object I want ..
    eg
    I've set up a water plane ... I'm dropping other objects into it (cubes) ... they topple and fall colliding with each other and some other objects I've set up .. I only want the splash particle effect to occur when those objects hit the water plane ... ignoring the collision with non water plane objects

    what's the best approach?

    p.s.
    I've been adding the script to the cubes ... which are instantiated at start ... due to the volume of objects hitting the water I thought that would be the best angle ... should I use the Physics.IgnoreCollision method? if so .. can you give me an example of it?

    thanx

    I've been testing (probably incorrectly) for a variable I set up
    Code (csharp):
    1. var water : GameObject;
    2. var splash : GameObject;
    3.  
    4. function OnCollisionEnter (collision : Collision) {
    5.     if (splash != null) {
    6.         if (Collision.gameObject == water) {
    7.             Instantiate (splash, transform.position, transform.rotation);
    8.         }
    9.     }
    10. }
    I guess I'm way off ...

    Would a nooB disclaimer excuse me dumbness?
     
  2. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Make the water plane's collider a trigger by checking the Is Trigger box in the inspector. This will allow it to detect when other colliders enter it, but it will not impede their motion. Then attach something like this to the water:
    Code (csharp):
    1. var splash : GameObject;
    2.  
    3. function OnTriggerEnter(other : Collider) {
    4.     Instantiate(splash, other.transform.position, Quaternion.identity);
    5. }
    This will make a splash every time an object enters the water. Drag your splash prefab to the Splash variable in the inspector.
     
  3. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Thanks Muriac
    I tried that earlier but had the wrong collider (I guess) for some reason I'd set a raycast collider to the water plane ... now I'm using a mesh collider ...

    now for some fun (splash)
    thanks again

    I'll let you know how it turns out
     
  4. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Couple of spin off q's
    essentially that works but there's a time delay ... the object hits the water then ... after a second or two the splash appears ... is that relative to my machine/graphics card ...
    there's around 40 to 100 objects hitting the water ...

    also a strange bug is occurring whereby the first time I hit play it does but when I restart it ... the camera gets frozen ... weird

    also what would be the best dispose of method?
    should I use destroy? the autodestuct appears to only kill emisions after they've been emitted ...

    nooB disclaimer
    -Folks are dumb where I come from!
     
  5. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    There shouldn't be a delay. Try switching to a box collider on the water mesh, since all you need is a flat surface.

    I'm not sure about your camera problem. How are you moving the camera?

    I see you've found the bug in the autodestruct property where it doesn't work if emit is already true. Here's how to get around that:

    1. Make sure Emit is false in your prefab particle system
    2. Make sure One Shot is true.
    3. Make sure Autodestruct is true.
    4. Modify the script attached to the water so it looks like this:
    Code (csharp):
    1. var splash : ParticleEmitter;
    2.  
    3. function OnTriggerEnter(other : Collider) {
    4.     var newSplash : ParticleEmitter = Instantiate(splash, other.transform.position, Quaternion.identity);
    5.     newSplash.Emit();
    6. }
    5. Re-link the splash prefab to the script in the inspector, even though it appears to be linked already. This is because Unity doesn't notice if you change a variable's type (in this case from GameObject to ParticleEmitter) but keep the name the same.
     
  6. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Excellent! Totally excellent!

    That worked a treat ... the timing of things makes sense now and the particles are killing themselves softly with your code/song ....

    Got a few new q's for you ....

    1/. If I wanted to affect the angle that the particle emitted at, relative to the object that hits the water, say an object has x and z movement as well as y movement ... to get the splash to behave in a more physically correct manner ... what would you suggest?

    1/a. Just want to adjust the pos and size of the splash a little ... when I use the particle emitter to adjust scale of the particle it forces the splash to submerge so that only a portion of it is visible ... where should I adjust the y pos of the particle?

    2/. Is there a way to continue the particle instantiations based on GameObject movement? ie The objects hitting the water bounce a few times before they settle into a stationary position. I'd love for them to continue to have an effect on the water plane for as long as they move ...
    So I guess I need a way to test for that movement right ... then instantiate "splash" at that new pos then stop instantiation process when movement is stopped ... but what is the correct method tp do that?

    3/. Also hoping to move objects with the game controller ... ie character walks into something and affects it based on both objects mass etc. I've been looking through the manual but haven't had any luck yet in finding the relevant code or example ... could you point me in the right direction? is there a straight forward solution or is there a tutorial I should do to get me up to speed?

    Thanx again ...
     
  7. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I believe water is displaced approximately as a reflection of the impact angle. Because your plane's normal is pointing straight up, the angle you want can be calculated in the :
    Code (csharp):
    1. var angleOfReflection = Vector3.up; //just in case there is no rigidbody
    2. if (other.rigidbody) {
    3.     other.rigidbody.velocity; //get velocity
    4.     angleOfReflection.y = -angleOfReflection.y; //reflect it
    5. }
    Whenever I have particle systems that I want to point in certain directions, I make sure the bulk of the force is in the local Z direction. That way, I can use transform.LookAt() to point it in a given direction. Once you've done this, you can add this line after the Instantiate, but before the emit:
    Code (csharp):
    1. newSplash.transform.LookAt(other.position + angleOfReflection);
    I will add answers to your other questions later, because I'm at work. :)
     
  8. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    I think I get the concept ... however in this example the code ..
    Code (csharp):
    1. newSplash.transform.LookAt(other.position + angleOfReflection);
    is returning the error ..
    What have I missed?
    Code (csharp):
    1. function OnTriggerEnter(other : Collider) {
    2.    
    3.     var angleOfReflection = Vector3.up; //just in case there is no rigidbody
    4.     if (other.rigidbody) {
    5.         //other.rigidbody.velocity; //get velocity
    6.         angleOfReflection.y = -angleOfReflection.y; //reflect it
    7.         }
    8.        
    9.     var newSplash : ParticleEmitter = Instantiate(splash, other.transform.position, Quaternion.identity);
    10.     newSplash.transform.LookAt(other.position + angleOfReflection);
    11.     newSplash.Emit();
    12. }
    I commented out velocity for the time being as that was also returning an error ...
    nooB Alert!

    p.s.
    Totally appreciate your help with this Muriac!
     
  9. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Sorry, that was a mess because I didn't give it enough time. Here's what the code should look like:
    Code (csharp):
    1. function OnTriggerEnter(other : Collider) {
    2.     var angleOfReflection : Vector3;
    3.    
    4.     if (other.rigidbody) {
    5.         angleOfReflection = other.rigidbody.velocity; //get velocity
    6.         angleOfReflection.y = -angleOfReflection.y; //reflect it
    7.     } else { //default angle is up
    8.         angleOfReflection = Vector3.up;
    9.     }
    10.    
    11.     var newSplash : ParticleEmitter = Instantiate(splash, other.transform.position, Quaternion.identity);
    12.     newSplash.transform.LookAt(other.transform.position + angleOfReflection);
    13.     newSplash.Emit();
    14. }
     
  10. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    For particle size, are you using ParticleRenderer.velocityScale? If so, try making the value you have negative. This will make particles stretch out ahead of themselves rather than behind, preventing the "bundle of hay" effect you might be seeing.

    For continued splashing, you'll probably want to use OnTriggerStay(). This function is very similar to OnTriggerEnter(), except that it is called every frame that a collider is in a trigger. Once a frame is probably too often for splashes, so you'll have to use a counter or some sort of random chance to determine whether a splash is generated.

    Moving objects with a CharacterController can be accomplished with one of the scripts in the 3D Platform Game example project on this page.
     
  11. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Thanks a bundle Muriac ...
    I've gotta duck out for a few hours ... but when I return I'll try all that you mentioned ... and let ya know how it goes ... and all about the new probs that no doubt I'll be encountering ...

    Thanks heaps for you help ...

    p.s.
    How long can I use the nooB disclaimer for do ya reckon?
    till then .... nooB Alert!
     
  12. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    As soon as you pass your knowledge on to someone else. That'll probably be pretty soon if you keep at it. :)
     
  13. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Hi Muriac ... had a go at the OnTriggerStay function using a counter as you suggested ... (which was reassuring as I'd wondered if that was the method I should use so your suggestion encouraged me to persevere with it until I got it right ... almost there now ... except for one thing ...
    Code (csharp):
    1. var splash : ParticleEmitter;
    2. var moveIt = Vector3();
    3. private var t = 1;
    4.  
    5. function OnTriggerStay(other : Collider) {
    6.     t = t + 1;
    7.     h2o = GameObject.Find("Plane_W");
    8.     var waterY = (h2o.transform.position.y * -2);
    9.     Debug.Log(waterY);
    10.     if (t > 120) {
    11.         t = 1;
    12.         if (other.attachedRigidbody) {
    13.             if (other.transform.position != moveIt) {
    14.                 var moreSplash : ParticleEmitter = Instantiate(splash, other.transform.position + Vector3(0,waterY,0), Quaternion.identity);
    15.                 moreSplash.Emit();
    16.                 }
    17.         }
    18.     }
    19.     moveIt = other.transform.position;
    20. }
    moveIt = other.transform.position, which I'm attempting to use to determine whether or not the object hitting the water is moving, always appears to return a different value which I'm assuming is because of the many objects that are referring to the script ... I'm thinking that I should set the moveIt variable within the objects that collide with the water plane then pass that value on to the water plane splash script ... does that make sense to you?
    I mean do you think that's the right approach? Or is there another way? ... also if it is the right approach what method do you think I should use? The objects hitting the water plane aren't children to it ... so there's no ancestor relationship ...
    The timer works reasonably well and I feel like it's getting close to the desired effect ... just a matter of stopping it as each object stops moving ...

    p.s
    Played around with the rotation script ... it returns no errors ... but it's hard to determine whether it's having any affect on the particle emissions rotation ...
    Code (csharp):
    1. var splash : ParticleEmitter;
    2. var moveIt = Vector3();
    3.  
    4. function OnTriggerEnter(other : Collider) {
    5.    
    6.     if (other.rigidbody) {
    7.         angleOfReflection = other.rigidbody.velocity; //get velocity
    8.         angleOfReflection.y = -angleOfReflection.y; //reflect it
    9.         } else { //default angle is up
    10.         angleOfReflection = Vector3.up;
    11.     }
    12.  
    13.     var newSplash : ParticleEmitter = Instantiate(splash, other.transform.position, Quaternion.identity);
    14.     newSplash.transform.LookAt(other.transform.position + angleOfReflection);
    15.     newSplash.Emit();
    16.  
    17. }
    according to the Debug.Log it's returning correct coordinates ... when I tested for the three different properties ... angleOfPosition, other.transform.position and other.transform.position + angleOfReflection ... theoretically it's working ... it's subtle though (if it's actually happening in practice) ...

    anyway cheers for now ... I'm gonna have another bash at it ... I think I'm gonna try broadcasting the moveIt variable from the objects hitting the water ... somehow
    (back to the manual)
     
  14. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    I don't know why it didn't occur to me earlier ...
    but testing for the velocity was the answer ... here's the code thus far ..
    Code (csharp):
    1. function OnTriggerStay(other : Collider) {
    2.     t = t + 1;
    3.     h2o = GameObject.Find("Plane_W");
    4.     var waterY = (h2o.transform.position.y * -1.5);
    5.    
    6.     if (other.rigidbody) {
    7.         angleOfReflection = other.rigidbody.velocity; //get velocity
    8.         angleOfReflection.y = -angleOfReflection.y; //reflect it
    9.         } else { //default angle is up
    10.         angleOfReflection = Vector3.up;
    11.     }
    12.    
    13.     if (other.rigidbody.velocity.x < 0.1) {
    14.         if (other.rigidbody.velocity.y < 0.1) {
    15.             if (other.rigidbody.velocity.z < 0.1) {
    16.                 var stop = 1;
    17.             }
    18.         }
    19.     }
    20.    
    21.     if (t > 10) {
    22.         t = 1;
    23.         Debug.Log(stop);
    24.         if (stop != 1) {
    25.             if (other.attachedRigidbody) {
    26.                 if (other.transform.position != moveIt) {
    27.                     var moreSplash : ParticleEmitter = Instantiate(splash, other.transform.position + Vector3(0,waterY,0), Quaternion.identity);
    28.                     moreSplash.transform.LookAt(other.transform.position + angleOfReflection);
    29.                     moreSplash.Emit();
    30.                     var moreWaves : ParticleEmitter = Instantiate(waves, other.transform.position, Quaternion.identity);
    31.                     moreWaves.transform.LookAt(other.transform.position + angleOfReflection);
    32.                     moreWaves.Emit();
    33.                     var moreSploosh : ParticleEmitter = Instantiate(sploosh, other.transform.position, Quaternion.identity);
    34.                     moreSploosh.transform.LookAt(other.transform.position + angleOfReflection);
    35.                     moreSploosh.Emit();
    36.                     Instantiate(ripple, other.transform.position - Vector3(0,0.3,0), Quaternion.identity);
    37.                 }
    38.             }
    39.         }
    40.     }
    41.     moveIt = other.transform.position;
    42. }
    43.  
    now I'm getting an error pertaining to the camera not having a rigid body ... so I'll either give it one or I'll make an exception of it ...
    but for now I'd like to focus on creating an animation for the ripple ... thought about making it a particle but was having troubles aligning the rotation so I've settled for a mesh with a bump map ... time for a quick tutorial on importing animations/bumps ...
    thanks heaps for your help thus far Muriac ..

    I'll post the result on the web so you can view it in the near future ... cheers for now!
     
  15. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    Hi ...
    Thanks for all the pointers ...
    I've posted an example of the script I'm using at the moment .. http://www.az.suiteaz.com/fluid/?q=node/32
    Although the waters refraction texture isn't behaving on all browsers ... you'll get the Idea ...
     
  16. AaronC

    AaronC

    Joined:
    Mar 6, 2006
    Posts:
    3,552
    Sheesh was it really neccessary to have so many cubes? Thats the slowest webplayer of all time, I had to force quit Safari...

    :roll: :wink:
     

    Attached Files:

  17. azabug

    azabug

    Joined:
    Aug 8, 2007
    Posts:
    111
    ooops ... :oops:

    looks like you found the instantiate key "q" .... yeah I was testing the limits of the script in terms of finding out what's a reasonable amount of objects to have at any given moment ... I came to the conclusion that for this script ... around 120 objects was the limit before it became too clunky and slow .... and even that was stretching it .... maybe I should post a more web player friendly version?

    p.s

    nice screen shot ...

    p.p.s
    I noticed that the refraction texture has come up as the "red 4" ... weird ... on my browsers (safari firefox) it comes up the way I intended .... yet I'm seeing this red 4 on some other browsers ..... what's that about?? ... anyone know??