Files
2025-05-13 05:18:03 +03:00

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);
}
}
}