- Home /
Magnet effect to draw coins,Magnetic effect to draw coins
Hello,
I have a space ship and some coins in my game. When I move my space ship towards the coins I want to have a magnetic effect so that the spaceship draws all the coins in. The code below does not work in my case. I have a circlecollider2d attached to a child of all my coins. The idea is when any coin comes nearer and nearer towards my spaceship the spaceship draws all of the coins in. But it's not working. Any help, please?
This code is attached to the coin.
public GameObject attractedTo;
public float radius;
public float force;
private bool inside;
private Transform magnet;
private Rigidbody2D rb;
void Start() {
rb = attractedTo.GetComponent<Rigidbody2D>();
magnet = GameObject.Find("Magnet").GetComponent<Transform>();
inside = false;
}
void FixedUpdate () {
if(inside) {
Vector3 magnetField = attractedTo.transform.position - magnet.position;
magnetField.z = 0;
float index = (radius - magnetField.magnitude) / radius;
rb.AddForce(force * magnetField * index, ForceMode2D.Force);
}
}
void OnTriggerEnter2D (Collider2D other) {
if (other.gameObject.tag == "PlayerShipTag") {
inside = true;
}
}
void OnTriggerExit2D (Collider2D other) {
if (other.gameObject.tag == "PlayerShipTag") {
inside = false;
}
}
Basic questions: is your radius greater than 0? Is the collider on your coins set to trigger? $$anonymous$$ore importantly, what doesn't work? Do the coins not move at all, or they move, but not in the right direction?
Also, I just noticed an issue: index
will be negative when outside radius
, so outside the radius objects will be pushed away ins$$anonymous$$d of attracted. Of course, this is not an issue if radius
is the same size as the trigger collider, but it could become a bug.
Answer by toddisarockstar · Apr 03, 2018 at 09:18 PM
multiplying the inverted distance by speed would make the coin move towards faster as it gets closer. attach this to your coin
void Start () {
ship = GameObject.Find("name of spaceship here").transform;
}
void Update () {
float dis = Vector3.Distance (ship.position, transform.position);
if (dis < 30) {
float speed = 30-dis;
speed = speed *Time.deltaTime*.5f;
transform.position = Vector3.MoveTowards (transform.position, ship.position, speed);}
}
Thanks. It works but my game runs very choppy now (slow). Is there an alternative available (ins$$anonymous$$d of Vector3.Distance)?
I thought that solution would not be efficient enough. You should not check for distance in Update()
, especially if multiple objects have the script. I will try to write up a answer.
Answer by Vilhien · Apr 03, 2018 at 11:18 PM
I do something similar to my fuel drops for my ship.
This script is attached to your (coin) that has a rigidbody component. Obviously you might want to set your distance a bit closer in your case ;)
public class gather : MonoBehaviour
{
Transform player;
public float distance;
Rigidbody move;
// Use this for initialization
void Start () {
move = GetComponent<Rigidbody>();
player = GameObject.FindGameObjectWithTag("Player").transform;
}
// Update is called once per frame
void Update ()
{
distance = Vector3.Distance(transform.position, player.transform.position);
if (distance < 115900)
{
move.AddForce((player.transform.position - transform.position) * (16));
}
}
}
Thanks for your solution! I changed the line with the Vector3.Distance to distance = (this.transform.position - player.transform.position).sqr$$anonymous$$agnitude; because it's much faster than Vector3.Distance. It's working now!:)
awesome, I will try sqr mag as well. I have heard its faster but I never adopted it into my code. Glad to hear it worked and feel free to contact me anytime, I'm relatively new by about five months but happy to brainstorm or help where I can.
Answer by tormentoarmagedoom · Apr 03, 2018 at 03:48 PM
Distance is already considered when using magnetField.magnitude
, magnetField
being attractedTo.transform.position - magnet.position
.
$$anonymous$$y game ran very choppy when I tried this out. But thanks for the hint anyway.
Answer by Harinezumi · Apr 04, 2018 at 12:57 PM
As written above, this would be my solution. You need a Collider2D set to trigger on the object you want this object to be attracted to and set its tag to "PlayerShipTag". I would also suggest to store magnetStrength
and magnetRange
on the player, to avoid attracting objects differently, but that is a different topic.
public class MagnetAttractable : MonoBehaviour {
[SerializeField] private float magnetStrength;
[SerializeField] private float magnetRange;
private Rigidbody2D ownRigidbody;
private Transform attractedTo;
private void Awake () {
ownRigidbody = GetComponent<Rigidbody2D>();
}
private void OnTriggerEnter2D (Collider2D other) {
if (other.gameObject.tag == "PlayerShipTag") {
attractedTo = other.transform;
}
}
private void OnTriggerExit2D (Collider2D other) {
if (other.gameObject.tag == "PlayerShipTag") {
attractedTo = null;
}
}
private void FixedUpdate () {
if (attractedTo != null) {
Vector3 direction = (attractedTo.position - transform.position).normalized;
float forceFactor = 1 - direction / magnetRange; // magnetism is actually inversely proportional to the square of distance, but this is good enough approximation
if (forceFactor > 0) {
ownRigidbody.AddForce(direction * magnetStrength, ForceMode2D.Force);
}
}
}
}
Answer by diego-giacomelli · Aug 08, 2020 at 11:27 AM
@drpelz, I think you could try to use a PointEffector2D.
This video tutorial is a good start point: https://www.youtube.com/watch?v=znciJ1-QRX8