I have the following Game Object (box) falling when the player enters a danger zone (triggered by a collider), but what I want is the Box to shake for half a second before falling. I assume a coroutine would be the best way for this to happen and I have the code to make the box fall, but I'm not sure how to make the box shake through my script.
screenshot
Here's my code, in case it might be useful to understand:
public class FallingBox : MonoBehaviour
{
[SerializeField] float fallSpeed = 3f;
[SerializeField] Transform target;
Rigidbody2D rigidbody;
BoxCollider2D boxCollider;
bool isFalling = false;
void Start()
{
rigidbody = GetComponent<Rigidbody2D>();
boxCollider = GetComponent<BoxCollider2D>();
}
void Update()
{
var frameMovement = fallSpeed * Time.deltaTime;
var targetPosition = target.transform.position;
if (isFalling)
{
transform.position = Vector2.MoveTowards(transform.position, targetPosition, frameMovement);
if (transform.position == targetPosition)
{
gameObject.layer = LayerMask.NameToLayer("Ground");
boxCollider.enabled = true;
}
}
}
//Called when entering the "danger zone"
public void ChangeStatus()
{
isFalling = true;
}
Maybe something like this? I left much of your normal fall code alone, just coroutined it.
The idea is to have a sin wave drive the shake, so it's a bit of a smooth shake.
public class FallingBox : MonoBehaviour
{
[SerializeField] float fallSpeed = 3f;
[SerializeField] Transform target;
Rigidbody2D rigidbody;
BoxCollider2D boxCollider;
void Start()
{
rigidbody = GetComponent<Rigidbody2D>();
boxCollider = GetComponent<BoxCollider2D>();
}
//Called when entering the "danger zone"
public void ChangeStatus()
{
StartCoroutine(OnStartFall());
}
IEnumerator OnStartFall()
{
var maxTrembleTime = 0.25f;
var currentTime = 0.0f;
while(currentTime < maxTrembleTime)
{
currentTime = Mathf.Clamp(currentTime + Time.deltaTime, 0, maxTrembleTime);
// sinOffset = 0 will have us back at the same point.
// You might want to scale this number by a constant to make it shake faster or slower
var sinOffset = (maxTrembleTime - currentTime);
var offset = Mathf.Sin(sinOffset); // Scale this offset to make it shake over more distance
transform.position.y += offset;
yield return null; // wait until next frame
}
// Begin normal falling code
while(true)
{
var frameMovement = fallSpeed * Time.deltaTime;
var targetPosition = target.transform.position;
transform.position = Vector2.MoveTowards(transform.position, targetPosition, frameMovement);
if (transform.position == targetPosition)
{
gameObject.layer = LayerMask.NameToLayer("Ground");
boxCollider.enabled = true;
break;
}
yield return null; // wait until next frame.
}
}
}
I did this code now, I think it might help:
IEnumerator Tremble() {
for ( int i = 0; i < 10; i++)
{
transform.localPosition += new Vector3(5f, 0, 0);
yield return new WaitForSeconds(0.01f);
transform.localPosition -= new Vector3(5f, 0, 0);
yield return new WaitForSeconds(0.01f);
}
}
The idea is to change directly the localPosition very fast to different directions. Check if it is what you are looking for or if you can work on it to get there 😉
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With