- Home /
How to send a signal when something stops happening?
When my character controller is pushing a crate, the pushing script calls the PlayPushingSound() function on the crate to play a dragging sound… But how can I tell it when I've stopped pushing the crate, thus ceasing the sound playback?
I could just add an update function that's always running on the crate script but seems kinda inefficient. Is there a better way?
(Simplified):
function OnControllerColliderHit (hit : ControllerColliderHit) {
var body : Rigidbody = hit.collider.attachedRigidbody;
// Calculate push direction from move direction, we only push objects to the sides
// never up and down
var pushDir = Vector3 (hit.moveDirection.x, 0, hit.moveDirection.z);
// push with move speed but never more than half runspeed
body.velocity = pushDir * pushPower * Mathf.Min (controller.GetSpeed (), controller.movement.runSpeed/2);
hit.gameObject.GetComponent(PushingSoundEffect).PushingSound();
}
Script attached to crate:
function PushingSound() {
// Don't restart audio clip
if (audio.isPlaying)
return;
audio.Play();
}
@script RequireComponent(AudioSource)
Answer by programmrzinc · Mar 06, 2012 at 10:18 PM
I am pretty sure this would work...
function OnCollisionExit () {
audio.Stop() //or whatever it is
}
I gave it a try as this was a simpler route but no luck — the character never actually goes into the collider in the first place (as he's just pushing it), so I don't believe it could work for this.
Oh sorry, I got my triggers and collisions mixed up. I gave it another try but can't seem to get it to recognize the collision with the player, it only recognizes what I assume is the floor.
Answer by Kiloblargh · Mar 06, 2012 at 11:14 PM
If the crate can slide for a while after you stop pushing it and you want the sound to play until it comes to a rest, just check repeatedly ( but not every frame in Update ) if the rigidbody is sleeping:
var myRB : Rigidbody // drag on in inspector, don't repeatedly call GetComponent
function OnCollisionEnter()
{
InvokeRepeating("AmIMoving", 0.0, 0.3); //precise enough but much cheaper than Update()
}
function AmIMoving()
{
if (myRB.IsSleeping)
{
audio.Stop();
Debug.Log("Crate has come to rest.")
CancelInvoke("AmIMoving");
}
}
Great idea… Though wouldn't this invoke a hundred different copies of AmI$$anonymous$$oving ?
Derrr. Yes, it would in fact do that. Sorry. Easy enough to fix, though: if (!IsInvoking("AmI$$anonymous$$oving")) { InvokeRepeating("AmI$$anonymous$$oving", 0.01, 0.3); }
Another thought- if you already have a repeating test function like that you could use it to check the XZ velocity of the rigidbody and if it's under a certain absolute value lower the volume of your scraping sound, and raise the pitch if it's over another value.
Hey the dynamic pitching is a pretty good idea actually.
Just one question, why—at the top of your code—say to drag the rigidbody into the inspector? It's a crate… there's like, a billion crates in the level. I think the only way I can do it is to repeatedly call GetComponent while I'm pushing the crate, right?
$$anonymous$$aybe I should totally rewrite my pushing script so there's an invisible trigger collider always in front of the character… Would that be better that my current method of OnControllerColliderHit, do you know?
Answer by Kiloblargh · Mar 07, 2012 at 09:07 PM
I dunno; I don't entirely trust the CharacterController enough to want to use it. IMHO it feels like something the Unity team cooked up primarily to make the built-in tutorial examples seem as if scripting gameplay in Unity is easier than it is in real life and not something they actually expect you to use in your game. If you can work out your own character control script from scratch you'll have a full understanding of how to make it do what you want it to do.
Your answer
Follow this Question
Related Questions
How can I stop executing a Function in a void Function? 1 Answer
How to Stop all audio 10 Answers
Why does my function play sounds on startup? 4 Answers
How do I pause/stop an audio clip that I choose, on a certain condition? 2 Answers
If a number reaches a certain value send it to another script to play a sound?? 1 Answer