Hi all,
I’ve just started using Unity (this week) and have been through a few tutorials and run through the forums and answers areas.
I’m attempting to create a script which simulates magnetic balls, so they get attracted to the player. I’ve considered using spring joints between the player ball and the other balls but couldn’t get one working in the way I wanted. I also tried setting up multiple colliders on the player ball one for collisions and one for “sphere of magnetcs” but that came with lots of problems too.
I’ve settled for tagging the “other” balls which can be attracted by the player ball and calculating a distance and applying a simple force.
Does this seem sensible? Is there a better way?
Here’s the code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
public float speed;
public float maxDistanceAttract;
public float attractForce;
public Color magneticColor;
private Color originalColor;
private Rigidbody rb;
private bool isMagnetic = false;
private float maxDistanceAttractSqr;
private GameObject[] attractees;
private float moveHorizontal;
private float moveVertical;
void Start()
{
//this object's Rigid Body
rb = GetComponent<Rigidbody>();
originalColor = rb.GetComponent<Renderer>().material.color;
//get the objects we're trying to track
attractees = GameObject.FindGameObjectsWithTag("Attractee");
//store the sqr value for comparisons (so we're not calculating every loop
maxDistanceAttractSqr = maxDistanceAttract * maxDistanceAttract;
}
//the control tests in Update
void Update()
{
if (Input.GetKeyUp(KeyCode.Space))
{
isMagnetic = !isMagnetic; //toggle magnetic value
if (isMagnetic) {
rb.GetComponent<Renderer>().material.color = magneticColor;
} else {
rb.GetComponent<Renderer>().material.color = originalColor;
}
}
moveHorizontal = Input.GetAxis ("Horizontal");
moveVertical = Input.GetAxis ("Vertical");
}
//all the physics calcs in Fixed Update
void FixedUpdate()
{
//this objects movement
if(moveHorizontal != 0 || moveVertical != 0)
{
Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
rb.AddForce(movement*speed);
}
if (isMagnetic)
{
//the other objects attraction forces - something a bit like magnetism
foreach (GameObject attractee in attractees)
{
Vector3 heading = rb.transform.position - attractee.transform.position;
//use sqrMagnitude in the test as its not an expensive test
//limit force applying to not happen if the bodies are really close
if (heading.sqrMagnitude < maxDistanceAttractSqr && heading.sqrMagnitude > 1.8f)
{
// now get the real distance
var distance = heading.magnitude;
// calc the direction vector
var direction = heading / distance;
//force is inverse by distance
var force = attractForce / distance;
attractee.GetComponent<Rigidbody> ().AddForce (direction * force);
}
}
}
}
}
You can see it in action here, space switches magnetism on and move the player ball with arrow keys:
Thanks to anyone in advance