Created
October 16, 2020 13:29
-
-
Save hyakugei/9e5647c283236ad37149ad0aec00972b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[RequireComponent(typeof(Rigidbody))] | |
public class Repulser : MonoBehaviour | |
{ | |
[SerializeField] | |
Collider[] colliderList; | |
[SerializeField] | |
Rigidbody rb; | |
[SerializeField] | |
float overlapRadius = 1f; | |
[SerializeField] | |
LayerMask layerMask; | |
[SerializeField] | |
LayerMask finalLayer; | |
[SerializeField] | |
float repulseForce = 1f; | |
[SerializeField] | |
float spawnStateTime = .1f; | |
enum State | |
{ | |
Spawn, | |
Disperse, | |
Solid | |
} | |
State state = State.Spawn; | |
static Collider[] items = new Collider[10]; | |
static int overlappingItemCount; | |
static int itemCounter = 0; | |
static Vector3 force = Vector3.zero; | |
float accumulator; | |
int initialLayer; | |
private void Awake() | |
{ | |
initialLayer = gameObject.layer; | |
} | |
private void OnEnable() | |
{ | |
gameObject.layer = initialLayer; | |
// reset object layer. | |
state = State.Spawn; | |
} | |
// Update is called once per frame | |
void FixedUpdate() | |
{ | |
if (state == State.Spawn) | |
{ | |
accumulator += Time.deltaTime; | |
if (accumulator >= spawnStateTime) | |
{ | |
accumulator = 0; | |
state = State.Disperse; | |
} | |
return; | |
} | |
else if (state == State.Disperse) | |
{ | |
overlappingItemCount = Physics.OverlapSphereNonAlloc(this.transform.position, overlapRadius, items, layerMask, QueryTriggerInteraction.Collide); | |
if (overlappingItemCount > 0) | |
{ | |
// still intersecting | |
force = Vector3.zero; | |
itemCounter = 0; | |
for(int i = 0; i < overlappingItemCount; i++) | |
{ | |
if (Contains(colliderList, items[i])) continue; | |
itemCounter++; | |
force += (this.transform.position - items[i].transform.position); | |
} | |
if(itemCounter == 0) | |
{ | |
// no valid colliders. | |
state = State.Solid; | |
return; | |
} | |
// bit of randomness | |
force += Random.insideUnitSphere; | |
rb.AddForce(force.normalized * repulseForce * Time.deltaTime, ForceMode.Force); | |
accumulator = 0; | |
} | |
else | |
{ | |
state = State.Solid; | |
} | |
return; | |
} | |
else if (state == State.Solid) | |
{ | |
this.gameObject.layer = finalLayer; | |
this.enabled = false; // stop getting updates. | |
} | |
} | |
private void OnDrawGizmos() | |
{ | |
Color c = Color.white; | |
if (state == State.Spawn) c = Color.red; | |
else if (state == State.Disperse) c = Color.yellow; | |
else if (state == State.Solid) c = Color.green; | |
Gizmos.color = c; | |
Gizmos.DrawSphere(this.transform.position, overlapRadius); | |
} | |
static bool Contains(Collider[] list, Collider toCheck) | |
{ | |
for(int i = 0; i < list.Length; i++) | |
{ | |
if (list[i] == toCheck) return true; | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Used to allow items (rigidbody items) to be spawned overlapping, but then to separate and become fully solid and interacting again. Requires a physics layer which interacts with the "world", but not itself. This is what the spawned item would start with for its layer. Once it is no longer in touch with other objects of its own layer, it then transitions to the "world" layer.