I am trying to implement a simple boomerang into my game. Simply, I want the player to throw it, and once it exceeds the throwDistance, I want it to return to the player.
Right now, it throws, then remains spinning in one spot without returning to the player. And if the player approaches, it pushes it further away.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerBoomerang : MonoBehaviour
{
public static PlayerBoomerang instance;
public float speed = 7.5f;
public Rigidbody2D theRB;
public float throwDistance = 1;
public int impactSound;
// Start is called before the first frame update
void Start()
{
theRB.velocity = transform.right * speed;
}
// Update is called once per frame
void Update()
{
if(Vector2.Distance(PlayerController.instance.boomerangFirePoint.position, transform.position) > throwDistance)
{
transform.position = Vector2.MoveTowards(transform.position, PlayerController.instance.transform.position, speed * Time.deltaTime);
}
}
private void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Destroy(gameObject);
PlayerController.instance.isBoomeranging = false;
}
if (other.tag == "Enemy")
{
//insert knockback script here
AudioManager.instance.PlaySFX(impactSound);
}
if (other.tag == "Boss")
{
//insert knockback script here
AudioManager.instance.PlaySFX(impactSound);
}
}
}
You are re-checking the distance every update. Even if your code detects the boomerang is at the proper range, it will only detect that for one frame.
I think the easiest solution would be to create a “isComingBack” bool that starts false. Once the distance is reached, set the bool to true. Only test the distance if the bool is false, otherwise run the logic to bring it back.
Aight I think the reason why your boomerang isnt destroyed when you bump into it is because your collider is not set to trigger, if you select your collider there should be a check box for setTrigger
Still having an issue with the boomerang getting stuck in mid-air. Here’s a gif: https://imgur.com/a/3UU7k0w
The script:
public static PlayerBoomerang instance;
public float speed = 7.5f;
public Rigidbody2D theRB;
public float throwDistance = 1f;
public bool isReturning;
public int impactSound;
// Start is called before the first frame update
void Start()
{
isReturning = false;
theRB.velocity = transform.right * speed;
}
// Update is called once per frame
void Update()
{
if(Vector2.Distance(PlayerController.instance.boomerangFirePoint.position, transform.position) > throwDistance)
{
isReturning = true;
}
if (isReturning)
{
//throwDistance = throwDistance + 1f;
transform.position = Vector2.MoveTowards(transform.position, PlayerController.instance.transform.position, speed * Time.deltaTime);
}
}
You need to add code that destroys the boomerang. I recommend you check the distance inside the if check for “isReturning” and destroy the boomerang when it’s close. Another option is to use a collider as @PuppyPolice suggested and destroy the boomerang when it touches you.
Ah but if you take a look at the gif I’m already able to destroy the boomerang - that isn’t my issue. The issue I’m encountering is that the boomerang appears to get stuck mid-air in front of the player and never returns. It’s very strange!
The rigidbody still has forward velocity from the Start function. You’re setting the transform position, and the rigidbody is also setting the transform position. So either use transform.position for everything, velocity for everything, or set velocity to 0 on the return.
Something like this might work (i didnt test this):
The easiest thing would be to set “theRB.velocity = Vector3.zero” when you set “isReturning” to true.
If you wanted to do the whole thing with velocity, you will need to update the velocity to point toward your player each fame as they move, unless you want the boomerang to fly to where they were instead of where they are.
updated my previous post with a quick code example not using rigidbody. @MSplitz-PsychoK 's solution is easiest, and would work but I think it’s a little weird to use physics for the throw but not the return.
A more specific answer: Rigidbody is used to control the transform using physics calculations. Generally when you use the Rigidbody, you never set the transform.position manually, you let the Rigidbody do it. In your code, you set the Rigidbody’s velocity, so every frame the Rigidbody moves the transform.position accordingly. That won’t end until you change the velocity somehow, or it changes due to other physics forces. So when you start to set transform.position manually in the reverse direction, both your code and the Rigidbody are applying movement. Since the velocity is set to “speed”, and you’re also moving it at “speed” in the other direction, the movement will just about cancel out.
Dude THANK YOU. I tried out what you suggested and that seemed to do it!
Unfortunately now I’m having an issue where the throwDistance isn’t being taken into consideration it seems. When I change the value the boomerang still only travels a short distance. Any thoughts?
When you declare a variable as public in a MonoBehaviour, it will be displayed in the inspector for editing. The value in the inspector will overwrite any default value you have assigned in code.
So public float throwDistance = 5f; is declaring a new variable, and assigning it a default value. Any new components of this type will start with 5 in the inspector. If you edit the inspector value however, the inspector value takes priority.