You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
3.4 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Autohand {
public enum MagnetEffect {
Attractive,
Repulsive
}
[Serializable]
public class UnityMagneticEvent : UnityEvent<MagneticSource, MagneticBody> { }
[Serializable]
[HelpURL("https://app.gitbook.com/s/5zKO0EvOjzUDeT2aiFk3/auto-hand/extras/magnetic-forces")]
public class MagneticSource : MonoBehaviour {
public Rigidbody body;
public MagnetEffect magneticEffect;
public float strength = 10f;
public float radius = 4f;
public ForceMode forceMode = ForceMode.Force;
public AnimationCurve forceDistanceCurce = AnimationCurve.Linear(0, 0, 1, 1);
public int magneticIndex = 0;
public UnityMagneticEvent magneticEnter;
public UnityMagneticEvent magneticExit;
List<MagneticBody> magneticBodies = new List<MagneticBody>();
float radiusScale;
private void Start() {
if(body == null)
body = GetComponent<Rigidbody>();
radiusScale = transform.lossyScale.x < transform.lossyScale.y ? transform.lossyScale.x : transform.lossyScale.y;
radiusScale = radiusScale < transform.lossyScale.z ? radiusScale : transform.lossyScale.z;
}
private void FixedUpdate() {
foreach(var magneticBody in magneticBodies) {
var position = transform.position;
var otherPosition = magneticBody.transform.position;
var distance = Vector3.Distance(position, otherPosition);
if(distance < radius * radiusScale) {
var distanceValue = distance / (radius * radiusScale + 0.0001f);
var distanceMulti = forceDistanceCurce.Evaluate(distanceValue) * magneticBody.strengthMultiplyer * strength;
distanceMulti *= magneticEffect == MagnetEffect.Repulsive ? -1 : 1;
magneticBody.body.AddForce((position - otherPosition).normalized * distanceMulti, forceMode);
}
}
}
private void OnTriggerEnter(Collider other) {
if(other.attachedRigidbody != null && other.CanGetComponent<MagneticBody>(out var magnetBody)) {
if(!magneticBodies.Contains(magnetBody) && magnetBody.magneticIndex == magneticIndex) {
magneticBodies.Add(magnetBody);
magneticEnter?.Invoke(this, magnetBody);
magnetBody.magneticEnter?.Invoke(this, magnetBody);
}
}
}
private void OnTriggerExit(Collider other) {
if(other.attachedRigidbody != null && other.CanGetComponent<MagneticBody>(out var magnetBody)) {
if(magneticBodies.Contains(magnetBody)) {
magneticBodies.Remove(magnetBody);
magneticExit?.Invoke(this, magnetBody);
magnetBody.magneticExit?.Invoke(this, magnetBody);
}
}
}
private void OnDrawGizmosSelected() {
Gizmos.color = Color.blue;
var radiusScale = transform.lossyScale.x < transform.lossyScale.y ? transform.lossyScale.x : transform.lossyScale.y;
radiusScale = radiusScale < transform.lossyScale.z ? radiusScale : transform.lossyScale.z;
Gizmos.DrawWireSphere(transform.position, radius * radiusScale);
}
}
}