Need a unique gift idea?
A Pastebin account makes a great Christmas gift
SHARE
TWEET

GravityObject.cs

mvaganov May 15th, 2017 (edited) 519 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4. /// <summary>Pull a PlayerControl (https://pastebin.com/9M9qyBmP) GameObject toward a Collider.
  5. /// Will work with a MeshCollider, but a SphereCollider or BoxCollider is optimal
  6. /// Latest version at: https://pastebin.com/71fHgXaA</summary>
  7. /// <description>MIT License - TL;DR - This code is free, don't bother me about it!</description>
  8. /// <author email="mvaganov@hotmail.com">Michael Vaganov</author>
  9. public class GravityObject : GravitySource {
  10.     #region public API
  11.     [Tooltip("If false, gravity will be based on the transform.position of this object, not it's collider")]
  12.     public bool useColliderGravity = true;
  13.  
  14.     public override Vector3 CalculateGravityDirectionFrom(Vector3 point) {
  15.         if(!useColliderGravity) { return (transform.position - point).normalized; }
  16.         Vector3 dir = Vector3.zero;
  17.         switch(colliderType) {
  18.         case ColliderType.box: {
  19.                 Vector3 p = NearestPointToBox(myCollider as BoxCollider, point);
  20.                 Vector3 delta = p - point;
  21.                 dir = delta.normalized;
  22.             }
  23.             break;
  24.         case ColliderType.mesh: {
  25.                 Vector3 normal;
  26.                 Vector3 p = nearestPointOnMeshCalculationObject.NearestPointTo(point, out normal);
  27.                 dir = (p - point).normalized;
  28.             }
  29.             break;
  30.         case ColliderType.sphere: {
  31.                 SphereCollider sc = myCollider as SphereCollider;
  32.                 Vector3 p = transform.position + sc.center;
  33.                 dir = (p - point).normalized;
  34.             }
  35.             break;
  36.         default:
  37.             dir = (transform.position - point).normalized;
  38.             break;
  39.         }
  40.         return dir;
  41.     }
  42.     public static Vector3 NearestPointToBox(BoxCollider box, Vector3 point) {
  43.         Transform t = box.transform;
  44.         Quaternion rot = t.rotation;
  45.         Vector3 delta = point - t.position;
  46.         Vector3 rotatedPoint = (Quaternion.Inverse(rot) * delta) + t.position;
  47.         t.rotation = Quaternion.identity;
  48.         Vector3 nearestPoint = box.ClosestPointOnBounds(rotatedPoint);
  49.         t.rotation = rot;
  50.         delta = nearestPoint - t.position;
  51.         delta = rot * delta;
  52.         nearestPoint = t.position + delta;
  53.         return nearestPoint;
  54.     }
  55.     #endregion
  56.     #region Calculate near-points
  57.     private enum ColliderType { none, mesh, box, sphere };
  58.     private ColliderType colliderType = ColliderType.none;
  59.     private Collider myCollider;
  60.     NearestPointOnMeshCalculationObject nearestPointOnMeshCalculationObject = null;
  61.  
  62.     public class NearestPointOnMeshCalculationObject {
  63.         Mesh mesh;
  64.         Vector3[] verts;
  65.         Vector3[] norms;
  66.         VertTriList vt;
  67.         KDTree kd;
  68.         Transform transform;
  69.  
  70.         public NearestPointOnMeshCalculationObject(GameObject go) {
  71.             transform = go.transform;
  72.             mesh = go.GetComponent<MeshFilter>().mesh;
  73.             verts = mesh.vertices;
  74.             norms = mesh.normals;
  75.             vt = new VertTriList(mesh);
  76.             kd = KDTree.MakeFromPoints(verts);
  77.         }
  78.         public Vector3 NearestVertexTo(Vector3 point) {
  79.             // convert point to local space
  80.             point = transform.InverseTransformPoint(point);
  81.             float minDistanceSqr = Mathf.Infinity;
  82.             Vector3 nearestVertex = Vector3.zero;
  83.             // scan all vertices to find nearest
  84.             foreach(Vector3 vertex in verts) {
  85.                 Vector3 diff = point-vertex;
  86.                 float distSqr = diff.sqrMagnitude;
  87.                 if(distSqr < minDistanceSqr) {
  88.                     minDistanceSqr = distSqr;
  89.                     nearestVertex = vertex;
  90.                 }
  91.             }
  92.             // convert nearest vertex back to world space
  93.             return transform.TransformPoint(nearestVertex);
  94.         }
  95.         public Vector3 NearestPointTo(Vector3 point, out Vector3 ptNormal) {
  96.             Vector3 objSpacePt = transform.InverseTransformPoint(point);
  97.             Vector3 meshPt = NearestPointOnMesh(objSpacePt, verts, kd, mesh.triangles, vt, out ptNormal);
  98.             Vector3 closest = transform.TransformPoint(meshPt);
  99.             ptNormal = transform.TransformVector(ptNormal).normalized;
  100.             return closest;
  101.         }
  102.         public Vector3 NearestPointTo(Vector3 point) {
  103.             Vector3 objSpacePt = transform.InverseTransformPoint(point);
  104.             Vector3 meshPt = NearestPointOnMesh(objSpacePt, verts, mesh.triangles, vt);
  105.             Vector3 closest = transform.TransformPoint(meshPt);
  106.             return closest;
  107.         }
  108.         public static float GetDistPointToLine(Vector3 origin, Vector3 direction, Vector3 point) {
  109.             Vector3 point2origin = origin - point;
  110.             Vector3 point2closestPointOnLine = point2origin - Vector3.Dot(point2origin, direction) * direction;
  111.             return point2closestPointOnLine.magnitude;
  112.         }
  113.         Vector3 NearestPointOnMesh(Vector3 pt, Vector3[] verts, KDTree vertProx, int[] tri, VertTriList vt, out Vector3 pointNormal) {
  114.             //  find nearest vertex (point must be on triangle useing this vertex if the mesh is convex)
  115.             int nearest = vertProx.FindNearest(pt);
  116.             pointNormal = Vector3.zero;
  117.             //  Get the list of triangles in which the nearest vert "participates".
  118.             int[] nearTris = vt[nearest];
  119.             Vector3 nearestPt = Vector3.zero;
  120.             float nearestSqDist = float.PositiveInfinity;
  121.             TriangleSection ts;
  122.             for(int i = 0; i < nearTris.Length; i++) {
  123.                 int triOff = nearTris[i] * 3;
  124.                 Vector3 a = verts[tri[triOff]], b = verts[tri[triOff + 1]], c = verts[tri[triOff + 2]];
  125.                 Vector3 possNearestPt = NearestPointOnTri(pt, a, b, c, out ts);
  126.                 float possNearestSqDist = (pt - possNearestPt).sqrMagnitude;
  127.                 if(possNearestSqDist < nearestSqDist) {
  128.                     nearestPt = possNearestPt;
  129.                     nearestSqDist = possNearestSqDist;
  130.                     switch(ts) {
  131.                     case TriangleSection.side_ab: {
  132.                             Vector3 norm1 = norms[tri[triOff+0]], norm2 = norms[tri[triOff+1]];
  133.                             pointNormal = (norm1+norm2)/2;
  134.                         }
  135.                         break;
  136.                     case TriangleSection.side_bc: {
  137.                             Vector3 norm1 = norms[tri[triOff+1]], norm2 = norms[tri[triOff+2]];
  138.                             pointNormal = (norm1+norm2)/2;
  139.                         }
  140.                         break;
  141.                     case TriangleSection.side_ca: {
  142.                             Vector3 norm1 = norms[tri[triOff+2]], norm2 = norms[tri[triOff+0]];
  143.                             pointNormal = (norm1+norm2)/2;
  144.                         }
  145.                         break;
  146.                     case TriangleSection.surface: {
  147.                             Vector3 AB = b - a, AC = c - a;
  148.                             pointNormal = Vector3.Normalize(Vector3.Cross(AB, AC));
  149.                         }
  150.                         break;
  151.                     }
  152.                 }
  153.             }
  154.             return nearestPt;
  155.         }
  156.         /// <summary>easier if we don't need to get the normal!</summary>
  157.         Vector3 NearestPointOnMesh(Vector3 pt, Vector3[] verts, int[] tri, VertTriList vt) {
  158.             //  find nearest vertex (point must be on triangle useing this vertex if the mesh is convex)
  159.             int nearest = -1;
  160.             float nearestSqDist = float.PositiveInfinity;
  161.             for(int i = 0; i < verts.Length; i++) {
  162.                 float sqDist = (verts[i] - pt).sqrMagnitude;
  163.                 if(sqDist < nearestSqDist) {
  164.                     nearest = i;
  165.                     nearestSqDist = sqDist;
  166.                 }
  167.             }
  168.             //  Get the list of triangles in which the nearest vert "participates".
  169.             int[] nearTris = vt[nearest];
  170.             Vector3 nearestPt = Vector3.zero;
  171.             nearestSqDist = float.PositiveInfinity;
  172.             TriangleSection ts;
  173.             for(int i = 0; i < nearTris.Length; i++) {
  174.                 int triOff = nearTris[i] * 3;
  175.                 Vector3 a = verts[tri[triOff]];
  176.                 Vector3 b = verts[tri[triOff + 1]];
  177.                 Vector3 c = verts[tri[triOff + 2]];
  178.                 Vector3 possNearestPt = NearestPointOnTri(pt, a, b, c, out ts);
  179.                 float possNearestSqDist = (pt - possNearestPt).sqrMagnitude;
  180.                 if(possNearestSqDist < nearestSqDist) {
  181.                     nearestPt = possNearestPt;
  182.                     nearestSqDist = possNearestSqDist;
  183.                 }
  184.             }
  185.             return nearestPt;
  186.         }
  187.  
  188.         public enum TriangleSection { unknown, surface, side_ab, side_bc, side_ca };
  189.         /// <param name="ptNormal">Point normal. If on the triangle surface, returns the surface normal</param>
  190.         public Vector3 NearestPointOnTri(Vector3 pt, Vector3 a, Vector3 b, Vector3 c, out TriangleSection pointDetail) {
  191.             pointDetail = TriangleSection.unknown;
  192.             Vector3 edge1 = b - a;
  193.             Vector3 edge2 = c - a;
  194.             Vector3 edge3 = c - b;
  195.             float edge1Len = edge1.magnitude;
  196.             float edge2Len = edge2.magnitude;
  197.             float edge3Len = edge3.magnitude;
  198.             Vector3 ptLineA = pt - a;
  199.             Vector3 ptLineB = pt - b;
  200.             Vector3 ptLineC = pt - c;
  201.             Vector3 xAxis = edge1 / edge1Len;
  202.             Vector3 zAxis = Vector3.Cross(edge1, edge2).normalized;
  203.             Vector3 yAxis = Vector3.Cross(zAxis, xAxis);
  204.             Vector3 edge1Cross = Vector3.Cross(edge1, ptLineA);
  205.             Vector3 edge2Cross = Vector3.Cross(edge2, -ptLineC);
  206.             Vector3 edge3Cross = Vector3.Cross(edge3, ptLineB);
  207.             bool edge1On = Vector3.Dot(edge1Cross, zAxis) > 0f;
  208.             bool edge2On = Vector3.Dot(edge2Cross, zAxis) > 0f;
  209.             bool edge3On = Vector3.Dot(edge3Cross, zAxis) > 0f;
  210.             //  If the point is inside the triangle then return its coordinate.
  211.             if(edge1On && edge2On && edge3On) {
  212.                 pointDetail = TriangleSection.surface;
  213.                 float xExtent = Vector3.Dot(ptLineA, xAxis);
  214.                 float yExtent = Vector3.Dot(ptLineA, yAxis);
  215.                 return a + xAxis * xExtent + yAxis * yExtent;
  216.             }
  217.             //  Otherwise, the nearest point is somewhere along one of the edges.
  218.             Vector3 edge1Norm = xAxis;
  219.             Vector3 edge2Norm = edge2.normalized;
  220.             Vector3 edge3Norm = edge3.normalized;
  221.             float edge1Ext = Mathf.Clamp(Vector3.Dot(edge1Norm, ptLineA), 0f, edge1Len);
  222.             float edge2Ext = Mathf.Clamp(Vector3.Dot(edge2Norm, ptLineA), 0f, edge2Len);
  223.             float edge3Ext = Mathf.Clamp(Vector3.Dot(edge3Norm, ptLineB), 0f, edge3Len);
  224.             Vector3 edge1Pt = a + edge1Ext * edge1Norm;
  225.             Vector3 edge2Pt = a + edge2Ext * edge2Norm;
  226.             Vector3 edge3Pt = b + edge3Ext * edge3Norm;
  227.             float sqDist1 = (pt - edge1Pt).sqrMagnitude;
  228.             float sqDist2 = (pt - edge2Pt).sqrMagnitude;
  229.             float sqDist3 = (pt - edge3Pt).sqrMagnitude;
  230.             if(sqDist1 < sqDist2) {
  231.                 if(sqDist1 < sqDist3) {
  232.                     pointDetail = TriangleSection.side_ab;
  233.                     return edge1Pt;
  234.                 } else {
  235.                     pointDetail = TriangleSection.side_bc;
  236.                     return edge3Pt;
  237.                 }
  238.             } else if(sqDist2 < sqDist3) {
  239.                 pointDetail = TriangleSection.side_ca;
  240.                 return edge2Pt;
  241.             } else {
  242.                 pointDetail = TriangleSection.side_bc;
  243.                 return edge3Pt;
  244.             }
  245.         }
  246.     }
  247.     #endregion // Calculate near-points
  248.     #region VertTriList
  249.     //  lookup table for a mesh identifying which vertexes reference which triangles
  250.     public class VertTriList {
  251.         public int[][] list;
  252.         public int[] aliases;
  253.  
  254.         //  Indexable - use "vertTri[i]" to get the list of triangles for vertex i.
  255.         public int[] this[int index] {
  256.             get { return list[aliases[index]]; }
  257.         }
  258.         public VertTriList(int[] tri, Vector3[] verts) { Init(tri, verts); }
  259.         public VertTriList(Mesh mesh) { Init(mesh.triangles, mesh.vertices); }
  260.         public void Init(int[] tri, Vector3[] verts) {
  261.             int numVerts = verts.Length;
  262.             // find duplicate verts, since many meshes are created with dups for rendering purposes
  263.             List<int>[] duplicates = new List<int>[verts.Length];
  264.             // create an alias table, so duplicate vertexes can point to the same triangles
  265.             aliases = new int[verts.Length];
  266.             for(int i = 0; i < duplicates.Length; ++i) { duplicates[i] = new List<int>(); }
  267.             for(int i = 0; i < verts.Length; ++i) {
  268.                 for(int j = i + 1; j < verts.Length; ++j) {
  269.                     if(verts[i] == verts[j]) {
  270.                         if(!duplicates[i].Contains(j)) duplicates[i].Add(j);
  271.                         if(!duplicates[j].Contains(i)) duplicates[j].Add(i);
  272.                     }
  273.                 }
  274.             }
  275.             // sort duplicates, so the earliest verts are first, and add that as an aliases
  276.             for(int i = 0; i < duplicates.Length; ++i) {
  277.                 duplicates[i].Sort();
  278.                 aliases[i] = (duplicates[i].Count>0) ? Mathf.Min(i, duplicates[i][0]) : i;
  279.             }
  280.             // go through the triangles, keeping a count of how many times each vert is used
  281.             int[] counts = new int[numVerts];
  282.             for(int i = 0; i < tri.Length; i++) { counts[tri[i]]++; }
  283.             // merge aliases into earliest counts
  284.             for(int i = 0; i < aliases.Length; ++i) {
  285.                 if(aliases[i] < i) {
  286.                     int earliestIndex = aliases[i];
  287.                     counts[earliestIndex] += counts[i];
  288.                     counts[i] = 0;
  289.                 }
  290.             }
  291.             // initialise empty jagged array with appropriate number of elements for each vert.
  292.             list = new int[numVerts][];
  293.             for(int i = 0; i < counts.Length; i++) {
  294.                 if(counts[i] > 0) { list[i] = new int[counts[i]]; }
  295.             }
  296.             // assign appropriate triangle number each time given vert is encountered in triangles list
  297.             for(int i = 0; i < tri.Length; i++) {
  298.                 int vert = tri[i];
  299.                 vert = aliases[vert]; // take aliases into account
  300.                 list[vert][--counts[vert]] = i / 3;
  301.             }
  302.         }
  303.     }
  304.     #endregion
  305.     #region KDTree
  306.     // KDTree.cs - A Stark, September 2009.
  307.     //  This class implements a data structure that stores a list of points in space.
  308.     //  A common task in game programming is to take a supplied point and discover which
  309.     //  of a stored set of points is nearest to it. For example, in path-plotting, it is often
  310.     //  useful to know which waypoint is nearest to the player's current
  311.     //  position. The kd-tree allows this "nearest neighbour" search to be carried out quickly,
  312.     //  or at least much more quickly than a simple linear search through the list.
  313.     //  At present, the class only allows for construction (using the MakeFromPoints static method)
  314.     //  and nearest-neighbour searching (using FindNearest). More exotic kd-trees are possible, and
  315.     //  this class may be extended in the future if there seems to be a need.
  316.     //  nearest-neighbour search returns integer index
  317.     public class KDTree {
  318.         public KDTree[] lr;
  319.         public Vector3 pivot;
  320.         public int pivotIndex, axis;
  321.         //  faster if 2, for X,Y search
  322.         const int numDims = 3;
  323.  
  324.         public KDTree() { lr = new KDTree[2]; }
  325.         //  Make a new tree from a list of points.
  326.         public static KDTree MakeFromPoints(params Vector3[] points) {
  327.             int[] indices = Iota(points.Length);
  328.             return MakeFromPointsInner(0, 0, points.Length - 1, points, indices);
  329.         }
  330.         //  Recursively build a tree by separating points at plane boundaries.
  331.         static KDTree MakeFromPointsInner(int depth, int stIndex, int enIndex, Vector3[] points, int[] inds) {
  332.             KDTree root = new KDTree();
  333.             root.axis = depth % numDims;
  334.             int splitPoint = FindPivotIndex(points, inds, stIndex, enIndex, root.axis);
  335.             root.pivotIndex = inds[splitPoint];
  336.             root.pivot = points[root.pivotIndex];
  337.             int leftEndIndex = splitPoint - 1;
  338.             if(leftEndIndex >= stIndex) {
  339.                 root.lr[0] = MakeFromPointsInner(depth + 1, stIndex, leftEndIndex, points, inds);
  340.             }
  341.             int rightStartIndex = splitPoint + 1;
  342.             if(rightStartIndex <= enIndex) {
  343.                 root.lr[1] = MakeFromPointsInner(depth + 1, rightStartIndex, enIndex, points, inds);
  344.             }
  345.             return root;
  346.         }
  347.         static void SwapElements(int[] arr, int a, int b) {
  348.             int temp = arr[a];
  349.             arr[a] = arr[b];
  350.             arr[b] = temp;
  351.         }
  352.         //  Simple "median of three" heuristic to find a reasonable splitting plane.
  353.         static int FindSplitPoint(Vector3[] points, int[] inds, int stIndex, int enIndex, int axis) {
  354.             float a = points[inds[stIndex]][axis];
  355.             float b = points[inds[enIndex]][axis];
  356.             int midIndex = (stIndex + enIndex) / 2;
  357.             float m = points[inds[midIndex]][axis];
  358.             if(a > b) {
  359.                 if(m > a) { return stIndex; }
  360.                 if(b > m) { return enIndex; }
  361.                 return midIndex;
  362.             } else {
  363.                 if(a > m) { return stIndex; }
  364.                 if(m > b) { return enIndex; }
  365.                 return midIndex;
  366.             }
  367.         }
  368.         //  a new pivot index from range by splitting points falling at either side of its plane.
  369.         public static int FindPivotIndex(Vector3[] points, int[] inds, int stIndex, int enIndex, int axis) {
  370.             int splitPoint = FindSplitPoint(points, inds, stIndex, enIndex, axis);
  371.             // int splitPoint = Random.Range(stIndex, enIndex);
  372.             Vector3 pivot = points[inds[splitPoint]];
  373.             SwapElements(inds, stIndex, splitPoint);
  374.             int currPt = stIndex + 1;
  375.             int endPt = enIndex;
  376.             while(currPt <= endPt) {
  377.                 Vector3 curr = points[inds[currPt]];
  378.                 if((curr[axis] > pivot[axis])) {
  379.                     SwapElements(inds, currPt, endPt);
  380.                     endPt--;
  381.                 } else {
  382.                     SwapElements(inds, currPt - 1, currPt);
  383.                     currPt++;
  384.                 }
  385.             }
  386.             return currPt - 1;
  387.         }
  388.         public static int[] Iota(int num) {
  389.             int[] result = new int[num];
  390.             for(int i = 0; i < num; i++) { result[i] = i; }
  391.             return result;
  392.         }
  393.         //  Find the nearest point in the set to the supplied point.
  394.         public int FindNearest(Vector3 pt) {
  395.             float bestSqDist = float.PositiveInfinity;
  396.             int bestIndex = -1;
  397.             Search(pt, ref bestSqDist, ref bestIndex);
  398.             return bestIndex;
  399.         }
  400.         //  Recursively search the tree.
  401.         void Search(Vector3 pt, ref float bestSqSoFar, ref int bestIndex) {
  402.             float mySqDist = (pivot - pt).sqrMagnitude;
  403.             if(mySqDist < bestSqSoFar) {
  404.                 bestSqSoFar = mySqDist;
  405.                 bestIndex = pivotIndex;
  406.             }
  407.             float planeDist = pt[axis] - pivot[axis]; //DistFromSplitPlane(pt, pivot, axis);
  408.             int selector = planeDist <= 0 ? 0 : 1;
  409.             if(lr[selector] != null) {
  410.                 lr[selector].Search(pt, ref bestSqSoFar, ref bestIndex);
  411.             }
  412.             selector = (selector + 1) % 2;
  413.             float sqPlaneDist = planeDist * planeDist;
  414.             if((lr[selector] != null) && (bestSqSoFar > sqPlaneDist)) {
  415.                 lr[selector].Search(pt, ref bestSqSoFar, ref bestIndex);
  416.             }
  417.         }
  418.         //  Get a point's distance from an axis-aligned plane.
  419.         float DistFromSplitPlane(Vector3 pt, Vector3 planePt, int axis) {
  420.             return pt[axis] - planePt[axis];
  421.         }
  422.         //  Simple output of tree structure - mainly useful for getting a rough
  423.         //  idea of how deep the tree is (and therefore how well the splitting
  424.         //  heuristic is performing).
  425.         public string Dump(int level) {
  426.             string result = pivotIndex.ToString().PadLeft(level) + "\n";
  427.             if(lr[0] != null) { result += lr[0].Dump(level + 2); }
  428.             if(lr[1] != null) { result += lr[1].Dump(level + 2); }
  429.             return result;
  430.         }
  431.     }
  432.     #endregion
  433.     #region MonoBehaviour
  434.     void Start() {
  435.         myCollider = GetComponent<Collider>();
  436.         if(myCollider is BoxCollider) { colliderType = ColliderType.box; } else if(myCollider is SphereCollider) { colliderType = ColliderType.sphere; } else if(myCollider is MeshCollider) {
  437.             nearestPointOnMeshCalculationObject = new NearestPointOnMeshCalculationObject(gameObject);
  438.             colliderType = ColliderType.mesh;
  439.         }
  440.     }
  441.     #endregion // MonoBehaviour
  442. }
  443.  
  444. #region Base GravitySource
  445. public class GravitySource : MonoBehaviour {
  446.     [Tooltip("apply gravity if player hits this collider")]
  447.     public bool entangleOnCollision = true;
  448.     [Tooltip("apply gravity if player enters this collider trigger")]
  449.     public bool entangleOnTrigger = true;
  450.     [Tooltip("apply gravity power on player")]
  451.     public bool forceGravitypower = false;
  452.     [Tooltip("How much acceleration to apply to the PlayerControl, if gravity power is forced")]
  453.     public float power = 9.81f;
  454.  
  455.     public virtual Vector3 CalculateGravityDirectionFrom(Vector3 point) {
  456.         Vector3 delta = transform.position - point;
  457.         return delta.normalized;
  458.     }
  459.     public void OnCollisionEnter(Collision col) {
  460.         if(!enabled) return;
  461.         if(entangleOnCollision) { EntanglePlayer(col.gameObject.GetComponent<PlayerControl>()); }
  462.     }
  463.     public void OnTriggerEnter(Collider col) {
  464.         if(entangleOnTrigger) { EntanglePlayer(col.GetComponent<PlayerControl>()); }
  465.     }
  466.     public void EntanglePlayer(PlayerControl p) {
  467.         if(p && p.gravityApplication != PlayerControl.GravityState.none) {
  468.             GravityPuller gp = p.gameObject.GetComponent<GravityPuller>();
  469.             if(!gp) { gp = p.gameObject.AddComponent<GravityPuller>(); }
  470.             if(gp.gravitySource != this) { gp.Init(this); } else { gp.Refresh(); }
  471.         }
  472.     }
  473. }
  474. #endregion // Base GravitySource
  475.  
  476. #region Gravity Puller (additional script for PlayerControl)
  477. public class GravityPuller : MonoBehaviour {
  478.     public GravitySource gravitySource;
  479.     private GravitySource lastGravitySource;
  480.     private float timeOfLastSource;
  481.     private PlayerControl p;
  482.     [Tooltip("If true, will re-orient velocity to match any changes to gravity. useful for making tight video-gamey motion on small gravity wells.")]
  483.     public bool velocityFollowsGravity = true;
  484.  
  485.     public void Init(GravitySource gs) {
  486.         if(gs != this && (gs != lastGravitySource || Time.time > timeOfLastSource+1)) {
  487.             timeOfLastSource = Time.time;
  488.             lastGravitySource = gravitySource;
  489.             gravitySource = gs;
  490.             p = GetComponent<PlayerControl>();
  491.             Refresh();
  492.         }
  493.     }
  494.     public void Refresh() {
  495.         Vector3 nextDir = gravitySource.CalculateGravityDirectionFrom(transform.position);
  496.         Rigidbody rb = p.rb;
  497.         if(velocityFollowsGravity && nextDir != p.gravity.dir && rb != null) {
  498.             Vector3 localVelocity = p.transform.InverseTransformDirection(rb.velocity);
  499.             float angle = Vector3.Angle(nextDir, p.gravity.dir);
  500.             Vector3 axis = Vector3.Cross(p.gravity.dir, nextDir).normalized;
  501.             Quaternion q = Quaternion.AngleAxis(angle, axis);
  502.             p.transform.rotation = Quaternion.LookRotation(q*transform.forward, q*transform.up);
  503.             rb.velocity = p.transform.TransformDirection (localVelocity);
  504.         }
  505.         p.gravity.dir = nextDir;
  506.         if (gravitySource.forceGravitypower) {
  507.             p.gravity.power = gravitySource.power;
  508.         }
  509.     }
  510.     void FixedUpdate() { Refresh(); }
  511.     public Vector3 PullAsIfFrom(Vector3 alternateLocation) {
  512.         return gravitySource.CalculateGravityDirectionFrom(alternateLocation);
  513.     }
  514. }
  515. #endregion // Gravity Puller (additional script for PlayerControl)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top