162 lines
4.2 KiB
C#
162 lines
4.2 KiB
C#
using UnityEngine;
|
|||
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System;
|
||
|
|
|
||
|
|
|
||
|
|
[Serializable]
|
||
|
|
public class GravityRayConfig{
|
||
|
|
public float radius = 0.5f;
|
||
|
|
public float length = 5.0f;
|
||
|
|
public float tileLength = 3.0f;
|
||
|
|
|
||
|
|
public static bool operator==(GravityRayConfig c1, GravityRayConfig c2){
|
||
|
|
return c1.radius == c2.radius && c1.length == c2.length && c1.tileLength == c2.tileLength;
|
||
|
|
}
|
||
|
|
public static bool operator!=(GravityRayConfig c1, GravityRayConfig c2){
|
||
|
|
return c1.radius != c2.radius || c1.length != c2.length || c1.tileLength != c2.tileLength;
|
||
|
|
}
|
||
|
|
public void AssignFrom(GravityRayConfig other){
|
||
|
|
radius = other.radius;
|
||
|
|
length = other.length;
|
||
|
|
tileLength = other.tileLength;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
[ExecuteInEditMode]
|
||
|
|
public class GravityRayBody : MonoBehaviour {
|
||
|
|
public GravityRayConfig config;
|
||
|
|
private GravityRayConfig lastConfig = new GravityRayConfig();
|
||
|
|
private const string rayObjectName = "Beam";
|
||
|
|
public Material beamMaterial;
|
||
|
|
GameObject ray = null;
|
||
|
|
List<GameObject> capturedObjects = new List<GameObject>();
|
||
|
|
public float centeringForce = 0.5f;
|
||
|
|
public float dragForce = 0.5f;
|
||
|
|
|
||
|
|
// Use this for initialization
|
||
|
|
void Start () {
|
||
|
|
RebuildRay ();
|
||
|
|
lastConfig = config;
|
||
|
|
}
|
||
|
|
|
||
|
|
void RebuildRay(){
|
||
|
|
lastConfig.AssignFrom (config);
|
||
|
|
|
||
|
|
if (ray == null) {
|
||
|
|
ray = AdvancedUtils.FindChild(gameObject, rayObjectName);
|
||
|
|
}
|
||
|
|
if (ray == null) {
|
||
|
|
ray = AdvancedUtils.CreateMeshObject(rayObjectName);
|
||
|
|
ray.transform.parent = transform;
|
||
|
|
ray.transform.localPosition = Vector3.zero;
|
||
|
|
ray.transform.localRotation = Quaternion.identity;
|
||
|
|
ray.transform.localScale = Vector3.one;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
CapsuleCollider c = gameObject.GetComponent<CapsuleCollider> ();
|
||
|
|
if (c == null) {
|
||
|
|
c = gameObject.AddComponent<CapsuleCollider>();
|
||
|
|
}
|
||
|
|
|
||
|
|
c.center = new Vector3 (0, config.length * 0.5f, 0);
|
||
|
|
c.radius = config.radius;
|
||
|
|
c.height = config.length;
|
||
|
|
c.direction = 1;
|
||
|
|
c.isTrigger = true;
|
||
|
|
|
||
|
|
var mf = ray.GetComponent<MeshFilter> ();
|
||
|
|
var m = mf.sharedMesh;
|
||
|
|
|
||
|
|
|
||
|
|
Vector3[] vertices;
|
||
|
|
Vector3[] normals;
|
||
|
|
int[] indices;
|
||
|
|
Vector2[] uvs;
|
||
|
|
AdvancedUtils.GenerateCylinder (config.radius, config.length, 33, 1,2, config.length / config.tileLength, out vertices, out indices, out uvs, out normals);
|
||
|
|
|
||
|
|
m.vertices = vertices;
|
||
|
|
m.SetIndices (indices, MeshTopology.Triangles, 0);
|
||
|
|
m.normals = normals;
|
||
|
|
m.uv = uvs;
|
||
|
|
m.RecalculateBounds ();
|
||
|
|
ray.renderer.sharedMaterial = beamMaterial;
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
// Update is called once per frame
|
||
|
|
void FixedUpdate () {
|
||
|
|
if (ray != null) {
|
||
|
|
ray.transform.Rotate (Vector3.up, Time.deltaTime * -90.0f);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(lastConfig != config){
|
||
|
|
RebuildRay();
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (var obj in capturedObjects) {
|
||
|
|
Vector3 a;
|
||
|
|
Vector3 b;
|
||
|
|
|
||
|
|
GetCylinderPoints(out a, out b);
|
||
|
|
|
||
|
|
|
||
|
|
Vector3 n = (b - a).normalized;
|
||
|
|
Vector3 p = AdvancedMath.LineNearestPoint(a, b, obj.transform.position);
|
||
|
|
Vector3 centeringDir = (p - obj.transform.position).normalized;
|
||
|
|
|
||
|
|
|
||
|
|
//Debug.Log(centeringDir);
|
||
|
|
obj.rigidbody.velocity += centeringDir * centeringForce * Time.deltaTime;
|
||
|
|
|
||
|
|
float forwardSpeed = Vector3.Dot(n, obj.rigidbody.velocity);
|
||
|
|
float diff = dragForce - forwardSpeed;
|
||
|
|
obj.rigidbody.velocity += n * dragForce * Time.deltaTime * 0.9f * diff;
|
||
|
|
|
||
|
|
//obj.rigidbody.velocity =obj.rigidbody.velocity * 0.9f * Time.deltaTime + centeringDir * centeringForce * Time.deltaTime + n * dragForce * Time.deltaTime;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void GetCylinderPoints(out Vector3 a, out Vector3 b){
|
||
|
|
a = ray.transform.position;
|
||
|
|
b = ray.transform.position + ray.transform.up * config.length;
|
||
|
|
}
|
||
|
|
|
||
|
|
void OnTriggerEnter(Collider other){
|
||
|
|
if (other.rigidbody!= null && !other.rigidbody.isKinematic && !capturedObjects.Contains (other.gameObject)) {
|
||
|
|
capturedObjects.Add(other.gameObject);
|
||
|
|
other.rigidbody.useGravity = false;
|
||
|
|
other.rigidbody.velocity = Vector3.zero;
|
||
|
|
Debug.Log("Beam captured object: " + other.name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void OnTriggerExit(Collider other){
|
||
|
|
if (capturedObjects.Contains (other.gameObject)) {
|
||
|
|
capturedObjects.Remove(other.gameObject);
|
||
|
|
other.rigidbody.useGravity = true;
|
||
|
|
Debug.Log("Beam lost object: " + other.name);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
void OnDrawGizmos(){
|
||
|
|
if(lastConfig != config){
|
||
|
|
RebuildRay();
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ray != null){
|
||
|
|
Vector3 a;
|
||
|
|
Vector3 b;
|
||
|
|
|
||
|
|
GetCylinderPoints(out a, out b);
|
||
|
|
Gizmos.DrawWireSphere(a, 0.2f);
|
||
|
|
Gizmos.DrawWireSphere(b, 0.2f);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|